From 55a89e9db3d78dca419db5f10256b60a1306d076 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@Germany> Date: Fri, 30 Oct 2009 18:31:28 +0100 Subject: [PATCH] added HashTbl as development replacement for HashTable - rename to HashTable later when it is considered stable --- applications/test/HashTable3/Make/files | 3 + applications/test/HashTable3/Make/options | 2 + applications/test/HashTable3/hashTableTest3.C | 83 +++ src/OpenFOAM/Make/files | 1 + .../containers/HashTables/HashTbl/HashTbl.C | 665 ++++++++++++++++++ .../containers/HashTables/HashTbl/HashTbl.H | 466 ++++++++++++ .../containers/HashTables/HashTbl/HashTblI.H | 548 +++++++++++++++ .../containers/HashTables/HashTbl/HashTblIO.C | 246 +++++++ .../HashTables/HashTbl/HashTblName.C | 33 + 9 files changed, 2047 insertions(+) create mode 100644 applications/test/HashTable3/Make/files create mode 100644 applications/test/HashTable3/Make/options create mode 100644 applications/test/HashTable3/hashTableTest3.C create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTblIO.C create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTblName.C diff --git a/applications/test/HashTable3/Make/files b/applications/test/HashTable3/Make/files new file mode 100644 index 00000000000..e8ec193ffa2 --- /dev/null +++ b/applications/test/HashTable3/Make/files @@ -0,0 +1,3 @@ +hashTableTest3.C + +EXE = $(FOAM_USER_APPBIN)/hashTableTest3 diff --git a/applications/test/HashTable3/Make/options b/applications/test/HashTable3/Make/options new file mode 100644 index 00000000000..6a9e9810b3d --- /dev/null +++ b/applications/test/HashTable3/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = -I$(LIB_SRC)/cfdTools/include */ +/* EXE_LIBS = -lfiniteVolume */ diff --git a/applications/test/HashTable3/hashTableTest3.C b/applications/test/HashTable3/hashTableTest3.C new file mode 100644 index 00000000000..422e35696c0 --- /dev/null +++ b/applications/test/HashTable3/hashTableTest3.C @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2009-2009 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Description + + Test speeds for some HashTable operations + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "HashTable.H" +#include "HashPtrTable.H" +#include "Map.H" +#include "StaticHashTable.H" +#include "HashTbl.H" +#include "cpuTime.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + const label nLoops = 30; + const label nBase = 100000; + const label nSize = nLoops * nBase; + + cpuTime timer; + + // ie, a + // Map<label> map(2 * nSize); + // HashTable<label, label, Hash<label> > map(2 * nSize); + // StaticHashTable<label, label, Hash<label> > map(2 * nSize); + HashTbl<label, label, Hash<label> > map(2 * nSize); + + Info<< "Constructed map of size: " << nSize + << " " << timer.cpuTimeIncrement() << " s\n\n"; + + for (label i = 0; i < nSize; i++) + { + map.insert(i, i); + } + Info<< "Inserted " << nSize << " elements: " + << timer.cpuTimeIncrement() << " s\n\n"; + + + label elemI = 0; + for (label iLoop = 0; iLoop < nLoops; iLoop++) + { + for (label i = 0; i < nBase; i++) + { + map.erase(elemI++); + } + Info<< "loop " << iLoop << " - Erased " << nBase << " elements: " + << " " << timer.cpuTimeIncrement() << " s\n"; + } + + return 0; +} + +// ************************************************************************* // diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 2823c2a9ec3..a290ec2847a 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -61,6 +61,7 @@ $(sha1)/SHA1Digest.C primitives/random/Random.C +containers/HashTables/HashTbl/HashTblName.C containers/HashTables/HashTable/HashTableName.C containers/HashTables/StaticHashTable/StaticHashTableName.C containers/Lists/SortableList/ParSortableListName.C diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C new file mode 100644 index 00000000000..8e7be6b147d --- /dev/null +++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C @@ -0,0 +1,665 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#ifndef HashTbl_C +#define HashTbl_C + +#include "HashTbl.H" +#include "List.H" + +// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +Foam::label Foam::HashTbl<T, Key, Hash>::canonicalSize(const label size) +{ + if (size < 1) + { + return 0; + } + + // enforce power of two + unsigned int goodSize = size; + + if (goodSize & (goodSize - 1)) + { + // brute-force is fast enough + goodSize = 1; + while (goodSize < unsigned(size)) + { + goodSize <<= 1; + } + } + + return goodSize; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +Foam::HashTbl<T, Key, Hash>::HashTbl(const label size) +: + HashTblName(), + nElmts_(0), + tableSize_(canonicalSize(size)), + table_(NULL), + endIter_(*this, NULL, 0), + endConstIter_(*this, NULL, 0) +{ + if (tableSize_) + { + table_ = new hashedEntry*[tableSize_]; + + for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++) + { + table_[hashIdx] = 0; + } + } +} + + +template<class T, class Key, class Hash> +Foam::HashTbl<T, Key, Hash>::HashTbl(const HashTbl<T, Key, Hash>& ht) +: + HashTblName(), + nElmts_(0), + tableSize_(ht.tableSize_), + table_(NULL), + endIter_(*this, NULL, 0), + endConstIter_(*this, NULL, 0) +{ + if (tableSize_) + { + table_ = new hashedEntry*[tableSize_]; + + for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++) + { + table_[hashIdx] = 0; + } + + for (const_iterator iter = ht.cbegin(); iter != ht.cend(); ++iter) + { + insert(iter.key(), *iter); + } + } +} + +template<class T, class Key, class Hash> +Foam::HashTbl<T, Key, Hash>::HashTbl +( + const Xfer<HashTbl<T, Key, Hash> >& ht +) +: + HashTblName(), + nElmts_(0), + tableSize_(0), + table_(NULL), + endIter_(*this, NULL, 0), + endConstIter_(*this, NULL, 0) +{ + transfer(ht()); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +Foam::HashTbl<T, Key, Hash>::~HashTbl() +{ + if (table_) + { + clear(); + delete[] table_; + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +bool Foam::HashTbl<T, Key, Hash>::found(const Key& key) const +{ + if (nElmts_) + { + const label hashIdx = hashKeyIndex(key); + + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + if (key == ep->key_) + { + return true; + } + } + } + +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl<T, Key, Hash>::found(const Key& key) : " + << "Entry " << key << " not found in hash table\n"; + } +# endif + + return false; +} + + +template<class T, class Key, class Hash> +typename Foam::HashTbl<T, Key, Hash>::iterator +Foam::HashTbl<T, Key, Hash>::find +( + const Key& key +) +{ + if (nElmts_) + { + const label hashIdx = hashKeyIndex(key); + + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + if (key == ep->key_) + { + return iterator(*this, ep, hashIdx); + } + } + } + +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl<T, Key, Hash>::find(const Key& key) : " + << "Entry " << key << " not found in hash table\n"; + } +# endif + + return end(); +} + + +template<class T, class Key, class Hash> +typename Foam::HashTbl<T, Key, Hash>::const_iterator +Foam::HashTbl<T, Key, Hash>::find +( + const Key& key +) const +{ + if (nElmts_) + { + const label hashIdx = hashKeyIndex(key); + + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + if (key == ep->key_) + { + return const_iterator(*this, ep, hashIdx); + } + } + } + +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl<T, Key, Hash>::find(const Key& key) const : " + << "Entry " << key << " not found in hash table\n"; + } +# endif + + return cend(); +} + + +template<class T, class Key, class Hash> +Foam::List<Key> Foam::HashTbl<T, Key, Hash>::toc() const +{ + List<Key> tofc(nElmts_); + label i = 0; + + for (const_iterator iter = cbegin(); iter != cend(); ++iter) + { + tofc[i++] = iter.key(); + } + + return tofc; +} + + +template<class T, class Key, class Hash> +Foam::List<Key> Foam::HashTbl<T, Key, Hash>::sortedToc() const +{ + List<Key> sortedList = this->toc(); + sort(sortedList); + + return sortedList; +} + + +template<class T, class Key, class Hash> +bool Foam::HashTbl<T, Key, Hash>::set +( + const Key& key, + const T& newEntry, + const bool protect +) +{ + if (!tableSize_) + { + resize(2); + } + + const label hashIdx = hashKeyIndex(key); + + hashedEntry* existing = 0; + hashedEntry* prev = 0; + + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + if (key == ep->key_) + { + existing = ep; + break; + } + prev = ep; + } + + // not found, insert it at the head + if (!existing) + { + table_[hashIdx] = new hashedEntry(key, table_[hashIdx], newEntry); + nElmts_++; + + if (double(nElmts_)/tableSize_ > 0.8) + { +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl<T, Key, Hash>::set" + "(const Key& key, T newEntry) : " + "Doubling table size\n"; + } +# endif + + resize(2*tableSize_); + } + } + else if (protect) + { + // found - but protected from overwriting + // this corresponds to the STL 'insert' convention +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl<T, Key, Hash>::set" + "(const Key& key, T newEntry, true) : " + "Cannot insert " << key << " already in hash table\n"; + } +# endif + return false; + } + else + { + // found - overwrite existing entry + // this corresponds to the Perl convention + hashedEntry* ep = new hashedEntry(key, existing->next_, newEntry); + + // replace existing element - within list or insert at the head + if (prev) + { + prev->next_ = ep; + } + else + { + table_[hashIdx] = ep; + } + + delete existing; + } + + return true; +} + + +template<class T, class Key, class Hash> +bool Foam::HashTbl<T, Key, Hash>::erase(const iterator& cit) +{ + if (cit.elmtPtr_) // note: endIter_ also has 0 elmtPtr_ + { + iterator& it = const_cast<iterator&>(cit); + + // Search element before elmtPtr_ + hashedEntry* prev = 0; + + for (hashedEntry* ep = table_[it.hashIndex_]; ep; ep = ep->next_) + { + if (ep == it.elmtPtr_) + { + break; + } + prev = ep; + } + + if (prev) + { + // Have element before elmtPtr + prev->next_ = it.elmtPtr_->next_; + delete it.elmtPtr_; + it.elmtPtr_ = prev; + } + else + { + // elmtPtr is first element on SLList + table_[it.hashIndex_] = it.elmtPtr_->next_; + delete it.elmtPtr_; + + // Search back for previous non-zero table entry + while (--it.hashIndex_ >= 0 && !table_[it.hashIndex_]) + {} + + if (it.hashIndex_ >= 0) + { + // In table entry search for last element + it.elmtPtr_ = table_[it.hashIndex_]; + + while (it.elmtPtr_ && it.elmtPtr_->next_) + { + it.elmtPtr_ = it.elmtPtr_->next_; + } + } + else + { + // No previous found. Mark with special value which is + // - not end()/cend() + // - handled by operator++ + it.elmtPtr_ = reinterpret_cast<hashedEntry*>(this); + it.hashIndex_ = -1; + } + } + + nElmts_--; + +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl<T, Key, Hash>::erase(iterator&) : " + << "hashedEntry " << it.elmtPtr_->key_ << " removed.\n"; + } +# endif + + return true; + } + else + { +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl<T, Key, Hash>::erase(iterator&) : " + << "cannot remove hashedEntry from hash table\n"; + } +# endif + + return false; + } +} + + +template<class T, class Key, class Hash> +bool Foam::HashTbl<T, Key, Hash>::erase(const Key& key) +{ + iterator fnd = find(key); + + if (fnd != end()) + { + return erase(fnd); + } + else + { + return false; + } +} + + +template<class T, class Key, class Hash> +Foam::label Foam::HashTbl<T, Key, Hash>::erase(const UList<Key>& keys) +{ + label count = 0; + + // Remove listed keys from this table + if (this->size()) + { + forAll(keys, keyI) + { + if (erase(keys[keyI])) + { + count++; + } + } + } + + return count; +} + + +template<class T, class Key, class Hash> +template<class AnyType> +Foam::label Foam::HashTbl<T, Key, Hash>::erase +( + const HashTbl<AnyType, Key, Hash>& rhs +) +{ + label count = 0; + + // Remove rhs elements from this table + if (this->size()) + { + // NOTE: could further optimize depending on which hash is smaller + for (iterator iter = begin(); iter != end(); ++iter) + { + if (rhs.found(iter.key()) && erase(iter)) + { + count++; + } + } + } + + return count; +} + + +template<class T, class Key, class Hash> +void Foam::HashTbl<T, Key, Hash>::resize(const label sz) +{ + label newSize = canonicalSize(sz); + + if (newSize == tableSize_) + { +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl<T, Key, Hash>::resize(const label) : " + << "new table size == old table size\n"; + } +# endif + + return; + } + + HashTbl<T, Key, Hash>* newTable = new HashTbl<T, Key, Hash>(newSize); + + for (const_iterator iter = cbegin(); iter != cend(); ++iter) + { + newTable->insert(iter.key(), *iter); + } + + label oldTableSize = tableSize_; + tableSize_ = newTable->tableSize_; + newTable->tableSize_ = oldTableSize; + + hashedEntry** oldTable = table_; + table_ = newTable->table_; + newTable->table_ = oldTable; + + delete newTable; +} + + +template<class T, class Key, class Hash> +void Foam::HashTbl<T, Key, Hash>::clear() +{ + if (nElmts_) + { + for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++) + { + if (table_[hashIdx]) + { + hashedEntry* ep = table_[hashIdx]; + while (hashedEntry* next = ep->next_) + { + delete ep; + ep = next; + } + delete ep; + table_[hashIdx] = 0; + } + } + nElmts_ = 0; + } +} + + +template<class T, class Key, class Hash> +void Foam::HashTbl<T, Key, Hash>::clearStorage() +{ + clear(); + resize(0); +} + + +template<class T, class Key, class Hash> +void Foam::HashTbl<T, Key, Hash>::transfer(HashTbl<T, Key, Hash>& ht) +{ + // as per the Destructor + if (table_) + { + clear(); + delete[] table_; + } + + tableSize_ = ht.tableSize_; + ht.tableSize_ = 0; + + table_ = ht.table_; + ht.table_ = NULL; + + nElmts_ = ht.nElmts_; + ht.nElmts_ = 0; +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +void Foam::HashTbl<T, Key, Hash>::operator= +( + const HashTbl<T, Key, Hash>& rhs +) +{ + // Check for assignment to self + if (this == &rhs) + { + FatalErrorIn + ( + "HashTbl<T, Key, Hash>::operator=" + "(const HashTbl<T, Key, Hash>&)" + ) << "attempted assignment to self" + << abort(FatalError); + } + + // could be zero-sized from a previous transfer() + if (!tableSize_) + { + resize(rhs.tableSize_); + } + else + { + clear(); + } + + for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) + { + insert(iter.key(), *iter); + } +} + + +template<class T, class Key, class Hash> +bool Foam::HashTbl<T, Key, Hash>::operator== +( + const HashTbl<T, Key, Hash>& rhs +) const +{ + // Are all my elements in rhs? + for (const_iterator iter = cbegin(); iter != cend(); ++iter) + { + const_iterator fnd = rhs.find(iter.key()); + + if (fnd == rhs.cend() || fnd() != iter()) + { + return false; + } + } + + // Are all rhs elements in me? + for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) + { + const_iterator fnd = find(iter.key()); + + if (fnd == cend() || fnd() != iter()) + { + return false; + } + } + return true; +} + + +template<class T, class Key, class Hash> +bool Foam::HashTbl<T, Key, Hash>::operator!= +( + const HashTbl<T, Key, Hash>& rhs +) const +{ + return !(operator==(rhs)); +} + + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +#include "HashTblIO.C" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H new file mode 100644 index 00000000000..1c9f6db257d --- /dev/null +++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H @@ -0,0 +1,466 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Class + Foam::HashTbl + +Description + An STL-conforming hash table. + +Note + Hashing index collisions are handled via chaining using a singly-linked + list with the colliding entry being added to the head of the linked + list. Thus copying the hash table (or indeed even resizing it) will + often result in a different hash order. Use a sorted table-of-contents + when the hash order is important. + +SourceFiles + HashTblI.H + HashTbl.C + HashTblIO.C + +\*---------------------------------------------------------------------------*/ + +#ifndef HashTbl_H +#define HashTbl_H + +#include "label.H" +#include "uLabel.H" +#include "word.H" +#include "Xfer.H" +#include "className.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of friend functions and operators + +template<class T> class List; +template<class T> class UList; +template<class T, class Key, class Hash> class HashTbl; +template<class T, class Key, class Hash> class HashPtrTable; + +template<class T, class Key, class Hash> +Istream& operator>>(Istream&, HashTbl<T, Key, Hash>&); + +template<class T, class Key, class Hash> +Ostream& operator<<(Ostream&, const HashTbl<T, Key, Hash>&); + + +/*---------------------------------------------------------------------------*\ + Class HashTblName Declaration +\*---------------------------------------------------------------------------*/ + +TemplateName(HashTbl); + + +/*---------------------------------------------------------------------------*\ + Class HashTbl Declaration +\*---------------------------------------------------------------------------*/ + +template<class T, class Key=word, class Hash=string::hash> +class HashTbl +: + public HashTblName +{ + // Private data type for table entries + + struct hashedEntry + { + //- The lookup key + Key key_; + + //- Pointer to next hashedEntry in sub-list + hashedEntry* next_; + + //- The data object + T obj_; + + //- Constructors + + //- Construct given key, next pointer and object + inline hashedEntry + ( + const Key&, + hashedEntry* next, + const T& newEntry + ); + + //- Dissallow construction as copy + hashedEntry(const hashedEntry&); + }; + + + // Private data: size of table, the table and current number of elements + + //- The current number of elements in table + label nElmts_; + + //- Number of primary entries allocated in table (not necessarily used) + label tableSize_; + + //- The table of primary entries + hashedEntry** table_; + + + // Private Member Functions + + //- Return a canonical (power-of-two) size + static label canonicalSize(const label); + + //- Return the hash index of the Key within the current table size. + // No checks for zero-sized tables. + inline label hashKeyIndex(const Key&) const; + + //- Assign a new hashedEntry to a possibly already existing key + bool set(const Key&, const T& newElmt, bool protect); + +public: + + //- Declare friendship with the HashPtrTable class + template<class T2, class Key2, class Hash2> + friend class HashPtrTable; + + + // Forward declaration of STL iterators + + class iterator; + friend class iterator; + + class const_iterator; + friend class const_iterator; + + + // Constructors + + //- Construct given initial table size + HashTbl(const label size = 128); + + //- Construct from Istream + HashTbl(Istream&, const label size = 128); + + //- Construct as copy + HashTbl(const HashTbl<T, Key, Hash>&); + + //- Construct by transferring the parameter contents + HashTbl(const Xfer<HashTbl<T, Key, Hash> >&); + + + // Destructor + + ~HashTbl(); + + + // Member Functions + + // Access + + //- Return number of elements in table. + inline label size() const; + + //- Return true if the hash table is empty + inline bool empty() const; + + //- Return true if hashedEntry is found in table + bool found(const Key&) const; + + //- Find and return an iterator set at the hashedEntry + // If not found iterator = end() + iterator find(const Key&); + + //- Find and return an const_iterator set at the hashedEntry + // If not found iterator = end() + const_iterator find(const Key&) const; + + //- Return the table of contents + List<Key> toc() const; + + //- Return the table of contents as a sorted list + List<Key> sortedToc() const; + + //- Print information + Ostream& printInfo(Ostream&) const; + + // Edit + + //- Insert a new hashedEntry + inline bool insert(const Key&, const T& newElmt); + + //- Assign a new hashedEntry, overwriting existing entries + inline bool set(const Key&, const T& newElmt); + + //- Erase an hashedEntry specified by given iterator + bool erase(const iterator&); + + //- Erase an hashedEntry specified by given key if in table + bool erase(const Key&); + + //- Remove entries given by the listed keys from this HashTbl + // Return the number of elements removed + label erase(const UList<Key>&); + + //- Remove entries given by the given keys from this HashTbl + // Return the number of elements removed. + // The parameter HashTbl needs the same type of keys, but + // but the type of values held is arbitrary. + template<class AnyType> + label erase(const HashTbl<AnyType, Key, Hash>&); + + //- Resize the hash table for efficiency + void resize(const label newSize); + + //- Clear all entries from table + void clear(); + + //- Clear the table entries and the table itself. + // Equivalent to clear() followed by resize(0) + void clearStorage(); + + //- Transfer the contents of the argument table into this table + // and annull the argument table. + void transfer(HashTbl<T, Key, Hash>&); + + //- Transfer contents to the Xfer container + inline Xfer<HashTbl<T, Key, Hash> > xfer(); + + + // Member Operators + + //- Find and return an hashedEntry + inline T& operator[](const Key&); + + //- Find and return an hashedEntry + inline const T& operator[](const Key&) const; + + //- Find and return an hashedEntry, create it null if not present. + inline T& operator()(const Key&); + + //- Assignment + void operator=(const HashTbl<T, Key, Hash>&); + + //- Equality. Two hash tables are equal if all contents of first are + // also in second and vice versa. So does not depend on table size or + // order! + bool operator==(const HashTbl<T, Key, Hash>&) const; + + //- The opposite of the equality operation. Takes linear time. + bool operator!=(const HashTbl<T, Key, Hash>&) const; + + + + // STL type definitions + + //- Type of values the HashTbl contains. + typedef T value_type; + + //- Type that can be used for storing into HashTbl::value_type + // objects. This type is usually List::value_type&. + typedef T& reference; + + //- Type that can be used for storing into constant + // HashTbl::value_type objects. This type is usually const + // HashTbl::value_type&. + typedef const T& const_reference; + + //- The type that can represent the size of a HashTbl. + typedef label size_type; + + + // STL iterator + + //- An STL-conforming iterator + class iterator + { + friend class HashTbl; + friend class const_iterator; + + // Private data + + //- Reference to the HashTbl this is an iterator for + HashTbl<T, Key, Hash>& hashTable_; + + //- Current element + hashedEntry* elmtPtr_; + + //- Current hash index + label hashIndex_; + + public: + + // Constructors + + //- Construct from hash table, element and hash index + inline iterator + ( + HashTbl<T, Key, Hash>& curHashTbl, + hashedEntry* elmt, + label hashIndex + ); + + // Member operators + + inline void operator=(const iterator&); + + inline bool operator==(const iterator&) const; + inline bool operator!=(const iterator&) const; + + inline bool operator==(const const_iterator&) const; + inline bool operator!=(const const_iterator&) const; + + inline T& operator*(); + inline T& operator()(); + + inline const T& operator*() const; + inline const T& operator()() const; + + inline iterator& operator++(); + inline iterator operator++(int); + + inline const Key& key() const; + }; + + + //- iterator set to the begining of the HashTbl + inline iterator begin(); + + //- iterator set to beyond the end of the HashTbl + inline const iterator& end(); + + + // STL const_iterator + + //- An STL-conforming const_iterator + class const_iterator + { + friend class iterator; + + // Private data + + //- Reference to the HashTbl this is an iterator for + const HashTbl<T, Key, Hash>& hashTable_; + + //- Current element + const hashedEntry* elmtPtr_; + + //- Current hash index + label hashIndex_; + + + public: + + // Constructors + + //- Construct from hash table, element and hash index + inline const_iterator + ( + const HashTbl<T, Key, Hash>& curHashTbl, + const hashedEntry* elmt, + label hashIndex + ); + + //- Construct from the non-const iterator + inline const_iterator(const iterator&); + + + // Member operators + + inline void operator=(const const_iterator&); + + inline bool operator==(const const_iterator&) const; + inline bool operator!=(const const_iterator&) const; + + inline bool operator==(const iterator&) const; + inline bool operator!=(const iterator&) const; + + inline const T& operator*() const; + inline const T& operator()() const; + + inline const_iterator& operator++(); + inline const_iterator operator++(int); + + inline const Key& key() const; + }; + + + //- const_iterator set to the beginning of the HashTbl + inline const_iterator cbegin() const; + + //- const_iterator set to beyond the end of the HashTbl + inline const const_iterator& cend() const; + + //- const_iterator set to the beginning of the HashTbl + inline const_iterator begin() const; + + //- const_iterator set to beyond the end of the HashTbl + inline const const_iterator& end() const; + + + // IOstream Operator + + friend Istream& operator>> <T, Key, Hash> + ( + Istream&, + HashTbl<T, Key, Hash>& + ); + + friend Ostream& operator<< <T, Key, Hash> + ( + Ostream&, + const HashTbl<T, Key, Hash>& + ); + + +private: + + //- iterator returned by end() + iterator endIter_; + + //- const_iterator returned by end() + const_iterator endConstIter_; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +# include "HashTblI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifndef NoHashTblC +#ifdef NoRepository +# include "HashTbl.C" +#endif +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H new file mode 100644 index 00000000000..8dd27700b59 --- /dev/null +++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H @@ -0,0 +1,548 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "error.H" + +// * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +inline Foam::HashTbl<T, Key, Hash>::hashedEntry::hashedEntry +( + const Key& key, + hashedEntry* next, + const T& newEntry +) +: + key_(key), + next_(next), + obj_(newEntry) +{} + + +// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +inline Foam::label +Foam::HashTbl<T, Key, Hash>::hashKeyIndex(const Key& key) const +{ + // size is power of two - this is the modulus + return Hash()(key) & (tableSize_ - 1); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +inline Foam::label Foam::HashTbl<T, Key, Hash>::size() const +{ + return nElmts_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::empty() const +{ + return !nElmts_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::insert +( + const Key& key, + const T& newEntry +) +{ + return set(key, newEntry, true); +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::set +( + const Key& key, + const T& newEntry +) +{ + return set(key, newEntry, false); +} + + +template<class T, class Key, class Hash> +inline Foam::Xfer<Foam::HashTbl<T, Key, Hash> > +Foam::HashTbl<T, Key, Hash>::xfer() +{ + return xferMove(*this); +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +inline T& Foam::HashTbl<T, Key, Hash>::operator[](const Key& key) +{ + iterator iter = find(key); + + if (iter == end()) + { + FatalErrorIn("HashTbl<T, Key, Hash>::operator[](const Key&)") + << key << " not found in table. Valid entries: " + << toc() + << exit(FatalError); + } + + return *iter; +} + + +template<class T, class Key, class Hash> +inline const T& Foam::HashTbl<T, Key, Hash>::operator[](const Key& key) const +{ + const_iterator iter = find(key); + + if (iter == cend()) + { + FatalErrorIn("HashTbl<T, Key, Hash>::operator[](const Key&) const") + << key << " not found in table. Valid entries: " + << toc() + << exit(FatalError); + } + + return *iter; +} + + +template<class T, class Key, class Hash> +inline T& Foam::HashTbl<T, Key, Hash>::operator()(const Key& key) +{ + iterator iter = find(key); + + if (iter == end()) + { + insert(key, T()); + return *find(key); + } + else + { + return *iter; + } +} + + +// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +inline Foam::HashTbl<T, Key, Hash>::iterator::iterator +( + HashTbl<T, Key, Hash>& hashTbl, + hashedEntry* elmt, + label hashIndex +) +: + hashTable_(hashTbl), + elmtPtr_(elmt), + hashIndex_(hashIndex) +{} + + +template<class T, class Key, class Hash> +inline void Foam::HashTbl<T, Key, Hash>::iterator::operator= +( + const iterator& iter +) +{ + elmtPtr_ = iter.elmtPtr_; + hashIndex_ = iter.hashIndex_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::iterator::operator== +( + const iterator& iter +) const +{ + return elmtPtr_ == iter.elmtPtr_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::iterator::operator!= +( + const iterator& iter +) const +{ + return elmtPtr_ != iter.elmtPtr_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::iterator::operator== +( + const const_iterator& iter +) const +{ + return elmtPtr_ == iter.elmtPtr_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::iterator::operator!= +( + const const_iterator& iter +) const +{ + return elmtPtr_ != iter.elmtPtr_; +} + + +template<class T, class Key, class Hash> +inline T& +Foam::HashTbl<T, Key, Hash>::iterator::operator*() +{ + return elmtPtr_->obj_; +} + + +template<class T, class Key, class Hash> +inline T& +Foam::HashTbl<T, Key, Hash>::iterator::operator()() +{ + return elmtPtr_->obj_; +} + + +template<class T, class Key, class Hash> +inline const T& +Foam::HashTbl<T, Key, Hash>::iterator::operator*() const +{ + return elmtPtr_->obj_; +} + + +template<class T, class Key, class Hash> +inline const T& +Foam::HashTbl<T, Key, Hash>::iterator::operator()() const +{ + return elmtPtr_->obj_; +} + + +template<class T, class Key, class Hash> +inline +typename Foam::HashTbl<T, Key, Hash>::iterator& +Foam::HashTbl<T, Key, Hash>::iterator::operator++() +{ + // Check for special value from erase. (sets hashIndex to -1) + if (hashIndex_ >= 0) + { + // Do we have additional elements on the SLList? + if (elmtPtr_ && elmtPtr_->next_) + { + elmtPtr_ = elmtPtr_->next_; + return *this; + } + } + + // Step to the next table entry + while + ( + ++hashIndex_ < hashTable_.tableSize_ + && !(elmtPtr_ = hashTable_.table_[hashIndex_]) + ) + {} + + if (hashIndex_ == hashTable_.tableSize_) + { + // make end iterator + elmtPtr_ = 0; + hashIndex_ = 0; + } + return *this; +} + + +template<class T, class Key, class Hash> +inline typename Foam::HashTbl<T, Key, Hash>::iterator +Foam::HashTbl<T, Key, Hash>::iterator::operator++ +( + int +) +{ + iterator tmp = *this; + ++*this; + return tmp; +} + + +template<class T, class Key, class Hash> +inline +const Key& Foam::HashTbl<T, Key, Hash>::iterator::key() const +{ + return elmtPtr_->key_; +} + + +template<class T, class Key, class Hash> +inline typename Foam::HashTbl<T, Key, Hash>::iterator +Foam::HashTbl<T, Key, Hash>::begin() +{ + label i = 0; + + if (nElmts_) + { + while (table_ && !table_[i] && ++i < tableSize_) + {} + } + else + { + i = tableSize_; + } + + if (i == tableSize_) + { +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl is empty\n"; + } +# endif + + return HashTbl<T, Key, Hash>::endIter_; + } + else + { + return iterator(*this, table_[i], i); + } +} + + +template<class T, class Key, class Hash> +inline const typename Foam::HashTbl<T, Key, Hash>::iterator& +Foam::HashTbl<T, Key, Hash>::end() +{ + return HashTbl<T, Key, Hash>::endIter_; +} + + +// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +inline Foam::HashTbl<T, Key, Hash>::const_iterator::const_iterator +( + const HashTbl<T, Key, Hash>& hashTbl, + const hashedEntry* elmt, + label hashIndex +) +: + hashTable_(hashTbl), + elmtPtr_(elmt), + hashIndex_(hashIndex) +{} + + +template<class T, class Key, class Hash> +inline Foam::HashTbl<T, Key, Hash>::const_iterator::const_iterator +( + const iterator& iter +) +: + hashTable_(iter.hashTable_), + elmtPtr_(iter.elmtPtr_), + hashIndex_(iter.hashIndex_) +{} + + +template<class T, class Key, class Hash> +inline void Foam::HashTbl<T, Key, Hash>::const_iterator::operator= +( + const const_iterator& iter +) +{ + elmtPtr_ = iter.elmtPtr_; + hashIndex_ = iter.hashIndex_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::const_iterator::operator== +( + const const_iterator& iter +) const +{ + return elmtPtr_ == iter.elmtPtr_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::const_iterator::operator!= +( + const const_iterator& iter +) const +{ + return elmtPtr_ != iter.elmtPtr_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::const_iterator::operator== +( + const iterator& iter +) const +{ + return elmtPtr_ == iter.elmtPtr_; +} + + +template<class T, class Key, class Hash> +inline bool Foam::HashTbl<T, Key, Hash>::const_iterator::operator!= +( + const iterator& iter +) const +{ + return elmtPtr_ != iter.elmtPtr_; +} + + +template<class T, class Key, class Hash> +inline const T& +Foam::HashTbl<T, Key, Hash>::const_iterator::operator*() const +{ + return elmtPtr_->obj_; +} + +template<class T, class Key, class Hash> +inline const T& +Foam::HashTbl<T, Key, Hash>::const_iterator::operator()() const +{ + return elmtPtr_->obj_; +} + + +template<class T, class Key, class Hash> +inline +typename Foam::HashTbl<T, Key, Hash>::const_iterator& +Foam::HashTbl<T, Key, Hash>::const_iterator::operator++() +{ + if + ( + !(elmtPtr_ = elmtPtr_->next_) + && ++hashIndex_ < hashTable_.tableSize_ + && !(elmtPtr_ = hashTable_.table_[hashIndex_]) + ) + { + while + ( + ++hashIndex_ < hashTable_.tableSize_ + && !(elmtPtr_ = hashTable_.table_[hashIndex_]) + ) + {} + } + + return *this; +} + + +template<class T, class Key, class Hash> +inline typename Foam::HashTbl<T, Key, Hash>::const_iterator +Foam::HashTbl<T, Key, Hash>::const_iterator::operator++ +( + int +) +{ + const_iterator tmp = *this; + ++*this; + return tmp; +} + + +template<class T, class Key, class Hash> +inline +const Key& Foam::HashTbl<T, Key, Hash>::const_iterator::key() const +{ + return elmtPtr_->key_; +} + + +template<class T, class Key, class Hash> +inline typename Foam::HashTbl<T, Key, Hash>::const_iterator +Foam::HashTbl<T, Key, Hash>::cbegin() const +{ + label i = 0; + + if (nElmts_) + { + while (table_ && !table_[i] && ++i < tableSize_) + {} + } + else + { + i = tableSize_; + } + + if (i == tableSize_) + { +# ifdef FULLDEBUG + if (debug) + { + Info<< "HashTbl is empty\n"; + } +# endif + + return HashTbl<T, Key, Hash>::endConstIter_; + } + else + { + return const_iterator(*this, table_[i], i); + } +} + + +template<class T, class Key, class Hash> +inline const typename Foam::HashTbl<T, Key, Hash>::const_iterator& +Foam::HashTbl<T, Key, Hash>::cend() const +{ + return HashTbl<T, Key, Hash>::endConstIter_; +} + + +template<class T, class Key, class Hash> +inline typename Foam::HashTbl<T, Key, Hash>::const_iterator +Foam::HashTbl<T, Key, Hash>::begin() const +{ + return this->cbegin(); +} + + +template<class T, class Key, class Hash> +inline const typename Foam::HashTbl<T, Key, Hash>::const_iterator& +Foam::HashTbl<T, Key, Hash>::end() const +{ + return HashTbl<T, Key, Hash>::endConstIter_; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTblIO.C b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblIO.C new file mode 100644 index 00000000000..ac438f77e91 --- /dev/null +++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblIO.C @@ -0,0 +1,246 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "HashTbl.H" +#include "Istream.H" +#include "Ostream.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +Foam::HashTbl<T, Key, Hash>::HashTbl(Istream& is, const label size) +: + HashTblName(), + nElmts_(0), + tableSize_(canonicalSize(size)), + table_(new hashedEntry*[tableSize_]), + endIter_(*this, NULL, 0), + endConstIter_(*this, NULL, 0) +{ + for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++) + { + table_[hashIdx] = 0; + } + + operator>>(is, *this); +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +Foam::Ostream& +Foam::HashTbl<T, Key, Hash>::printInfo(Ostream& os) const +{ + label used = 0; + label maxChain = 0; + unsigned avgChain = 0; + + for (label hashIdx = 0; hashIdx < tableSize_; ++hashIdx) + { + label count = 0; + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + ++count; + } + + if (count) + { + ++used; + avgChain += count; + + if (maxChain < count) + { + maxChain = count; + } + } + } + + os << "HashTbl<T,Key,Hash>" + << " elements:" << size() << " slots:" << used << "/" << tableSize_ + << " chaining(avg/max):" << (used ? (float(avgChain)/used) : 0) + << "/" << maxChain << endl; + + return os; +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +template<class T, class Key, class Hash> +Foam::Istream& Foam::operator>> +( + Istream& is, + HashTbl<T, Key, Hash>& L +) +{ + is.fatalCheck("operator>>(Istream&, HashTbl<T, Key, Hash>&)"); + + // Anull list + L.clear(); + + is.fatalCheck("operator>>(Istream&, HashTbl<T, Key, Hash>&)"); + + token firstToken(is); + + is.fatalCheck + ( + "operator>>(Istream&, HashTbl<T, Key, Hash>&) : " + "reading first token" + ); + + if (firstToken.isLabel()) + { + label s = firstToken.labelToken(); + + // Read beginning of contents + char delimiter = is.readBeginList("HashTbl<T, Key, Hash>"); + + if (s) + { + if (2*s > L.tableSize_) + { + L.resize(2*s); + } + + if (delimiter == token::BEGIN_LIST) + { + for (label i=0; i<s; i++) + { + Key key; + is >> key; + L.insert(key, pTraits<T>(is)); + + is.fatalCheck + ( + "operator>>(Istream&, HashTbl<T, Key, Hash>&) : " + "reading entry" + ); + } + } + else + { + FatalIOErrorIn + ( + "operator>>(Istream&, HashTbl<T, Key, Hash>&)", + is + ) << "incorrect first token, '(', found " << firstToken.info() + << exit(FatalIOError); + } + } + + // Read end of contents + is.readEndList("HashTbl"); + } + else if (firstToken.isPunctuation()) + { + if (firstToken.pToken() != token::BEGIN_LIST) + { + FatalIOErrorIn + ( + "operator>>(Istream&, HashTbl<T, Key, Hash>&)", + is + ) << "incorrect first token, '(', found " << firstToken.info() + << exit(FatalIOError); + } + + token lastToken(is); + while + ( + !( + lastToken.isPunctuation() + && lastToken.pToken() == token::END_LIST + ) + ) + { + is.putBack(lastToken); + + Key key; + is >> key; + + T element; + is >> element; + + L.insert(key, element); + + is.fatalCheck + ( + "operator>>(Istream&, HashTbl<T, Key, Hash>&) : " + "reading entry" + ); + + is >> lastToken; + } + } + else + { + FatalIOErrorIn + ( + "operator>>(Istream&, HashTbl<T, Key, Hash>&)", + is + ) << "incorrect first token, expected <int> or '(', found " + << firstToken.info() + << exit(FatalIOError); + } + + is.fatalCheck("operator>>(Istream&, HashTbl<T, Key, Hash>&)"); + + return is; +} + + +template<class T, class Key, class Hash> +Foam::Ostream& Foam::operator<< +( + Ostream& os, + const HashTbl<T, Key, Hash>& L +) +{ + // Write size and start delimiter + os << nl << L.size() << nl << token::BEGIN_LIST << nl; + + // Write contents + for + ( + typename HashTbl<T, Key, Hash>::const_iterator iter = L.cbegin(); + iter != L.cend(); + ++iter + ) + { + os << iter.key() << token::SPACE << iter() << nl; + } + + // Write end delimiter + os << token::END_LIST; + + // Check state of IOstream + os.check("Ostream& operator<<(Ostream&, const HashTbl&)"); + + return os; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTblName.C b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblName.C new file mode 100644 index 00000000000..61e198becb2 --- /dev/null +++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblName.C @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2009 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 2 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, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "HashTbl.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(Foam::HashTblName, 0); + +// ************************************************************************* // -- GitLab