From 8fc27e0ec85288d7eccab1edb3e70d838a4f9c17 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Thu, 25 Jan 2018 15:00:25 +0100 Subject: [PATCH] ENH: make hashedWordList movable --- applications/test/hashedWordList/Make/files | 3 + applications/test/hashedWordList/Make/options | 2 + .../test/hashedWordList/Test-hashedWordList.C | 181 +++++++++++++++++ .../primitives/strings/lists/hashedWordList.C | 111 ++++------- .../primitives/strings/lists/hashedWordList.H | 117 ++++++----- .../strings/lists/hashedWordListI.H | 182 +++++++++++------- 6 files changed, 392 insertions(+), 204 deletions(-) create mode 100644 applications/test/hashedWordList/Make/files create mode 100644 applications/test/hashedWordList/Make/options create mode 100644 applications/test/hashedWordList/Test-hashedWordList.C diff --git a/applications/test/hashedWordList/Make/files b/applications/test/hashedWordList/Make/files new file mode 100644 index 00000000000..e92564415ee --- /dev/null +++ b/applications/test/hashedWordList/Make/files @@ -0,0 +1,3 @@ +Test-hashedWordList.C + +EXE = $(FOAM_USER_APPBIN)/Test-hashedWordList diff --git a/applications/test/hashedWordList/Make/options b/applications/test/hashedWordList/Make/options new file mode 100644 index 00000000000..6a9e9810b3d --- /dev/null +++ b/applications/test/hashedWordList/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = -I$(LIB_SRC)/cfdTools/include */ +/* EXE_LIBS = -lfiniteVolume */ diff --git a/applications/test/hashedWordList/Test-hashedWordList.C b/applications/test/hashedWordList/Test-hashedWordList.C new file mode 100644 index 00000000000..e7126e6a8ed --- /dev/null +++ b/applications/test/hashedWordList/Test-hashedWordList.C @@ -0,0 +1,181 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 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/>. + +Description + +\*---------------------------------------------------------------------------*/ + +#include "IOstreams.H" +#include "ITstream.H" +#include "FlatOutput.H" +#include "hashedWordList.H" + +using namespace Foam; + +Ostream& printInfo(const hashedWordList& list, bool withAddr=false) +{ + Info<< flatOutput(list) << nl << list.lookup() << nl; + if (withAddr) + { + Info<< "addr=" << long(list.cdata()) << nl; + } + + return Info; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + Info<< "Test hashedWordList" << nl; + + hashedWordList list1 + { + "this", + "is", + "a", + "list", + "of", + "words", + }; + + Info<<nl << "From initializer_list" << nl; + printInfo(list1, true); + + list1.sort(); + + Info<<nl << "sorted" << nl; + printInfo(list1, true); + + // Copy construct + hashedWordList list2(list1); + + Info<<nl << "Copy construct" << nl; + Info<<"list1: "; + printInfo(list1, true); + Info<<"list2: "; + printInfo(list2, true); + + // Move construct + hashedWordList list3(std::move(list1)); + + Info<<nl << "Move construct" << nl; + Info<<"list1: "; + printInfo(list1, true); + Info<<"list3: "; + printInfo(list3, true); + + // Move assign + list1 = std::move(list3); + + Info<<nl << "Move assign" << nl; + Info<<"list1: "; + printInfo(list1, true); + Info<<"list3: "; + printInfo(list3, true); + + list1.swap(list3); + Info<<nl << "Swap" << nl; + Info<<"list1: "; + printInfo(list1, true); + Info<<"list3: "; + printInfo(list3, true); + + wordList wlist1 + { + "plain", "list", "with", "some", "with", "list", "duplicates" + }; + + + // Copy construct unique + hashedWordList list4(wlist1, true); + + Info<<nl << "Copy construct unique" << nl; + Info<<"words: " << flatOutput(wlist1) << nl; + Info<<"list4: "; + printInfo(list4, false); + + // Move construct unique + hashedWordList list5(std::move(wlist1), true); + + Info<<nl << "Move construct unique" << nl; + Info<<"words: " << flatOutput(wlist1) << nl; + Info<<"list5: "; + printInfo(list5, false); + + // Move back. Leaves lookup() with some rubbish, but clean that later + wlist1 = std::move(list5); + + Info<<nl << "Move to wordList" << nl; + Info<<"words: " << flatOutput(wlist1) << nl; + Info<<"list5: "; + printInfo(list5, false); + + // Move back. Leaves lookup() with some rubbish, but clean that later + list5 = std::move(wlist1); + + Info<<nl << "Moved from wordList" << nl; + Info<<"words: " << flatOutput(wlist1) << nl; + Info<<"list5: "; + printInfo(list5, false); + + + // Test access: + + Info<<nl << "Access" << nl; + Info<<"list: " << flatOutput(list5) << nl; + + for (const auto str : { "some", "list", "of", "words" }) + { + Info<<"index of " << str << " = " << list5[str] << nl; + } + + // Stream construct + { + ITstream input + ( + "input", + "(plain list with some with list duplicates)" + ); + + hashedWordList list6(input); + + Info<<nl << "Construct from stream" << nl; + Info<<"list: " << flatOutput(list6) << nl; + + input.rewind(); + + input >> list4; + Info<<nl << "re-read from stream" << nl; + Info<<"list: " << flatOutput(list4) << nl; + } + + + Info<< "\nEnd\n"; + + return 0; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/strings/lists/hashedWordList.C b/src/OpenFOAM/primitives/strings/lists/hashedWordList.C index d1a8a8ac9fe..d47f7e42c96 100644 --- a/src/OpenFOAM/primitives/strings/lists/hashedWordList.C +++ b/src/OpenFOAM/primitives/strings/lists/hashedWordList.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -24,118 +24,73 @@ License \*---------------------------------------------------------------------------*/ #include "hashedWordList.H" +#include "CStringList.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::hashedWordList::hashedWordList ( - const label count, - const char** lst, - const bool removeDuplicates + const label len, + const char** array, + bool unique ) : - List<word>(count) + wordList(len) { - forAll(*this, i) + for (label i=0; i < len; ++i) { - List<word>::operator[](i) = lst[i]; + wordList::operator[](i) = array[i]; } - rehash(removeDuplicates); + rehash(unique); } -Foam::hashedWordList::hashedWordList -( - const char** lst, - const bool removeDuplicates -) -{ - // Determine the number of entries - label count = 0; - for (unsigned i = 0; lst[i] && *(lst[i]); ++i) - { - ++count; - } - - List<word>::setSize(count); - forAll(*this, i) - { - List<word>::operator[](i) = lst[i]; - } - - rehash(removeDuplicates); -} - - -Foam::hashedWordList::hashedWordList(Istream& is) -{ - is >> *this; -} - - -// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // +Foam::hashedWordList::hashedWordList(const char** array, bool unique) +: + hashedWordList(CStringList::count(array), array, unique) +{} -void Foam::hashedWordList::transfer -( - List<word>& lst, - const bool removeDuplicates -) -{ - List<word>::transfer(lst); - rehash(removeDuplicates); -} +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::hashedWordList::rehash() const { - indices_.clear(); + lookup_.clear(); - forAll(*this, i) + const wordUList& list = *this; + const label len = list.size(); + + for (label i=0; i < len; ++i) { - indices_.insert(List<word>::operator[](i), i); + lookup_.insert(list[i], i); } } void Foam::hashedWordList::uniq() { - indices_.clear(); + lookup_.clear(); + + wordList& list = *this; + const label len = list.size(); - label nElem = 0; - forAll(*this, i) + label count = 0; + for (label i=0; i < len; ++i) { - const word& item = List<word>::operator[](i); + word& item = list[i]; - if (indices_.insert(item, nElem)) + if (lookup_.insert(item, i)) { - if (nElem != i) + if (count != i) { - List<word>::operator[](nElem) = item; + list[count] = std::move(item); } - ++nElem; + ++count; } } - List<word>::setSize(nElem); -} - - -// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // - -Foam::Istream& Foam::operator>>(Istream& is, hashedWordList& lst) -{ - is >> static_cast<List<word>&>(lst); - lst.rehash(); - - return is; -} - - -Foam::Ostream& Foam::operator<<(Ostream& os, const hashedWordList& lst) -{ - os << static_cast<const UList<word>&>(lst); - return os; + list.resize(count); } diff --git a/src/OpenFOAM/primitives/strings/lists/hashedWordList.H b/src/OpenFOAM/primitives/strings/lists/hashedWordList.H index a2e68df9df3..c7a451942e4 100644 --- a/src/OpenFOAM/primitives/strings/lists/hashedWordList.H +++ b/src/OpenFOAM/primitives/strings/lists/hashedWordList.H @@ -25,7 +25,8 @@ Class Foam::hashedWordList Description - A wordList with hashed indices for additional fast lookup by name. + A wordList with hashed named lookup, which can be faster in some + situations than using the normal list find/found methods. SourceFiles hashedWordListI.H @@ -44,11 +45,9 @@ SourceFiles namespace Foam { +// Forward declarations class hashedWordList; - -// Forward declaration of friend functions and operators -Istream& operator>>(Istream& is, hashedWordList& lst); -Ostream& operator<<(Ostream& os, const hashedWordList& lst); +inline Istream& operator>>(Istream& is, hashedWordList& lst); /*---------------------------------------------------------------------------*\ @@ -57,44 +56,34 @@ Ostream& operator<<(Ostream& os, const hashedWordList& lst); class hashedWordList : - public List<word> + public wordList { - // Private data - - //- Hash of words/indices - mutable HashTable<label> indices_; - - - // Private Member Functions + // Private Data - //- Rebuild the lookup hash or make unique entries first. - inline void rehash(const bool unique); + //- Lookup HashTable of words vs list-indices + mutable HashTable<label> lookup_; public: // Constructors - //- Construct null - inline hashedWordList(); + //- Construct an empty list + inline hashedWordList() = default; - //- Copy constructor. + //- Copy construct. inline hashedWordList(const hashedWordList& lst); - //- Construct from list of words, - // optionally eliminating duplicates - inline hashedWordList - ( - const UList<word>& lst, - const bool removeDuplicates=false - ); + //- Move construct. + inline hashedWordList(hashedWordList&& lst); - //- Construct by transferring the parameter contents, - // optionally eliminating duplicates - inline hashedWordList - ( - const Xfer<List<word>>& lst, - const bool removeDuplicates=false - ); + //- Copy construct from list of words + inline explicit hashedWordList(const wordUList& lst); + + //- Copy construct from list of words, eliminating duplicates + inline hashedWordList(const wordUList& lst, bool unique); + + //- Move construct from list of words, optionally eliminating duplicates + inline hashedWordList(wordList&& lst, bool unique=false); //- Construct from an initializer list inline hashedWordList(std::initializer_list<word> lst); @@ -110,19 +99,14 @@ public: //- Construct from number and list of words, // optionally eliminating duplicates - hashedWordList - ( - const label count, - const char** lst, - const bool removeDuplicates=false - ); + hashedWordList(const label len, const char** array, bool unique=false); //- Construct from a nullptr-terminated list of words, // optionally eliminating duplicates - hashedWordList(const char** lst, const bool removeDuplicates=false); + hashedWordList(const char** array, bool unique=false); //- Construct from Istream - hashedWordList(Istream& is); + inline hashedWordList(Istream& is); // Member Functions @@ -132,7 +116,7 @@ public: //- Append an element at the end of the list, // optionally avoid append if it would be a duplicate entry - inline void append(const word& name, const bool avoidDuplicates=false); + inline void append(const word& name, bool unique=false); //- Does the list contain the specified name inline bool found(const word& name) const; @@ -143,51 +127,64 @@ public: //- Return the hash of words/indices for inspection inline const HashTable<label>& lookup() const; + //- Swap contents + inline void swap(hashedWordList& lst); + + //- Transfer contents of the argument into this list + //- and annul the argument list, optionally eliminating duplicates + inline void transfer(hashedWordList& lst); + //- Transfer the contents of the argument List into this list - // and annul the argument list, - // optionally eliminating duplicates - void transfer(List<word>& lst, const bool removeDuplicates=false); + //- and annul the argument list, optionally eliminating duplicates + inline void transfer(wordList& lst, bool unique=false); //- Rebuild the lookup hash indices void rehash() const; - //- Sort the list and rehash the indices - inline void sort(); + //- Rebuild the lookup hash indices, or make unique entries first. + inline void rehash(bool unique); - //- Adjust the list if necessary to eliminate duplicate entries, - // and rehash the indices + //- Adjust the list (if needed) to eliminate duplicate entries, + //- and rehash the indices void uniq(); + //- Sort the list and rehash the indices + inline void sort(); + // Member Operators - //- Return name corresponding to specified index + //- Return name corresponding to specified index. + // Fatal for out of range values. inline const word& operator[](const label index) const; //- Return index corresponding to specified name, or -1 on failure inline label operator[](const word& name) const; - //- Does the list contain the specified name - same as found. - // Makes hashedWordList suitable as a unary predicate. + //- Check hashed values for the specified name - same as found. + // Can be used as a unary predicate. inline bool operator()(const word& name) const; // Assignment - //- Assignment operator from list of words. Rehashes the indices. - inline void operator=(const UList<word>& lst); + //- Copy assignment. Rehashes the indices. + inline void operator=(const hashedWordList& lst); + + //- Copy assignment from list of words. Rehashes the indices. + inline void operator=(const wordUList& lst); - //- Assignment operator from initializer list. Rehashes the indices. + //- Copy assignment from initializer list. Rehashes the indices. inline void operator=(std::initializer_list<word> lst); - //- Assignment operator. Rehashes the indices. - inline void operator=(const hashedWordList& lst); - + //- Move assignment operator. + inline void operator=(hashedWordList&& lst); - // Istream operators + //- Move assignment from list of words. Rehashes the indices. + inline void operator=(wordList&& lst); - friend Istream& operator>>(Istream& is, hashedWordList& lst); - friend Ostream& operator<<(Ostream& os, const hashedWordList& lst); + //- Read from an input stream. Rehashes the indices. + inline friend Istream& operator>>(Istream& is, hashedWordList& lst); }; diff --git a/src/OpenFOAM/primitives/strings/lists/hashedWordListI.H b/src/OpenFOAM/primitives/strings/lists/hashedWordListI.H index f57ef3abcae..0f7971c0c2b 100644 --- a/src/OpenFOAM/primitives/strings/lists/hashedWordListI.H +++ b/src/OpenFOAM/primitives/strings/lists/hashedWordListI.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. + \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -23,64 +23,46 @@ License \*---------------------------------------------------------------------------*/ -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - -inline void Foam::hashedWordList::rehash(const bool unique) -{ - if (unique) - { - uniq(); - } - else - { - rehash(); - } -} +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // +inline Foam::hashedWordList::hashedWordList(const hashedWordList& lst) +: + hashedWordList(static_cast<const wordUList&>(lst), false) +{} -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -inline Foam::hashedWordList::hashedWordList() +inline Foam::hashedWordList::hashedWordList(hashedWordList&& lst) : - List<word>() + wordList(std::move(static_cast<wordList&>(lst))), + lookup_(std::move(lst.lookup_)) {} -inline Foam::hashedWordList::hashedWordList(const hashedWordList& lst) +inline Foam::hashedWordList::hashedWordList(const wordUList& lst) : - List<word>(static_cast<const UList<word>&>(lst)) -{ - rehash(); -} + hashedWordList(lst, false) +{} -inline Foam::hashedWordList::hashedWordList -( - const UList<word>& lst, - const bool removeDuplicates -) +inline Foam::hashedWordList::hashedWordList(const wordUList& lst, bool unique) : - List<word>(lst) + wordList(lst) { - rehash(removeDuplicates); + rehash(unique); } -inline Foam::hashedWordList::hashedWordList -( - const Xfer<List<word>>& lst, - const bool removeDuplicates -) +inline Foam::hashedWordList::hashedWordList(wordList&& lst, bool unique) : - List<word>(lst) + wordList(std::move(lst)) { - rehash(removeDuplicates); + rehash(unique); } inline Foam::hashedWordList::hashedWordList(std::initializer_list<word> lst) : - List<word>(lst) + wordList(lst) { rehash(); } @@ -92,37 +74,41 @@ inline Foam::hashedWordList::hashedWordList const HashTable<AnyType, word, AnyHash>& tbl ) : - List<word>(tbl.size()) + wordList(tbl.size()) { + wordList& list = *this; + label count = 0; for (auto iter = tbl.cbegin(); iter != tbl.cend(); ++iter) { - List<word>::operator[](count++) = iter.key(); + list[count++] = iter.key(); } this->sort(); } +inline Foam::hashedWordList::hashedWordList(Istream& is) +{ + is >> *this; +} + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // inline void Foam::hashedWordList::clear() { - List<word>::clear(); - indices_.clear(); + wordList::clear(); + lookup_.clear(); } -inline void Foam::hashedWordList::append -( - const word& name, - const bool avoidDuplicates -) +inline void Foam::hashedWordList::append(const word& name, bool unique) { // name is either unique or we don't care about duplicates - if (indices_.insert(name, size()) || !avoidDuplicates) + if (lookup_.insert(name, size()) || !unique) { - List<word>::append(name); + wordList::append(name); } } @@ -130,19 +116,64 @@ inline void Foam::hashedWordList::append inline const Foam::HashTable<Foam::label>& Foam::hashedWordList::lookup() const { - return indices_; + const label lenList = wordList::size(); + const label lenHash = lookup_.size(); + + if ((lenList < lenHash) || (lenList && !lenHash)) + { + rehash(); // Was somehow out of sync + } + + return lookup_; } inline bool Foam::hashedWordList::found(const word& name) const { - return indices_.found(name); + return lookup().found(name); } inline bool Foam::hashedWordList::contains(const word& name) const { - return indices_.found(name); + return lookup().found(name); +} + + +inline void Foam::hashedWordList::swap(hashedWordList& lst) +{ + wordList::swap(static_cast<wordList&>(lst)); + lookup_.swap(lst.lookup_); +} + + +inline void Foam::hashedWordList::transfer +( + hashedWordList& lst +) +{ + wordList::transfer(static_cast<wordList&>(lst)); + lookup_.transfer(lst.lookup_); +} + + +inline void Foam::hashedWordList::transfer(wordList& lst, bool unique) +{ + wordList::transfer(lst); + rehash(unique); +} + + +inline void Foam::hashedWordList::rehash(bool unique) +{ + if (unique) + { + uniq(); + } + else + { + rehash(); + } } @@ -160,46 +191,65 @@ inline const Foam::word& Foam::hashedWordList::operator[] const label index ) const { - return List<word>::operator[](index); + return wordList::operator[](index); } inline Foam::label Foam::hashedWordList::operator[](const word& name) const { - auto iter = indices_.find(name); + return lookup_.lookup(name, -1); // -1 = not found or not hashed +} - if (iter.found()) - { - return iter.object(); - } - return -1; // Not found (or not hashed?) +inline bool Foam::hashedWordList::operator()(const word& name) const +{ + return lookup_.found(name); } -inline bool Foam::hashedWordList::operator()(const word& name) const +inline void Foam::hashedWordList::operator=(const hashedWordList& lst) { - return indices_.found(name); + wordList::operator=(lst); + rehash(); } -inline void Foam::hashedWordList::operator=(const UList<word>& lst) +inline void Foam::hashedWordList::operator=(const wordUList& lst) { - List<word>::operator=(lst); + wordList::operator=(lst); rehash(); } inline void Foam::hashedWordList::operator=(std::initializer_list<word> lst) { - List<word>::operator=(lst); + wordList::operator=(lst); rehash(); } -inline void Foam::hashedWordList::operator=(const hashedWordList& lst) +inline void Foam::hashedWordList::operator=(hashedWordList&& lst) { - operator=(static_cast<const UList<word>&>(lst)); + wordList::operator=(std::move(static_cast<wordList&>(lst))); + lookup_ = std::move(lst.lookup_); +} + + +inline void Foam::hashedWordList::operator=(wordList&& lst) +{ + wordList::operator=(std::move(lst)); + rehash(); +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +inline Foam::Istream& Foam::operator>>(Istream& is, hashedWordList& lst) +{ + is >> static_cast<wordList&>(lst); + lst.rehash(); + + return is; } -- GitLab