mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: allow passing of comparator to sortToc methods
- this increases the flexibility of the interface
- Add stringOps 'natural' string sorting comparison.
Digits are sorted in their natural order, which means that
(file10.txt file05.txt file2.txt)
are sorted as
(file2.txt file05.txt file10.txt)
STYLE: consistent naming of template parameters for comparators
- Compare for normal binary predicates
- ListComparePredicate for list compare binary predicates
This commit is contained in:
@ -3,7 +3,7 @@
|
|||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -27,6 +27,8 @@ Description
|
|||||||
|
|
||||||
#include "SortableList.H"
|
#include "SortableList.H"
|
||||||
#include "ListOps.H"
|
#include "ListOps.H"
|
||||||
|
#include "HashSet.H"
|
||||||
|
#include "stringOps.H"
|
||||||
|
|
||||||
using namespace Foam;
|
using namespace Foam;
|
||||||
|
|
||||||
@ -175,6 +177,142 @@ int main(int argc, char *argv[])
|
|||||||
Info<< "flat = " << values << endl;
|
Info<< "flat = " << values << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort strings
|
||||||
|
{
|
||||||
|
HashSet<string> hashed
|
||||||
|
{
|
||||||
|
"2.txt",
|
||||||
|
"05.txt",
|
||||||
|
"15.txt",
|
||||||
|
"other.bak04",
|
||||||
|
"other.bak1",
|
||||||
|
"file1.txt",
|
||||||
|
"file10.txt",
|
||||||
|
"file2.txt",
|
||||||
|
"file100.txt",
|
||||||
|
"file.txt",
|
||||||
|
"file011.txt",
|
||||||
|
"file15.txt",
|
||||||
|
"file0009.txt",
|
||||||
|
"abcd.txt",
|
||||||
|
|
||||||
|
// Some regular processor directories
|
||||||
|
"processor0",
|
||||||
|
"processor1",
|
||||||
|
"processor9",
|
||||||
|
"processor10",
|
||||||
|
"processor11",
|
||||||
|
"processor20",
|
||||||
|
"processor21",
|
||||||
|
"processor35",
|
||||||
|
"processors",
|
||||||
|
|
||||||
|
// Aggregate processor directories
|
||||||
|
"processor0-31",
|
||||||
|
"processor32-63",
|
||||||
|
"processor64-95",
|
||||||
|
"processor96-127",
|
||||||
|
"processor128-159",
|
||||||
|
"processor160-191",
|
||||||
|
"processor192-223",
|
||||||
|
"processor224-255",
|
||||||
|
};
|
||||||
|
|
||||||
|
Info<< nl << "Test string sorting" << nl << endl;
|
||||||
|
|
||||||
|
// Using hash toc
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
Info<< "Unsorted" << hashed.toc() << endl;
|
||||||
|
Info<< "sortedToc" << hashed.sortedToc() << endl;
|
||||||
|
Info<< "natural"
|
||||||
|
<< hashed.sortedToc(stringOps::natural_sort()) << endl;
|
||||||
|
|
||||||
|
Info<< "reverse natural"
|
||||||
|
<< hashed.sortedToc(stringOps::natural_sort::reverse())
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal list
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
labelList order;
|
||||||
|
|
||||||
|
List<string> strings(hashed.toc());
|
||||||
|
Info<< nl << "stringList:" << strings << endl;
|
||||||
|
|
||||||
|
sort(strings);
|
||||||
|
Info<< "normal sort:" << strings << endl;
|
||||||
|
|
||||||
|
shuffle(strings);
|
||||||
|
sort(strings, stringOps::natural_sort());
|
||||||
|
Info<< "natural sort:" << strings << endl;
|
||||||
|
|
||||||
|
shuffle(strings);
|
||||||
|
sort(strings, stringOps::natural_sort::reverse());
|
||||||
|
Info<< "reverse natural:" << strings << endl;
|
||||||
|
|
||||||
|
strings = hashed.toc();
|
||||||
|
|
||||||
|
Info<< nl << "test sorted order" << endl;
|
||||||
|
Info<< nl << "list:" << strings << endl;
|
||||||
|
|
||||||
|
sortedOrder(strings, order);
|
||||||
|
Info<< "sortedOrder:" << flatOutput(order) << endl;
|
||||||
|
|
||||||
|
shuffle(strings);
|
||||||
|
sort(strings, stringOps::natural_sort());
|
||||||
|
Info<< "reverse natural:" << strings << endl;
|
||||||
|
|
||||||
|
shuffle(strings);
|
||||||
|
sort(strings, stringOps::natural_sort::reverse());
|
||||||
|
Info<< "reverse natural:" << strings << endl;
|
||||||
|
|
||||||
|
sortedOrder
|
||||||
|
(
|
||||||
|
strings,
|
||||||
|
order,
|
||||||
|
stringOps::natural_sort::less<string>(strings)
|
||||||
|
);
|
||||||
|
Info<< "natural sortedOrder: " << flatOutput(order) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SortableList
|
||||||
|
if (false)
|
||||||
|
{
|
||||||
|
SortableList<string> sortable;
|
||||||
|
Info<< nl << "Testing sortable list";
|
||||||
|
|
||||||
|
// Assign to ensure list is initially unsorted
|
||||||
|
sortable = hashed.toc();
|
||||||
|
Info<< nl << "input:" << sortable << endl;
|
||||||
|
|
||||||
|
sortable.sort();
|
||||||
|
Info<< nl << "normal:" << sortable << endl;
|
||||||
|
|
||||||
|
// This is still a bother (looks fairly ugly)
|
||||||
|
// so not implemented for now
|
||||||
|
|
||||||
|
/// // Assign to ensure list is initially unsorted
|
||||||
|
/// sortable = hashed.toc();
|
||||||
|
/// sortable.sort
|
||||||
|
/// (
|
||||||
|
/// stringOps::natural_sort::less<string>(sortable)
|
||||||
|
/// );
|
||||||
|
/// Info<< nl << "natural:" << sortable << endl;
|
||||||
|
|
||||||
|
/// // Assign to ensure list is initially unsorted
|
||||||
|
/// sortable = hashed.toc();
|
||||||
|
/// sortable.sort
|
||||||
|
/// (
|
||||||
|
/// stringOps::natural_sort::greater<string>(sortable)
|
||||||
|
/// );
|
||||||
|
/// Info<< nl << "natural:" << sortable << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Info<< "\nEnd\n" << endl;
|
Info<< "\nEnd\n" << endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -114,6 +114,7 @@ $(strings)/wordRe/wordRe.C
|
|||||||
$(strings)/wordRes/wordRes.C
|
$(strings)/wordRes/wordRes.C
|
||||||
$(strings)/lists/hashedWordList.C
|
$(strings)/lists/hashedWordList.C
|
||||||
$(strings)/stringOps/stringOps.C
|
$(strings)/stringOps/stringOps.C
|
||||||
|
$(strings)/stringOps/stringOpsSort.C
|
||||||
$(strings)/parsing/parsing.C
|
$(strings)/parsing/parsing.C
|
||||||
|
|
||||||
ops = primitives/ops
|
ops = primitives/ops
|
||||||
|
|||||||
@ -189,6 +189,17 @@ Foam::wordList Foam::DictionaryBase<IDLListType, T>::sortedToc() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class IDLListType, class T>
|
||||||
|
template<class Compare>
|
||||||
|
Foam::wordList Foam::DictionaryBase<IDLListType, T>::sortedToc
|
||||||
|
(
|
||||||
|
const Compare& comp
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return hashedTs_.sortedToc(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class IDLListType, class T>
|
template<class IDLListType, class T>
|
||||||
void Foam::DictionaryBase<IDLListType, T>::insert(const word& keyword, T* tPtr)
|
void Foam::DictionaryBase<IDLListType, T>::insert(const word& keyword, T* tPtr)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -131,6 +131,10 @@ public:
|
|||||||
//- Return the table of contents as a sorted list
|
//- Return the table of contents as a sorted list
|
||||||
wordList sortedToc() const;
|
wordList sortedToc() const;
|
||||||
|
|
||||||
|
//- Return table of contents sorted using the specified comparator
|
||||||
|
template<class Compare>
|
||||||
|
wordList sortedToc(const Compare& comp) const;
|
||||||
|
|
||||||
|
|
||||||
// Editing
|
// Editing
|
||||||
|
|
||||||
|
|||||||
@ -268,13 +268,27 @@ Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
|
|||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
Foam::List<Key> Foam::HashTable<T, Key, Hash>::sortedToc() const
|
Foam::List<Key> Foam::HashTable<T, Key, Hash>::sortedToc() const
|
||||||
{
|
{
|
||||||
List<Key> keyLst = this->toc();
|
List<Key> keyLst(this->toc());
|
||||||
Foam::sort(keyLst);
|
Foam::sort(keyLst);
|
||||||
|
|
||||||
return keyLst;
|
return keyLst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
template<class Compare>
|
||||||
|
Foam::List<Key> Foam::HashTable<T, Key, Hash>::sortedToc
|
||||||
|
(
|
||||||
|
const Compare& comp
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
List<Key> keyLst(this->toc());
|
||||||
|
Foam::sort(keyLst, comp);
|
||||||
|
|
||||||
|
return keyLst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
template<class UnaryPredicate>
|
template<class UnaryPredicate>
|
||||||
Foam::List<Key> Foam::HashTable<T, Key, Hash>::tocKeys
|
Foam::List<Key> Foam::HashTable<T, Key, Hash>::tocKeys
|
||||||
|
|||||||
@ -347,6 +347,10 @@ public:
|
|||||||
//- Return the table of contents as a sorted list
|
//- Return the table of contents as a sorted list
|
||||||
List<Key> sortedToc() const;
|
List<Key> sortedToc() const;
|
||||||
|
|
||||||
|
//- Return table of contents sorted using the specified comparator
|
||||||
|
template<class Compare>
|
||||||
|
List<Key> sortedToc(const Compare& comp) const;
|
||||||
|
|
||||||
//- Return the sorted table of contents with keys that satisfy
|
//- Return the sorted table of contents with keys that satisfy
|
||||||
// the unary predicate, optionally with inverted logic.
|
// the unary predicate, optionally with inverted logic.
|
||||||
template<class UnaryPredicate>
|
template<class UnaryPredicate>
|
||||||
|
|||||||
@ -110,24 +110,44 @@ void inplaceMapKey(const labelUList& oldToNew, Container& lst);
|
|||||||
template<class T>
|
template<class T>
|
||||||
void sortedOrder(const UList<T>& lst, labelList& order);
|
void sortedOrder(const UList<T>& lst, labelList& order);
|
||||||
|
|
||||||
template<class T, class Cmp>
|
//- Sort using specified list compare predicate
|
||||||
void sortedOrder(const UList<T>& lst, labelList& order, const Cmp& cmp);
|
template<class T, class ListComparePredicate>
|
||||||
|
void sortedOrder
|
||||||
|
(
|
||||||
|
const UList<T>& lst,
|
||||||
|
labelList& order,
|
||||||
|
const ListComparePredicate& comp
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Generate (sorted) indices corresponding to duplicate list values
|
//- Generate (sorted) indices corresponding to duplicate list values
|
||||||
template<class T>
|
template<class T>
|
||||||
void duplicateOrder(const UList<T>& lst, labelList& order);
|
void duplicateOrder(const UList<T>& lst, labelList& order);
|
||||||
|
|
||||||
template<class T, class Cmp>
|
//- Generate (sorted) indices corresponding to duplicate list values
|
||||||
void duplicateOrder(const UList<T>& lst, labelList& order, const Cmp& cmp);
|
// sort using specified list compare predicate
|
||||||
|
template<class T, class ListComparePredicate>
|
||||||
|
void duplicateOrder
|
||||||
|
(
|
||||||
|
const UList<T>& lst,
|
||||||
|
labelList& order,
|
||||||
|
const ListComparePredicate& comp
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Generate (sorted) indices corresponding to unique list values
|
//- Generate (sorted) indices corresponding to unique list values
|
||||||
template<class T>
|
template<class T>
|
||||||
void uniqueOrder(const UList<T>& lst, labelList& order);
|
void uniqueOrder(const UList<T>& lst, labelList& order);
|
||||||
|
|
||||||
template<class T, class Cmp>
|
//- Generate (sorted) indices corresponding to unique list values
|
||||||
void uniqueOrder(const UList<T>& lst, labelList& order, const Cmp& cmp);
|
// sort using specified list compare predicate
|
||||||
|
template<class T, class ListComparePredicate>
|
||||||
|
void uniqueOrder
|
||||||
|
(
|
||||||
|
const UList<T>& lst,
|
||||||
|
labelList& order,
|
||||||
|
const ListComparePredicate& comp
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Inplace sorting and removal of duplicates.
|
//- Inplace sorting and removal of duplicates.
|
||||||
@ -137,8 +157,12 @@ void inplaceUniqueSort(ListType& lst);
|
|||||||
|
|
||||||
//- Inplace sorting and removal of duplicates.
|
//- Inplace sorting and removal of duplicates.
|
||||||
// Do not use FixedList for the input list, since it doesn't resize.
|
// Do not use FixedList for the input list, since it doesn't resize.
|
||||||
template<class ListType, class Cmp>
|
template<class ListType, class ListComparePredicate>
|
||||||
void inplaceUniqueSort(ListType& lst, const Cmp& cmp);
|
void inplaceUniqueSort
|
||||||
|
(
|
||||||
|
ListType& lst,
|
||||||
|
const ListComparePredicate& comp
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Extract elements of List when select is a certain value.
|
//- Extract elements of List when select is a certain value.
|
||||||
|
|||||||
@ -211,27 +211,30 @@ void Foam::sortedOrder
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Cmp>
|
template<class T, class ListComparePredicate>
|
||||||
void Foam::sortedOrder
|
void Foam::sortedOrder
|
||||||
(
|
(
|
||||||
const UList<T>& lst,
|
const UList<T>& lst,
|
||||||
labelList& order,
|
labelList& order,
|
||||||
const Cmp& cmp
|
const ListComparePredicate& comp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
const label len = lst.size();
|
||||||
|
|
||||||
// list lengths must be identical
|
// list lengths must be identical
|
||||||
if (order.size() != lst.size())
|
if (order.size() != len)
|
||||||
{
|
{
|
||||||
// avoid copying any elements, they are overwritten anyhow
|
// Avoid copying any elements, they are overwritten anyhow
|
||||||
order.clear();
|
order.clear();
|
||||||
order.setSize(lst.size());
|
order.setSize(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
forAll(order, elemI)
|
for (label i=0; i<len; ++i)
|
||||||
{
|
{
|
||||||
order[elemI] = elemI;
|
order[i] = i; // identity
|
||||||
}
|
}
|
||||||
Foam::stableSort(order, cmp);
|
|
||||||
|
Foam::stableSort(order, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -246,12 +249,12 @@ void Foam::duplicateOrder
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Cmp>
|
template<class T, class ListComparePredicate>
|
||||||
void Foam::duplicateOrder
|
void Foam::duplicateOrder
|
||||||
(
|
(
|
||||||
const UList<T>& lst,
|
const UList<T>& lst,
|
||||||
labelList& order,
|
labelList& order,
|
||||||
const Cmp& cmp
|
const ListComparePredicate& comp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (lst.size() < 2)
|
if (lst.size() < 2)
|
||||||
@ -260,7 +263,7 @@ void Foam::duplicateOrder
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sortedOrder(lst, order, cmp);
|
sortedOrder(lst, order, comp);
|
||||||
|
|
||||||
const label last = (order.size()-1);
|
const label last = (order.size()-1);
|
||||||
label n = 0;
|
label n = 0;
|
||||||
@ -286,15 +289,15 @@ void Foam::uniqueOrder
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Cmp>
|
template<class T, class ListComparePredicate>
|
||||||
void Foam::uniqueOrder
|
void Foam::uniqueOrder
|
||||||
(
|
(
|
||||||
const UList<T>& lst,
|
const UList<T>& lst,
|
||||||
labelList& order,
|
labelList& order,
|
||||||
const Cmp& cmp
|
const ListComparePredicate& comp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
sortedOrder(lst, order, cmp);
|
sortedOrder(lst, order, comp);
|
||||||
|
|
||||||
if (order.size() > 1)
|
if (order.size() > 1)
|
||||||
{
|
{
|
||||||
@ -324,18 +327,24 @@ void Foam::inplaceUniqueSort(ListType& lst)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ListType, class Cmp>
|
template<class ListType, class ListComparePredicate>
|
||||||
void Foam::inplaceUniqueSort(ListType& lst, const Cmp& cmp)
|
void Foam::inplaceUniqueSort
|
||||||
|
(
|
||||||
|
ListType& lst,
|
||||||
|
const ListComparePredicate& comp
|
||||||
|
)
|
||||||
{
|
{
|
||||||
labelList order;
|
labelList order;
|
||||||
uniqueOrder(lst, order, cmp);
|
uniqueOrder(lst, order, comp);
|
||||||
|
|
||||||
ListType newLst(order.size());
|
const label len = order.size();
|
||||||
newLst.setSize(order.size()); // Consistent sizing (eg, DynamicList)
|
|
||||||
|
|
||||||
forAll(order, elemI)
|
ListType newLst(len);
|
||||||
|
newLst.setSize(len); // Consistent sizing (eg, DynamicList)
|
||||||
|
|
||||||
|
for (label i=0; i<len; ++i)
|
||||||
{
|
{
|
||||||
newLst[elemI] = lst[order[elemI]];
|
newLst[i] = lst[order[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
lst.transfer(newLst);
|
lst.transfer(newLst);
|
||||||
|
|||||||
@ -133,7 +133,7 @@ Foam::List<T>& Foam::SortableList<T>::shrink()
|
|||||||
template<class T>
|
template<class T>
|
||||||
void Foam::SortableList<T>::sort()
|
void Foam::SortableList<T>::sort()
|
||||||
{
|
{
|
||||||
sortedOrder(*this, indices_);
|
Foam::sortedOrder(*this, indices_);
|
||||||
|
|
||||||
List<T> lst(*this, indices_); // Copy with indices for mapping
|
List<T> lst(*this, indices_); // Copy with indices for mapping
|
||||||
List<T>::transfer(lst);
|
List<T>::transfer(lst);
|
||||||
@ -143,7 +143,7 @@ void Foam::SortableList<T>::sort()
|
|||||||
template<class T>
|
template<class T>
|
||||||
void Foam::SortableList<T>::reverseSort()
|
void Foam::SortableList<T>::reverseSort()
|
||||||
{
|
{
|
||||||
sortedOrder(*this, indices_, typename UList<T>::greater(*this));
|
Foam::sortedOrder(*this, indices_, typename UList<T>::greater(*this));
|
||||||
|
|
||||||
List<T> lst(*this, indices_); // Copy with indices for mapping
|
List<T> lst(*this, indices_); // Copy with indices for mapping
|
||||||
List<T>::transfer(lst);
|
List<T>::transfer(lst);
|
||||||
@ -157,6 +157,7 @@ void Foam::SortableList<T>::swap(SortableList<T>& lst)
|
|||||||
indices_.swap(lst.indices_);
|
indices_.swap(lst.indices_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Foam::Xfer<Foam::List<T>> Foam::SortableList<T>::xfer()
|
Foam::Xfer<Foam::List<T>> Foam::SortableList<T>::xfer()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -119,8 +119,8 @@ public:
|
|||||||
//- Clear the indices and return a reference to the underlying List
|
//- Clear the indices and return a reference to the underlying List
|
||||||
List<T>& shrink();
|
List<T>& shrink();
|
||||||
|
|
||||||
//- (stable) sort the list (if changed after construction time)
|
//- (stable) sort the list (if changed after construction time).
|
||||||
// also resizes the indices as required
|
// Resizes the indices as required
|
||||||
void sort();
|
void sort();
|
||||||
|
|
||||||
//- Reverse (stable) sort the list
|
//- Reverse (stable) sort the list
|
||||||
|
|||||||
@ -293,10 +293,10 @@ void Foam::sort(UList<T>& a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Cmp>
|
template<class T, class Compare>
|
||||||
void Foam::sort(UList<T>& a, const Cmp& cmp)
|
void Foam::sort(UList<T>& a, const Compare& comp)
|
||||||
{
|
{
|
||||||
std::sort(a.begin(), a.end(), cmp);
|
std::sort(a.begin(), a.end(), comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -307,10 +307,10 @@ void Foam::stableSort(UList<T>& a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Cmp>
|
template<class T, class Compare>
|
||||||
void Foam::stableSort(UList<T>& a, const Cmp& cmp)
|
void Foam::stableSort(UList<T>& a, const Compare& comp)
|
||||||
{
|
{
|
||||||
std::stable_sort(a.begin(), a.end(), cmp);
|
std::stable_sort(a.begin(), a.end(), comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -139,39 +139,35 @@ public:
|
|||||||
|
|
||||||
// Public classes
|
// Public classes
|
||||||
|
|
||||||
//- Less function class that can be used for sorting
|
//- A list compare binary predicate for normal sort
|
||||||
class less
|
struct less
|
||||||
{
|
{
|
||||||
const UList<T>& values_;
|
const UList<T>& values;
|
||||||
|
|
||||||
public:
|
less(const UList<T>& list)
|
||||||
|
|
||||||
less(const UList<T>& values)
|
|
||||||
:
|
:
|
||||||
values_(values)
|
values(list)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool operator()(const label a, const label b)
|
bool operator()(const label a, const label b) const
|
||||||
{
|
{
|
||||||
return values_[a] < values_[b];
|
return values[a] < values[b];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//- Greater function class that can be used for sorting
|
//- A list compare binary predicate for reverse sort
|
||||||
class greater
|
struct greater
|
||||||
{
|
{
|
||||||
const UList<T>& values_;
|
const UList<T>& values;
|
||||||
|
|
||||||
public:
|
greater(const UList<T>& list)
|
||||||
|
|
||||||
greater(const UList<T>& values)
|
|
||||||
:
|
:
|
||||||
values_(values)
|
values(list)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool operator()(const label a, const label b)
|
bool operator()(const label a, const label b) const
|
||||||
{
|
{
|
||||||
return values_[a] > values_[b];
|
return values[a] > values[b];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -487,14 +483,14 @@ public:
|
|||||||
template<class T>
|
template<class T>
|
||||||
void sort(UList<T>& a);
|
void sort(UList<T>& a);
|
||||||
|
|
||||||
template<class T, class Cmp>
|
template<class T, class Compare>
|
||||||
void sort(UList<T>& a, const Cmp& cmp);
|
void sort(UList<T>& a, const Compare& comp);
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void stableSort(UList<T>& a);
|
void stableSort(UList<T>& a);
|
||||||
|
|
||||||
template<class T, class Cmp>
|
template<class T, class Compare>
|
||||||
void stableSort(UList<T>& a, const Cmp& cmp);
|
void stableSort(UList<T>& a, const Compare& comp);
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void shuffle(UList<T>& a);
|
void shuffle(UList<T>& a);
|
||||||
|
|||||||
@ -452,6 +452,10 @@ public:
|
|||||||
//- Return the sorted table of contents
|
//- Return the sorted table of contents
|
||||||
wordList sortedToc() const;
|
wordList sortedToc() const;
|
||||||
|
|
||||||
|
//- Return table of contents sorted using the specified comparator
|
||||||
|
template<class Compare>
|
||||||
|
wordList sortedToc(const Compare& comp) const;
|
||||||
|
|
||||||
//- Return the list of available keys or patterns
|
//- Return the list of available keys or patterns
|
||||||
List<keyType> keys(bool patterns = false) const;
|
List<keyType> keys(bool patterns = false) const;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,13 @@ License
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Compare>
|
||||||
|
Foam::wordList Foam::dictionary::sortedToc(const Compare& comp) const
|
||||||
|
{
|
||||||
|
return hashedEntries_.sortedToc(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T Foam::dictionary::lookupType
|
T Foam::dictionary::lookupType
|
||||||
(
|
(
|
||||||
|
|||||||
@ -49,37 +49,40 @@ namespace predicates
|
|||||||
Class always Declaration
|
Class always Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
//- Unary and binary predicates returning true, useful for templating.
|
//- Unary and binary predicates that always return true, useful for templating.
|
||||||
class always
|
struct always
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
typedef always value_type;
|
typedef always value_type;
|
||||||
|
|
||||||
//- Construct null
|
//- Null constructible
|
||||||
inline always()
|
inline always()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
//- Evaluated as a bool - return true
|
//- Evaluated as a bool
|
||||||
|
// \return true
|
||||||
inline operator bool() const
|
inline operator bool() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Unary predicate returning true
|
//- Unary predicate
|
||||||
|
// \return true
|
||||||
template<class T>
|
template<class T>
|
||||||
inline bool operator()(const T&) const
|
inline bool operator()(const T&) const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Binary predicate returning true
|
//- Binary predicate
|
||||||
|
// \return true
|
||||||
template<class T1, class T2>
|
template<class T1, class T2>
|
||||||
inline bool operator()(const T1&, const T2&) const
|
inline bool operator()(const T1&, const T2&) const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- String match returning true
|
//- String match
|
||||||
|
// \return true
|
||||||
inline bool match(const std::string&, bool literal=false) const
|
inline bool match(const std::string&, bool literal=false) const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -91,37 +94,40 @@ public:
|
|||||||
Class never Declaration
|
Class never Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
//- Unary and binary predicates returning false, useful for templating.
|
//- Unary and binary predicates that never return true, useful for templating.
|
||||||
class never
|
struct never
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
typedef never value_type;
|
typedef never value_type;
|
||||||
|
|
||||||
//- Construct null
|
//- Null constructible
|
||||||
inline never()
|
inline never()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
//- Evaluated as a bool - return false
|
//- Evaluated as a bool
|
||||||
|
// \return false
|
||||||
inline operator bool() const
|
inline operator bool() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Unary predicate returning false
|
//- Unary predicate
|
||||||
|
// \return false
|
||||||
template<class T>
|
template<class T>
|
||||||
inline bool operator()(const T&) const
|
inline bool operator()(const T&) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Binary predicate returning false
|
//- Binary predicate
|
||||||
|
// \return false
|
||||||
template<class T1, class T2>
|
template<class T1, class T2>
|
||||||
inline bool operator()(const T1&, const T2&) const
|
inline bool operator()(const T1&, const T2&) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- String match returning false
|
//- String match
|
||||||
|
// \return false
|
||||||
inline bool match(const std::string&, bool literal=false) const
|
inline bool match(const std::string&, bool literal=false) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -41,6 +41,7 @@ SourceFiles
|
|||||||
#include "word.H"
|
#include "word.H"
|
||||||
#include "dictionary.H"
|
#include "dictionary.H"
|
||||||
#include "HashTable.H"
|
#include "HashTable.H"
|
||||||
|
#include "stringOpsSort.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|||||||
325
src/OpenFOAM/primitives/strings/stringOps/stringOpsSort.C
Normal file
325
src/OpenFOAM/primitives/strings/stringOps/stringOpsSort.C
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Changes for OpenFOAM
|
||||||
|
|
||||||
|
Code cleanup, reduction, elimination of redundant code.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//========================================================================
|
||||||
|
// Copyright (c) 1998-2010,2011 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, distribute with modifications, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included
|
||||||
|
// in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
// IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||||
|
// THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// Except as contained in this notice, the name(s) of the above copyright
|
||||||
|
// holders shall not be used in advertising or otherwise to promote the
|
||||||
|
// sale, use or other dealings in this Software without prior written
|
||||||
|
// authorization.
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
//========================================================================
|
||||||
|
// Original Author: Jan-Marten Spit <jmspit@euronet.nl>
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "stringOpsSort.H"
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Local tweaks/preferences:
|
||||||
|
//
|
||||||
|
// [DIGITS_ALWAYS_FIRST] : as per original code
|
||||||
|
// This results in "file123.txt" sorting before "file.txt", which is
|
||||||
|
// inconsistent with what 'ls -v' produces
|
||||||
|
// - normally do not want this (Mark Olesen: Oct-2017)
|
||||||
|
#undef DIGITS_ALWAYS_FIRST
|
||||||
|
|
||||||
|
// [IGNORE_LEADING_ZEROS] : as per original code
|
||||||
|
// This results in "file0005.txt" sorting before "file06.txt"
|
||||||
|
// -> normally want this (Mark Olesen: Oct-2017)
|
||||||
|
#define IGNORE_LEADING_ZEROS
|
||||||
|
|
||||||
|
// [MANUAL_NUMCOMPARE] : handwritten code instead of strncmp
|
||||||
|
// The orignal code has a mix of strncmp for equality but handwritten code
|
||||||
|
// for greater-than/less-than.
|
||||||
|
//
|
||||||
|
// -> this does to be unneeded, rely on strncmp() return values
|
||||||
|
// (Mark Olesen: Oct-2017)
|
||||||
|
#undef MANUAL_NUMCOMPARE
|
||||||
|
|
||||||
|
// [DEBUG_NATSTRCMP] : debug info to std::cerr (for development purposes only)
|
||||||
|
#undef DEBUG_NATSTRCMP
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef DEBUG_NATSTRCMP
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static inline void debugPrint(const char* text, T item1, T item2)
|
||||||
|
{
|
||||||
|
std::cerr << text << ": <" << item1 << "> <" << item2 << ">\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Character sequences, end pointer is _inclusive_.
|
||||||
|
static inline void debugPrint
|
||||||
|
(
|
||||||
|
const char* b1, const char* e1,
|
||||||
|
const char* b2, const char* e2
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cerr << "<";
|
||||||
|
while (b1 < e1) { std::cerr << *b1++; }
|
||||||
|
std::cerr << *e1 << "> ";
|
||||||
|
|
||||||
|
std::cerr << "<";
|
||||||
|
while (b2 < e2) { std::cerr << *b2++; }
|
||||||
|
std::cerr << *e2 << ">\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MANUAL_NUMCOMPARE
|
||||||
|
// Manual comparison of identical length (digit) sequences
|
||||||
|
static inline int manual_numcompare(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
while (*s1 && *s2)
|
||||||
|
{
|
||||||
|
const int cmp = (*s1 - *s2);
|
||||||
|
if (!cmp) return cmp;
|
||||||
|
|
||||||
|
++s1; ++s2;
|
||||||
|
}
|
||||||
|
return 0; // Length check done before in caller.
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
int Foam::stringOps::natstrcmp(const char* s1, const char* s2)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_NATSTRCMP
|
||||||
|
debugPrint("natstrcmp", s1, s2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// States for state engine
|
||||||
|
enum stateType { SCAN, ALPHA, NUMERIC };
|
||||||
|
|
||||||
|
// Number of leading zeroes
|
||||||
|
unsigned zeros1 = 0;
|
||||||
|
unsigned zeros2 = 0;
|
||||||
|
|
||||||
|
// Pointers to begin/end of integer sequences (without leading zeros)
|
||||||
|
const char* numbeg1 = nullptr;
|
||||||
|
const char* numbeg2 = nullptr;
|
||||||
|
const char* numend1 = nullptr;
|
||||||
|
const char* numend2 = nullptr;
|
||||||
|
|
||||||
|
stateType state = SCAN;
|
||||||
|
|
||||||
|
const char* p1 = s1;
|
||||||
|
const char* p2 = s2;
|
||||||
|
|
||||||
|
while (*p1 && *p2)
|
||||||
|
{
|
||||||
|
// Bitmask for digits vs alpha
|
||||||
|
// - 0: neither are digits
|
||||||
|
// - 1: p1 is the only digit
|
||||||
|
// - 2: p2 is the only digit
|
||||||
|
// - 3: both p1 and p2 are digits
|
||||||
|
|
||||||
|
const unsigned digitMask =
|
||||||
|
((isdigit(*p2) ? 2:0) | (isdigit(*p1) ? 1:0));
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case SCAN:
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_NATSTRCMP
|
||||||
|
debugPrint("SCAN", *p1, *p2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (digitMask)
|
||||||
|
{
|
||||||
|
case 0: // (alpha,alpha)
|
||||||
|
{
|
||||||
|
state = ALPHA;
|
||||||
|
|
||||||
|
if (*p1 == *p2)
|
||||||
|
{
|
||||||
|
++p1; ++p2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Lexical compare
|
||||||
|
return (*p1 - *p2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DIGITS_ALWAYS_FIRST
|
||||||
|
case 0x1: // (digit,alpha) : digit < alpha
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x2: // (alpha,digit) : alpha > digit
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else /* DIGITS_ALWAYS_FIRST */
|
||||||
|
case 0x1: // (digit,alpha)
|
||||||
|
case 0x2: // (alpha,digit)
|
||||||
|
{
|
||||||
|
// Lexical compare for digits/alpha
|
||||||
|
return (*p1 - *p2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* DIGITS_ALWAYS_FIRST */
|
||||||
|
|
||||||
|
default: // (digit,digit)
|
||||||
|
{
|
||||||
|
state = NUMERIC;
|
||||||
|
|
||||||
|
#ifdef IGNORE_LEADING_ZEROS
|
||||||
|
if (!zeros1) // Start skip of leading zeros
|
||||||
|
{
|
||||||
|
while (*p1 == '0') { ++p1; ++zeros1; }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
while (*p1 == '0') { ++p1; }
|
||||||
|
}
|
||||||
|
#ifdef IGNORE_LEADING_ZEROS
|
||||||
|
if (!zeros2) // Start skip of leading zeros
|
||||||
|
{
|
||||||
|
while (*p2 == '0') { ++p2; ++zeros2; }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
while (*p2 == '0') { ++p2; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zeros1 == zeros2)
|
||||||
|
{
|
||||||
|
// Same number of zeros - so irrelevant
|
||||||
|
zeros1 = zeros2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isdigit(*p1)) --p1;
|
||||||
|
if (!isdigit(*p2)) --p2;
|
||||||
|
|
||||||
|
numbeg1 = numend1 = p1;
|
||||||
|
numbeg2 = numend2 = p2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ALPHA:
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_NATSTRCMP
|
||||||
|
debugPrint("ALPHA", *p1, *p2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (digitMask)
|
||||||
|
{
|
||||||
|
state = SCAN;
|
||||||
|
}
|
||||||
|
else // (alpha,alpha)
|
||||||
|
{
|
||||||
|
if (*p1 == *p2)
|
||||||
|
{
|
||||||
|
++p1; ++p2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Lexical compare
|
||||||
|
return (*p1 - *p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NUMERIC:
|
||||||
|
{
|
||||||
|
while (isdigit(*p1)) numend1 = p1++;
|
||||||
|
while (isdigit(*p2)) numend2 = p2++;
|
||||||
|
|
||||||
|
#ifdef DEBUG_NATSTRCMP
|
||||||
|
debugPrint("NUMERIC", *p1, *p2);
|
||||||
|
debugPrint(numbeg1,numend1, numbeg2,numend2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Length (minus 1) of each sequence
|
||||||
|
const size_t len1 = (numend1 - numbeg1);
|
||||||
|
const size_t len2 = (numend2 - numbeg2);
|
||||||
|
|
||||||
|
if (len1 < len2)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (len1 > len2)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same number of digits, leading zeros have been skipped.
|
||||||
|
// - so lexical and numerical compares are equivalent.
|
||||||
|
|
||||||
|
const int cmp = strncmp(numbeg1, numbeg2, len1+1);
|
||||||
|
if (!cmp)
|
||||||
|
{
|
||||||
|
// Identical (digit) sequence - continue
|
||||||
|
state = SCAN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef MANUAL_STRNCMP
|
||||||
|
return manual_numcompare(numbeg1, numbeg2);
|
||||||
|
#else
|
||||||
|
return cmp;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zeros1 < zeros2) return -1;
|
||||||
|
if (zeros1 > zeros2) return 1;
|
||||||
|
if (!*p1 && *p2) return -1; // s1 shorter than s2
|
||||||
|
if (*p1 && !*p2) return 1; // s1 longer than s2
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
133
src/OpenFOAM/primitives/strings/stringOps/stringOpsSort.H
Normal file
133
src/OpenFOAM/primitives/strings/stringOps/stringOpsSort.H
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
InNamespace
|
||||||
|
Foam::stringOps
|
||||||
|
|
||||||
|
Description
|
||||||
|
Specialized string sorting.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
stringOpsSort.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef stringOpsSort_H
|
||||||
|
#define stringOpsSort_H
|
||||||
|
|
||||||
|
#include "stringOps.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace stringOps
|
||||||
|
{
|
||||||
|
|
||||||
|
//- 'Natural' compare for C-strings
|
||||||
|
// Uses algorithm and code from Jan-Marten Spit <jmspit@euronet.nl>
|
||||||
|
//
|
||||||
|
// In the 'natural' comparison, strings are compared alphabetically
|
||||||
|
// and numerically. Thus 'file010.txt' sorts after 'file2.txt'
|
||||||
|
//
|
||||||
|
// \param s1 left string
|
||||||
|
// \param s2 right string
|
||||||
|
// \return -1 when s1 < s2, 0 when s1 == s2, 1 when s1 > s2
|
||||||
|
int natstrcmp(const char* s1, const char* s2);
|
||||||
|
|
||||||
|
|
||||||
|
//- Encapsulation of natural order sorting for algorithms
|
||||||
|
struct natural_sort
|
||||||
|
{
|
||||||
|
//- Natural compare for std::string
|
||||||
|
// \return -1 when s1 < s2, 0 when s1 == s2, 1 when s1 > s2
|
||||||
|
static inline int compare
|
||||||
|
(
|
||||||
|
const std::string& s1,
|
||||||
|
const std::string& s2
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return natstrcmp(s1.data(), s2.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Default (forward) natural sorting
|
||||||
|
bool operator()(const std::string& s1, const std::string& s2) const
|
||||||
|
{
|
||||||
|
return natural_sort::compare(s1, s2) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Reverse natural sorting
|
||||||
|
struct reverse
|
||||||
|
{
|
||||||
|
//- Reverse natural sorting
|
||||||
|
bool operator()(const std::string& s1, const std::string& s2) const
|
||||||
|
{
|
||||||
|
return natural_sort::compare(s1, s2) > 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//- A list compare binary predicate for natural sort
|
||||||
|
template<class T>
|
||||||
|
struct less
|
||||||
|
{
|
||||||
|
const UList<T>& values;
|
||||||
|
|
||||||
|
less(const UList<T>& list)
|
||||||
|
:
|
||||||
|
values(list)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator()(const label a, const label b) const
|
||||||
|
{
|
||||||
|
return natural_sort::compare(values[a], values[b]) < 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//- A list compare binary predicate for reverse natural sort
|
||||||
|
template<class T>
|
||||||
|
struct greater
|
||||||
|
{
|
||||||
|
const UList<T>& values;
|
||||||
|
|
||||||
|
greater(const UList<T>& list)
|
||||||
|
:
|
||||||
|
values(list)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool operator()(const label a, const label b) const
|
||||||
|
{
|
||||||
|
return natural_sort::compare(values[a], values[b]) > 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace stringOps
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Reference in New Issue
Block a user