diff --git a/src/foam/Make/files b/src/foam/Make/files index aa6d266f2..17a9e6590 100644 --- a/src/foam/Make/files +++ b/src/foam/Make/files @@ -81,8 +81,8 @@ coordinateSystems/coordinateRotation/axisCoordinateRotation.C primitives/random/Random.C -containers/HashTables/HashTable/HashTableName.C -containers/HashTables/StaticHashTable/StaticHashTableName.C +containers/HashTables/HashTable/HashTableCore.C +containers/HashTables/StaticHashTable/StaticHashTableCore.C containers/Lists/SortableList/ParSortableListName.C containers/Lists/PackedList/PackedListName.C containers/Lists/ListOps/ListOps.C diff --git a/src/foam/containers/HashTables/HashPtrTable/HashPtrTable.C b/src/foam/containers/HashTables/HashPtrTable/HashPtrTable.C index d51e828f8..eab7560b1 100644 --- a/src/foam/containers/HashTables/HashPtrTable/HashPtrTable.C +++ b/src/foam/containers/HashTables/HashPtrTable/HashPtrTable.C @@ -24,19 +24,13 @@ License \*---------------------------------------------------------------------------*/ #include "error.H" - #include "HashPtrTable.H" -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // Construct given initial table size template -HashPtrTable::HashPtrTable(label size) +Foam::HashPtrTable::HashPtrTable(const label size) : HashTable(size) {} @@ -44,14 +38,16 @@ HashPtrTable::HashPtrTable(label size) // Construct as copy template -HashPtrTable::HashPtrTable(const HashPtrTable& ht) +Foam::HashPtrTable::HashPtrTable +( + const HashPtrTable& ht +) : HashTable() { for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter) { - // Bug fix, Microsoft port. HJ, 21/Mar/2011 - this->insert(iter.key(), iter()->clone().ptr()); + this->insert(iter.key(), new T(**iter)); } } @@ -59,7 +55,7 @@ HashPtrTable::HashPtrTable(const HashPtrTable& ht) // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // template -HashPtrTable::~HashPtrTable() +Foam::HashPtrTable::~HashPtrTable() { clear(); } @@ -68,7 +64,7 @@ HashPtrTable::~HashPtrTable() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template -T* HashPtrTable::remove(iterator& it) +T* Foam::HashPtrTable::remove(iterator& it) { T* elemPtr = *it; HashTable::erase(it); @@ -77,7 +73,7 @@ T* HashPtrTable::remove(iterator& it) template -bool HashPtrTable::erase(iterator& it) +bool Foam::HashPtrTable::erase(iterator& it) { T* elemPtr = *it; @@ -98,7 +94,7 @@ bool HashPtrTable::erase(iterator& it) template -void HashPtrTable::clear() +void Foam::HashPtrTable::clear() { for ( @@ -117,13 +113,13 @@ void HashPtrTable::clear() // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template -void HashPtrTable::operator= +void Foam::HashPtrTable::operator= ( - const HashPtrTable& ht + const HashPtrTable& rhs ) { // Check for assignment to self - if (this == &ht) + if (this == &rhs) { FatalErrorIn ( @@ -133,20 +129,14 @@ void HashPtrTable::operator= << abort(FatalError); } - clear(); + this->clear(); - for(const_iterator iter = ht.begin(); iter != ht.end(); ++iter) + for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter) { - // Bug fix, Microsoft port. HJ, 21/Mar/2011 - insert(iter.key(), iter()->clone().ptr()); + this->insert(iter.key(), new T(**iter)); } } - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // #include "HashPtrTableIO.C" diff --git a/src/foam/containers/HashTables/HashPtrTable/HashPtrTable.H b/src/foam/containers/HashTables/HashPtrTable/HashPtrTable.H index fa710ef0f..53375a05a 100644 --- a/src/foam/containers/HashTables/HashPtrTable/HashPtrTable.H +++ b/src/foam/containers/HashTables/HashPtrTable/HashPtrTable.H @@ -50,34 +50,33 @@ class Ostream; template class HashPtrTable; -template Istream& operator>> -( - Istream&, - HashPtrTable& -); +template +Istream& operator>>(Istream&, HashPtrTable&); -template Ostream& operator<< -( - Ostream&, - const HashPtrTable& -); +template +Ostream& operator<<(Ostream&, const HashPtrTable&); /*---------------------------------------------------------------------------*\ Class HashPtrTable Declaration \*---------------------------------------------------------------------------*/ -template +template class HashPtrTable : public HashTable { - // Private member functions + // Private Member Functions //- Read from Istream using given Istream constructor class template void read(Istream&, const INew& inewt); + //- Read from dictionary using given dictionary constructor class + template + void read(const dictionary& dict, const INew& inewt); + + public: @@ -97,13 +96,16 @@ public: //- Construct from Istream using default Istream constructor class HashPtrTable(Istream&); + //- Construct from dictionary using default dictionary constructor + // class + HashPtrTable(const dictionary&); + //- Construct as copy HashPtrTable(const HashPtrTable&); - // Destructor - - ~HashPtrTable(); + //- Destructor + ~HashPtrTable(); // Member Functions @@ -119,6 +121,9 @@ public: //- Clear all entries from table void clear(); + //- Write + void write(Ostream& os) const; + // Member Operators @@ -127,7 +132,6 @@ public: // IOstream Operators -#ifndef SWIG friend Istream& operator>> ( Istream&, @@ -139,7 +143,6 @@ public: Ostream&, const HashPtrTable& ); -#endif }; diff --git a/src/foam/containers/HashTables/HashPtrTable/HashPtrTableIO.C b/src/foam/containers/HashTables/HashPtrTable/HashPtrTableIO.C index 819705e0f..f76464571 100644 --- a/src/foam/containers/HashTables/HashPtrTable/HashPtrTableIO.C +++ b/src/foam/containers/HashTables/HashPtrTable/HashPtrTableIO.C @@ -27,17 +27,13 @@ License #include "Istream.H" #include "Ostream.H" #include "INew.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ +#include "dictionary.H" // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // template template -void HashPtrTable::read(Istream& is, const INew& inewt) +void Foam::HashPtrTable::read(Istream& is, const INew& inewt) { is.fatalCheck("HashPtrTable::read(Istream&, const INew&)"); @@ -54,7 +50,7 @@ void HashPtrTable::read(Istream& is, const INew& inewt) label s = firstToken.labelToken(); // Read beginning of contents - char listDelimiter = is.readBeginList("HashPtrTable"); + char delimiter = is.readBeginList("HashPtrTable"); if (s) { @@ -63,7 +59,7 @@ void HashPtrTable::read(Istream& is, const INew& inewt) this->resize(2*s); } - if (listDelimiter == token::BEGIN_LIST) + if (delimiter == token::BEGIN_LIST) { for (label i=0; i::read(Istream& is, const INew& inewt) } -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - template template -HashPtrTable::HashPtrTable(Istream& is, const INew& inewt) +void Foam::HashPtrTable::read +( + const dictionary& dict, + const INew& inewt +) { - read(is, inewt); + forAllConstIter(dictionary, dict, iter) + { + this->insert + ( + iter().keyword(), + inewt(dict.subDict(iter().keyword())).ptr() + ); + } } template -HashPtrTable::HashPtrTable(Istream& is) +void Foam::HashPtrTable::write(Ostream& os) const { - read(is, INew()); + + for + ( + typename HashPtrTable::const_iterator + iter = this->begin(); + iter != this->end(); + ++iter + ) + { + const T* ptr = iter(); + ptr->write(os); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template +template +Foam::HashPtrTable::HashPtrTable(Istream& is, const INew& inewt) +{ + this->read(is, inewt); +} + + +template +Foam::HashPtrTable::HashPtrTable(Istream& is) +{ + this->read(is, INew()); +} + + +template +Foam::HashPtrTable::HashPtrTable(const dictionary& dict) +{ + this->read(dict, INew()); } // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // template -Istream& operator>>(Istream& is, HashPtrTable& L) +Foam::Istream& Foam::operator>>(Istream& is, HashPtrTable& L) { L.clear(); L.read(is, INew()); @@ -172,15 +212,16 @@ Istream& operator>>(Istream& is, HashPtrTable& L) template -Ostream& operator<<(Ostream& os, const HashPtrTable& L) +Foam::Ostream& Foam::operator<< +( + Ostream& os, + const HashPtrTable& L +) { - // Write size of HashPtrTable - os << nl << L.size(); + // Write size and start delimiter + os << nl << L.size() << nl << token::BEGIN_LIST << nl; - // Write beginning of contents - os << nl << token::BEGIN_LIST << nl; - - // Write HashPtrTable contents + // Write contents for ( typename HashPtrTable::const_iterator iter = L.begin(); @@ -191,7 +232,7 @@ Ostream& operator<<(Ostream& os, const HashPtrTable& L) os << iter.key() << token::SPACE << *iter() << nl; } - // Write end of contents + // Write end delimiter os << token::END_LIST; // Check state of IOstream @@ -201,8 +242,4 @@ Ostream& operator<<(Ostream& os, const HashPtrTable& L) } -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - // ************************************************************************* // diff --git a/src/foam/containers/HashTables/HashSet/HashSet.C b/src/foam/containers/HashTables/HashSet/HashSet.C index 6d327d68e..d701dd7ea 100644 --- a/src/foam/containers/HashTables/HashSet/HashSet.C +++ b/src/foam/containers/HashTables/HashSet/HashSet.C @@ -52,6 +52,24 @@ Foam::HashSet::HashSet } +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template +Foam::label Foam::HashSet::insert(const UList& lst) +{ + label count = 0; + forAll(lst, elemI) + { + if (this->insert(lst[elemI])) + { + ++count; + } + } + + return count; +} + + // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template @@ -89,7 +107,7 @@ bool Foam::HashSet::operator==(const HashSet& rhs) const template bool Foam::HashSet::operator!=(const HashSet& rhs) const { - return !(this->operator==(rhs)); + return !(operator==(rhs)); } @@ -124,7 +142,7 @@ void Foam::HashSet::operator^=(const HashSet& rhs) // Add missed rhs elements, remove duplicate elements for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) { - if (found(iter.key())) + if (this->found(iter.key())) { this->erase(iter.key()); } diff --git a/src/foam/containers/HashTables/HashSet/HashSet.H b/src/foam/containers/HashTables/HashSet/HashSet.H index bd9e5797e..fae9dbc91 100644 --- a/src/foam/containers/HashTables/HashSet/HashSet.H +++ b/src/foam/containers/HashTables/HashSet/HashSet.H @@ -128,10 +128,26 @@ public: return HashTable::insert(key, nil()); } + //- Insert keys from a UList of Key + // Return the number of new elements inserted + label insert(const UList&); + //- Same as insert (cannot overwrite nil content) bool set(const Key& key) { - return HashTable::insert(key, nil()); + return insert(key); + } + + //- Same as insert (cannot overwrite nil content) + label set(const UList& lst) + { + return insert(lst); + } + + //- Unset the specified key - same as erase + bool unset(const Key& key) + { + return HashTable::erase(key); } diff --git a/src/foam/containers/HashTables/HashTable/HashTable.C b/src/foam/containers/HashTables/HashTable/HashTable.C index 107aa5406..fd86ee0da 100644 --- a/src/foam/containers/HashTables/HashTable/HashTable.C +++ b/src/foam/containers/HashTables/HashTable/HashTable.C @@ -29,44 +29,15 @@ License #include "HashTable.H" #include "List.H" -// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // - -template -Foam::label Foam::HashTable::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 Foam::HashTable::HashTable(const label size) : - HashTableName(), + HashTableCore(), nElmts_(0), - tableSize_(canonicalSize(size)), - table_(NULL), - endIter_(*this, NULL, 0), - endConstIter_(*this, NULL, 0) + tableSize_(HashTableCore::canonicalSize(size)), + table_(NULL) { if (tableSize_) { @@ -83,12 +54,10 @@ Foam::HashTable::HashTable(const label size) template Foam::HashTable::HashTable(const HashTable& ht) : - HashTableName(), + HashTableCore(), nElmts_(0), tableSize_(ht.tableSize_), - table_(NULL), - endIter_(*this, NULL, 0), - endConstIter_(*this, NULL, 0) + table_(NULL) { if (tableSize_) { @@ -112,12 +81,10 @@ Foam::HashTable::HashTable const Xfer >& ht ) : - HashTableName(), + HashTableCore(), nElmts_(0), tableSize_(0), - table_(NULL), - endIter_(*this, NULL, 0), - endConstIter_(*this, NULL, 0) + table_(NULL) { transfer(ht()); } @@ -181,7 +148,7 @@ Foam::HashTable::find { if (key == ep->key_) { - return iterator(*this, ep, hashIdx); + return iterator(this, ep, hashIdx); } } } @@ -194,7 +161,7 @@ Foam::HashTable::find } # endif - return end(); + return iterator(); } @@ -213,7 +180,7 @@ Foam::HashTable::find { if (key == ep->key_) { - return const_iterator(*this, ep, hashIdx); + return const_iterator(this, ep, hashIdx); } } } @@ -226,23 +193,32 @@ Foam::HashTable::find } # endif - return cend(); + return const_iterator(); } -// Return the table of contents template Foam::List Foam::HashTable::toc() const { - List tofc(nElmts_); - label i = 0; + List keys(nElmts_); + label keyI = 0; for (const_iterator iter = cbegin(); iter != cend(); ++iter) { - tofc[i++] = iter.key(); + keys[keyI++] = iter.key(); } - return tofc; + return keys; +} + + +template +Foam::List Foam::HashTable::sortedToc() const +{ + List sortedLst = this->toc(); + sort(sortedLst); + + return sortedLst; } @@ -280,7 +256,7 @@ bool Foam::HashTable::set table_[hashIdx] = new hashedEntry(key, table_[hashIdx], newEntry); nElmts_++; - if (double(nElmts_)/tableSize_ > 0.8) + if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize) { # ifdef FULLDEBUG if (debug) @@ -332,18 +308,22 @@ bool Foam::HashTable::set template -bool Foam::HashTable::erase(const iterator& cit) +bool Foam::HashTable::iteratorBase::erase() { - if (cit.elmtPtr_) // note: endIter_ also has 0 elmtPtr_ + // note: entryPtr_ is NULL for end(), so this catches that too + if (entryPtr_) { - iterator& it = const_cast(cit); - - // Search element before elmtPtr_ + // Search element before entryPtr_ hashedEntry* prev = 0; - for (hashedEntry* ep = table_[it.hashIndex_]; ep; ep = ep->next_) + for + ( + hashedEntry* ep = hashTable_->table_[hashIndex_]; + ep; + ep = ep->next_ + ) { - if (ep == it.elmtPtr_) + if (ep == entryPtr_) { break; } @@ -352,98 +332,76 @@ bool Foam::HashTable::erase(const iterator& cit) if (prev) { - // Have element before elmtPtr - prev->next_ = it.elmtPtr_->next_; - delete it.elmtPtr_; - it.elmtPtr_ = prev; + // has an element before entryPtr - reposition to there + prev->next_ = entryPtr_->next_; + delete entryPtr_; + entryPtr_ = prev; } else { - // elmtPtr is first element on SLList - table_[it.hashIndex_] = it.elmtPtr_->next_; - delete it.elmtPtr_; + // entryPtr was first element on SLList + hashTable_->table_[hashIndex_] = entryPtr_->next_; + delete entryPtr_; - // Search back for previous non-zero table entry - while (--it.hashIndex_ >= 0 && !table_[it.hashIndex_]) - {} + // assign any non-NULL pointer value so it doesn't look + // like end()/cend() + entryPtr_ = reinterpret_cast(this); - 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(this); - it.hashIndex_ = -1; - } + // Mark with special hashIndex value to signal it has been rewound. + // The next increment will bring it back to the present location. + // + // From the current position 'curPos', we wish to continue at + // prevPos='curPos-1', which we mark as markPos='-curPos-1'. + // The negative lets us notice it is special, the extra '-1' + // is needed to avoid ambiguity for position '0'. + // To retrieve prevPos, we would later use '-(markPos+1) - 1' + hashIndex_ = -hashIndex_ - 1; } - nElmts_--; - -# ifdef FULLDEBUG - if (debug) - { - Info<< "HashTable::erase(iterator&) : " - << "hashedEntry " << it.elmtPtr_->key_ << " removed.\n"; - } -# endif + hashTable_->nElmts_--; return true; } else { -# ifdef FULLDEBUG - if (debug) - { - Info<< "HashTable::erase(iterator&) : " - << "cannot remove hashedEntry from hash table\n"; - } -# endif - return false; } } + +// NOTE: +// We use (const iterator&) here, but manipulate its contents anyhow. +// The parameter should be (iterator&), but then the compiler doesn't find +// it correctly and tries to call as (iterator) instead. +// +template +bool Foam::HashTable::erase(const iterator& iter) +{ + // adjust iterator after erase + return const_cast(iter).erase(); +} + + template bool Foam::HashTable::erase(const Key& key) { - iterator fnd = find(key); - - if (fnd != end()) - { - return erase(fnd); - } - else - { - return false; - } + return erase(find(key)); } template Foam::label Foam::HashTable::erase(const UList& keys) { + const label nTotal = nElmts_; label count = 0; - // Remove listed keys from this table - if (this->size()) + // Remove listed keys from this table - terminates early if possible + for (label keyI = 0; count < nTotal && keyI < keys.size(); ++keyI) { - forAll(keys, keyI) + if (erase(keys[keyI])) { - if (erase(keys[keyI])) - { - count++; - } + count++; } } @@ -477,7 +435,7 @@ Foam::label Foam::HashTable::erase template void Foam::HashTable::resize(const label sz) { - label newSize = canonicalSize(sz); + label newSize = HashTableCore::canonicalSize(sz); if (newSize == tableSize_) { @@ -492,22 +450,22 @@ void Foam::HashTable::resize(const label sz) return; } - HashTable* newTable = new HashTable(newSize); + HashTable* tmpTable = new HashTable(newSize); for (const_iterator iter = cbegin(); iter != cend(); ++iter) { - newTable->insert(iter.key(), *iter); + tmpTable->insert(iter.key(), *iter); } - label oldTableSize = tableSize_; - tableSize_ = newTable->tableSize_; - newTable->tableSize_ = oldTableSize; + label oldSize = tableSize_; + tableSize_ = tmpTable->tableSize_; + tmpTable->tableSize_ = oldSize; hashedEntry** oldTable = table_; - table_ = newTable->table_; - newTable->table_ = oldTable; + table_ = tmpTable->table_; + tmpTable->table_ = oldTable; - delete newTable; + delete tmpTable; } @@ -543,6 +501,19 @@ void Foam::HashTable::clearStorage() } +template +void Foam::HashTable::shrink() +{ + const label newSize = HashTableCore::canonicalSize(nElmts_); + + if (newSize < tableSize_) + { + // avoid having the table disappear on us + resize(newSize ? newSize : 2); + } +} + + template void Foam::HashTable::transfer(HashTable& ht) { @@ -606,18 +577,12 @@ bool Foam::HashTable::operator== const HashTable& rhs ) const { - // Are all my elements in rhs? - for (const_iterator iter = cbegin(); iter != cend(); ++iter) + // sizes (number of keys) must match + if (size() != rhs.size()) { - const_iterator fnd = rhs.find(iter.key()); - - if (fnd == rhs.cend() || fnd() != iter()) - { - return false; - } + return false; } - // Are all rhs elements in me? for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) { const_iterator fnd = find(iter.key()); @@ -627,6 +592,7 @@ bool Foam::HashTable::operator== return false; } } + return true; } diff --git a/src/foam/containers/HashTables/HashTable/HashTable.H b/src/foam/containers/HashTables/HashTable/HashTable.H index a62c35ab3..f90c2b03e 100644 --- a/src/foam/containers/HashTables/HashTable/HashTable.H +++ b/src/foam/containers/HashTables/HashTable/HashTable.H @@ -70,23 +70,59 @@ Ostream& operator<<(Ostream&, const HashTable&); /*---------------------------------------------------------------------------*\ - Class HashTableName Declaration + Class HashTableCore Declaration \*---------------------------------------------------------------------------*/ -TemplateName(HashTable); +//- Template-invariant bits for HashTable +struct HashTableCore +{ + //- Return a canonical (power-of-two) size + static label canonicalSize(const label); + + //- Maximum allowable table size + static const label maxTableSize; + + //- Construct null + HashTableCore() + {} + + //- Define template name and debug + ClassName("HashTable"); + + //- A zero-sized end iterator + struct iteratorEnd + { + //- Construct null + iteratorEnd() + {} + }; + + //- iteratorEnd set to beyond the end of any HashTable + inline static iteratorEnd cend() + { + return iteratorEnd(); + } + + //- iteratorEnd set to beyond the end of any HashTable + inline static iteratorEnd end() + { + return iteratorEnd(); + } +}; /*---------------------------------------------------------------------------*\ - Class HashTable Declaration + Class HashTable Declaration \*---------------------------------------------------------------------------*/ template class HashTable : - public HashTableName + public HashTableCore { // Private data type for table entries + //- Structure to hold a hashed entry with SLList for collisions struct hashedEntry { //- The lookup key @@ -98,18 +134,17 @@ class HashTable //- The data object T obj_; - //- Constructors + //- Construct from key, next pointer and object + inline hashedEntry(const Key&, hashedEntry* next, const T&); - //- Construct given key, next pointer and object - inline hashedEntry - ( - const Key&, - hashedEntry* next, - const T& newEntry - ); - //- Dissallow construction as copy - hashedEntry(const hashedEntry&); + private: + + //- Disallow default bitwise copy construct + hashedEntry(const hashedEntry&); + + //- Disallow default bitwise assignment + void operator=(const hashedEntry&); }; @@ -118,7 +153,7 @@ class HashTable //- The current number of elements in table label nElmts_; - //- Number of primary entries allocated in table (not necessarily used) + //- Number of primary entries allocated in table label tableSize_; //- The table of primary entries @@ -137,27 +172,32 @@ class HashTable //- Assign a new hashedEntry to a possibly already existing key bool set(const Key&, const T& newElmt, bool protect); - public: + // Forward declaration of iterators + + class iteratorBase; + class iterator; + class const_iterator; + //- Declare friendship with the HashPtrTable class template friend class HashPtrTable; + //- Declare friendship with the iteratorBase + friend class iteratorBase; - // Forward declaration of STL iterators - - class iterator; + //- Declare friendship with the iterator friend class iterator; - class const_iterator; + //- Declare friendship with the const_iterator friend class const_iterator; // Constructors //- Construct given initial table size - HashTable(const label size = 128); + explicit HashTable(const label size = 128); //- Construct from Istream HashTable(Istream&, const label size = 128); @@ -169,16 +209,18 @@ public: HashTable(const Xfer >&); - // Destructor - - ~HashTable(); + //- Destructor + ~HashTable(); // Member Functions // Access - //- Return number of elements in table. + //- The size of the underlying table + inline label capacity() const; + + //- Return number of elements in table inline label size() const; //- Return true if the hash table is empty @@ -198,9 +240,13 @@ public: //- Return the table of contents List toc() const; + //- Return the table of contents as a sorted list + List sortedToc() const; + //- Print information Ostream& printInfo(Ostream&) const; + // Edit //- Insert a new hashedEntry @@ -209,10 +255,11 @@ public: //- Assign a new hashedEntry, overwriting existing entries inline bool set(const Key&, const T& newElmt); - //- Erase an hashedEntry specified by given iterator + //- Erase a hashedEntry specified by given iterator + // This invalidates the iterator until the next operator++ bool erase(const iterator&); - //- Erase an hashedEntry specified by given key if in table + //- Erase a hashedEntry specified by the given key bool erase(const Key&); //- Remove entries given by the listed keys from this HashTable @@ -236,8 +283,11 @@ public: // Equivalent to clear() followed by resize(0) void clearStorage(); + //- Shrink the allocated table to approx. twice number of elements + void shrink(); + //- Transfer the contents of the argument table into this table - // and annull the argument table. + // and annul the argument table. void transfer(HashTable&); //- Transfer contents to the Xfer container @@ -246,27 +296,27 @@ public: // Member Operators - //- Find and return an hashedEntry + //- Find and return a hashedEntry inline T& operator[](const Key&); - //- Find and return an hashedEntry + //- Find and return a hashedEntry inline const T& operator[](const Key&) const; - //- Find and return an hashedEntry, create it null if not present. + //- Find and return a hashedEntry, create it null if not present inline T& operator()(const Key&); //- Assignment void operator=(const HashTable&); - //- 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! + //- Equality. Hash tables are equal if the keys and values are equal. + // Independent of table storage size and table order. bool operator==(const HashTable&) const; //- The opposite of the equality operation. Takes linear time. bool operator!=(const HashTable&) const; + // STL type definitions //- Type of values the HashTable contains. @@ -285,138 +335,198 @@ public: typedef label size_type; - // STL iterator + // Iterators and helpers - //- An STL-conforming iterator - class iterator + //- The iterator base for HashTable + // Note: data and functions are protected, to allow reuse by iterator + // and prevent most external usage. + // iterator and const_iterator have the same size, allowing + // us to reinterpret_cast between them (if desired) + class iteratorBase { - friend class HashTable; - friend class const_iterator; + // Private Data - // Private data - - //- Reference to the HashTable this is an iterator for - HashTable& hashTable_; + //- Pointer to the HashTable for which this is an iterator + // This also lets us use the default bitwise copy/assignment + HashTable* hashTable_; //- Current element - hashedEntry* elmtPtr_; + hashedEntry* entryPtr_; //- Current hash index label hashIndex_; + + protected: + + // Constructors + + //- Construct null - equivalent to an 'end' position + inline iteratorBase(); + + //- Construct from hash table, moving to its 'begin' position + inline explicit iteratorBase + ( + const HashTable* curHashTable + ); + + //- Construct from hash table, element and hash index + inline explicit iteratorBase + ( + const HashTable* curHashTable, + const hashedEntry* elmt, + const label hashIndex + ); + + + // Protected Member Functions + + //- Increment to the next position + inline void increment(); + + //- Erase the HashTable element at the current position + bool erase(); + + //- Return non-const access to referenced object + inline T& object(); + + //- Return const access to referenced object + inline const T& cobject() const; + + + public: + + // Member operators + + // Access + + //- Return the Key corresponding to the iterator + inline const Key& key() const; + + //- Compare hashedEntry element pointers + inline bool operator==(const iteratorBase&) const; + inline bool operator!=(const iteratorBase&) const; + + //- Compare hashedEntry to iteratorEnd pointers + inline bool operator==(const iteratorEnd& unused) const; + inline bool operator!=(const iteratorEnd& unused) const; + }; + + + //- An STL-conforming iterator + class iterator + : + public iteratorBase + { + friend class HashTable; + + // Private Member Functions + + //- Construct from hash table, moving to its 'begin' position + inline explicit iterator + ( + HashTable* curHashTable + ); + + //- Construct from hash table, element and hash index + inline explicit iterator + ( + HashTable* curHashTable, + hashedEntry* elmt, + const label hashIndex + ); + + public: // Constructors - //- Construct from hash table, element and hash index - inline iterator - ( - HashTable& curHashTable, - hashedEntry* elmt, - label hashIndex - ); + //- Construct null (end iterator) + inline iterator(); + + //- Construct end iterator + inline iterator(const iteratorEnd& unused); + // 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; - + //- Return referenced hash value inline T& operator*(); inline T& operator()(); + //- Return referenced hash value 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 HashTable + //- iterator set to the beginning of the HashTable inline iterator begin(); - //- iterator set to beyond the end of the HashTable - inline const iterator& end(); - // STL const_iterator //- An STL-conforming const_iterator class const_iterator + : + public iteratorBase { - friend class iterator; + friend class HashTable; - // Private data + // Private Member Functions - //- Reference to the HashTable this is an iterator for - const HashTable& hashTable_; + //- Construct from hash table, moving to its 'begin' position + inline explicit const_iterator + ( + const HashTable* curHashTable + ); - //- Current element - const hashedEntry* elmtPtr_; - - //- Current hash index - label hashIndex_; + //- Construct from hash table, element and hash index + inline explicit const_iterator + ( + const HashTable* curHashTable, + const hashedEntry* elmt, + const label hashIndex + ); public: // Constructors - //- Construct from hash table, element and hash index - inline const_iterator - ( - const HashTable& curHashTable, - const hashedEntry* elmt, - label hashIndex - ); + //- Construct null (end iterator) + inline const_iterator(); - //- Construct from the non-const iterator + //- Construct from iterator inline const_iterator(const iterator&); + //- Construct end iterator + inline const_iterator(const iteratorEnd& unused); + // 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; - + //- Return referenced hash value 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 HashTable inline const_iterator cbegin() const; - //- const_iterator set to beyond the end of the HashTable - inline const const_iterator& cend() const; - //- const_iterator set to the beginning of the HashTable inline const_iterator begin() const; - //- const_iterator set to beyond the end of the HashTable - inline const const_iterator& end() const; - // IOstream Operator -#ifndef SWIG friend Istream& operator>> ( Istream&, @@ -428,16 +538,6 @@ public: Ostream&, const HashTable& ); -#endif - - -private: - - //- iterator returned by end() - iterator endIter_; - - //- const_iterator returned by end() - const_iterator endConstIter_; }; diff --git a/src/foam/containers/HashTables/HashTable/HashTableName.C b/src/foam/containers/HashTables/HashTable/HashTableCore.C similarity index 65% rename from src/foam/containers/HashTables/HashTable/HashTableName.C rename to src/foam/containers/HashTables/HashTable/HashTableCore.C index 03e95b0c3..c31bb5ba6 100644 --- a/src/foam/containers/HashTables/HashTable/HashTableName.C +++ b/src/foam/containers/HashTables/HashTable/HashTableCore.C @@ -24,9 +24,48 @@ License \*---------------------------------------------------------------------------*/ #include "HashTable.H" +#include "uLabel.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // -defineTypeNameAndDebug(Foam::HashTableName, 0); +namespace Foam +{ +defineTypeNameAndDebug(HashTableCore, 0); +} + +const Foam::label Foam::HashTableCore::maxTableSize +( + Foam::HashTableCore::canonicalSize + ( + Foam::labelMax/2 + ) +); + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +Foam::label Foam::HashTableCore::canonicalSize(const label size) +{ + if (size < 1) + { + return 0; + } + + // enforce power of two + uLabel goodSize = size; + + if (goodSize & (goodSize - 1)) + { + // brute-force is fast enough + goodSize = 1; + while (goodSize < unsigned(size)) + { + goodSize <<= 1; + } + } + + return goodSize; +} + // ************************************************************************* // diff --git a/src/foam/containers/HashTables/HashTable/HashTableI.H b/src/foam/containers/HashTables/HashTable/HashTableI.H index 8aeaa5b8f..19bff973f 100644 --- a/src/foam/containers/HashTables/HashTable/HashTableI.H +++ b/src/foam/containers/HashTables/HashTable/HashTableI.H @@ -32,12 +32,12 @@ inline Foam::HashTable::hashedEntry::hashedEntry ( const Key& key, hashedEntry* next, - const T& newEntry + const T& obj ) : key_(key), next_(next), - obj_(newEntry) + obj_(obj) {} @@ -54,6 +54,13 @@ Foam::HashTable::hashKeyIndex(const Key& key) const // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +template +inline Foam::label Foam::HashTable::capacity() const +{ + return tableSize_; +} + + template inline Foam::label Foam::HashTable::size() const { @@ -75,7 +82,7 @@ inline bool Foam::HashTable::insert const T& newEntry ) { - return set(key, newEntry, true); + return this->set(key, newEntry, true); } @@ -86,7 +93,7 @@ inline bool Foam::HashTable::set const T& newEntry ) { - return set(key, newEntry, false); + return this->set(key, newEntry, false); } @@ -103,9 +110,9 @@ Foam::HashTable::xfer() template inline T& Foam::HashTable::operator[](const Key& key) { - iterator iter = find(key); + iterator iter = this->find(key); - if (iter == end()) + if (iter == this->end()) { FatalErrorIn("HashTable::operator[](const Key&)") << key << " not found in table. Valid entries: " @@ -120,9 +127,9 @@ inline T& Foam::HashTable::operator[](const Key& key) template inline const T& Foam::HashTable::operator[](const Key& key) const { - const_iterator iter = find(key); + const_iterator iter = this->find(key); - if (iter == cend()) + if (iter == this->cend()) { FatalErrorIn("HashTable::operator[](const Key&) const") << key << " not found in table. Valid entries: " @@ -137,11 +144,11 @@ inline const T& Foam::HashTable::operator[](const Key& key) const template inline T& Foam::HashTable::operator()(const Key& key) { - iterator iter = find(key); + iterator iter = this->find(key); - if (iter == end()) + if (iter == this->end()) { - insert(key, T()); + this->insert(key, T()); return *find(key); } else @@ -151,78 +158,215 @@ inline T& Foam::HashTable::operator()(const Key& key) } -// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * // +// * * * * * * * * * * * * * * * iterator base * * * * * * * * * * * * * * * // template -inline Foam::HashTable::iterator::iterator +inline Foam::HashTable::iteratorBase::iteratorBase() +: + hashTable_(0), + entryPtr_(0), + hashIndex_(0) +{} + + +template +inline Foam::HashTable::iteratorBase::iteratorBase ( - HashTable& hashTbl, - hashedEntry* elmt, - label hashIndex + const HashTable* hashTbl ) : - hashTable_(hashTbl), - elmtPtr_(elmt), + hashTable_(const_cast*>(hashTbl)), + entryPtr_(0), + hashIndex_(0) +{ + if (hashTable_->nElmts_) + { + // find first non-NULL table entry + while + ( + !(entryPtr_ = hashTable_->table_[hashIndex_]) + && ++hashIndex_ < hashTable_->tableSize_ + ) + {} + + if (hashIndex_ >= hashTable_->tableSize_) + { + // make into an end iterator + entryPtr_ = 0; + hashIndex_ = 0; + } + } +} + + +template +inline Foam::HashTable::iteratorBase::iteratorBase +( + const HashTable* hashTbl, + const hashedEntry* elmt, + const label hashIndex +) +: + hashTable_(const_cast*>(hashTbl)), + entryPtr_(const_cast(elmt)), hashIndex_(hashIndex) {} template -inline void Foam::HashTable::iterator::operator= +inline void +Foam::HashTable::iteratorBase::increment() +{ + // A negative index is a special value from erase + if (hashIndex_ < 0) + { + // the markPos='-curPos-1', but we wish to continue at 'curPos-1' + // thus use '-(markPos+1) -1' + hashIndex_ = -(hashIndex_+1) - 1; + } + else if (entryPtr_) + { + if (entryPtr_->next_) + { + // Move to next element on the SLList + entryPtr_ = entryPtr_->next_; + return; + } + } + // else + // { + // // if we reach here (entryPtr_ is NULL) it is already at the end() + // // we should probably stop + // } + + + // Step to the next table entry + while + ( + ++hashIndex_ < hashTable_->tableSize_ + && !(entryPtr_ = hashTable_->table_[hashIndex_]) + ) + {} + + if (hashIndex_ >= hashTable_->tableSize_) + { + // make into an end iterator + entryPtr_ = 0; + hashIndex_ = 0; + } +} + + +template +inline +const Key& Foam::HashTable::iteratorBase::key() const +{ + return entryPtr_->key_; +} + + +template +inline T& +Foam::HashTable::iteratorBase::object() +{ + return entryPtr_->obj_; +} + + +template +inline const T& +Foam::HashTable::iteratorBase::cobject() const +{ + return entryPtr_->obj_; +} + + +template +inline bool Foam::HashTable::iteratorBase::operator== ( - const iterator& iter + const iteratorBase& iter +) const +{ + return entryPtr_ == iter.entryPtr_; +} + + +template +inline bool Foam::HashTable::iteratorBase::operator!= +( + const iteratorBase& iter +) const +{ + return entryPtr_ != iter.entryPtr_; +} + + +template +inline bool Foam::HashTable::iteratorBase::operator== +( + const iteratorEnd& +) const +{ + return !entryPtr_; +} + + +template +inline bool Foam::HashTable::iteratorBase::operator!= +( + const iteratorEnd& +) const +{ + return entryPtr_; +} + + +// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * // + +template +inline Foam::HashTable::iterator::iterator() +: + iteratorBase() +{} + + +template +inline Foam::HashTable::iterator::iterator +( + const iteratorEnd& ) -{ - elmtPtr_ = iter.elmtPtr_; - hashIndex_ = iter.hashIndex_; -} +: + iteratorBase() +{} template -inline bool Foam::HashTable::iterator::operator== +inline Foam::HashTable::iterator::iterator ( - const iterator& iter -) const -{ - return elmtPtr_ == iter.elmtPtr_; -} + HashTable* hashTbl +) +: + iteratorBase(hashTbl) +{} template -inline bool Foam::HashTable::iterator::operator!= +inline Foam::HashTable::iterator::iterator ( - const iterator& iter -) const -{ - return elmtPtr_ != iter.elmtPtr_; -} - - -template -inline bool Foam::HashTable::iterator::operator== -( - const const_iterator& iter -) const -{ - return elmtPtr_ == iter.elmtPtr_; -} - - -template -inline bool Foam::HashTable::iterator::operator!= -( - const const_iterator& iter -) const -{ - return elmtPtr_ != iter.elmtPtr_; -} + HashTable* hashTbl, + hashedEntry* elmt, + const label hashIndex +) +: + iteratorBase(hashTbl, elmt, hashIndex) +{} template inline T& Foam::HashTable::iterator::operator*() { - return elmtPtr_->obj_; + return this->object(); } @@ -230,7 +374,7 @@ template inline T& Foam::HashTable::iterator::operator()() { - return elmtPtr_->obj_; + return this->object(); } @@ -238,7 +382,7 @@ template inline const T& Foam::HashTable::iterator::operator*() const { - return elmtPtr_->obj_; + return this->cobject(); } @@ -246,7 +390,7 @@ template inline const T& Foam::HashTable::iterator::operator()() const { - return elmtPtr_->obj_; + return this->cobject(); } @@ -255,53 +399,18 @@ inline typename Foam::HashTable::iterator& Foam::HashTable::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; - } + this->increment(); return *this; } template inline typename Foam::HashTable::iterator -Foam::HashTable::iterator::operator++ -( - int -) +Foam::HashTable::iterator::operator++(int) { - iterator tmp = *this; - ++*this; - return tmp; -} - - -template -inline -const Key& Foam::HashTable::iterator::key() const -{ - return elmtPtr_->key_; + iterator old = *this; + this->increment(); + return old; } @@ -309,135 +418,74 @@ template inline typename Foam::HashTable::iterator Foam::HashTable::begin() { - label i = 0; - - if (nElmts_) - { - while (table_ && !table_[i] && ++i < tableSize_) - {} - } - else - { - i = tableSize_; - } - - if (i == tableSize_) - { -# ifdef FULLDEBUG - if (debug) - { - Info<< "HashTable is empty\n"; - } -# endif - - return HashTable::endIter_; - } - else - { - return iterator(*this, table_[i], i); - } -} - - -template -inline const typename Foam::HashTable::iterator& -Foam::HashTable::end() -{ - return HashTable::endIter_; + return iterator(this); } // * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * // +template +inline Foam::HashTable::const_iterator::const_iterator() +: + iteratorBase() +{} + + template inline Foam::HashTable::const_iterator::const_iterator ( - const HashTable& hashTbl, + const HashTable::iterator& iter +) +: + iteratorBase(iter) +{} + + +template +inline Foam::HashTable::const_iterator::const_iterator +( + const iteratorEnd& +) +: + iteratorBase() +{} + + +template +inline Foam::HashTable::const_iterator::const_iterator +( + const HashTable* hashTbl +) +: + iteratorBase(hashTbl) +{} + + +template +inline Foam::HashTable::const_iterator::const_iterator +( + const HashTable* hashTbl, const hashedEntry* elmt, - label hashIndex + const label hashIndex ) : - hashTable_(hashTbl), - elmtPtr_(elmt), - hashIndex_(hashIndex) + iteratorBase(hashTbl, elmt, hashIndex) {} -template -inline Foam::HashTable::const_iterator::const_iterator -( - const iterator& iter -) -: - hashTable_(iter.hashTable_), - elmtPtr_(iter.elmtPtr_), - hashIndex_(iter.hashIndex_) -{} - - -template -inline void Foam::HashTable::const_iterator::operator= -( - const const_iterator& iter -) -{ - elmtPtr_ = iter.elmtPtr_; - hashIndex_ = iter.hashIndex_; -} - - -template -inline bool Foam::HashTable::const_iterator::operator== -( - const const_iterator& iter -) const -{ - return elmtPtr_ == iter.elmtPtr_; -} - - -template -inline bool Foam::HashTable::const_iterator::operator!= -( - const const_iterator& iter -) const -{ - return elmtPtr_ != iter.elmtPtr_; -} - - -template -inline bool Foam::HashTable::const_iterator::operator== -( - const iterator& iter -) const -{ - return elmtPtr_ == iter.elmtPtr_; -} - - -template -inline bool Foam::HashTable::const_iterator::operator!= -( - const iterator& iter -) const -{ - return elmtPtr_ != iter.elmtPtr_; -} - - template inline const T& Foam::HashTable::const_iterator::operator*() const { - return elmtPtr_->obj_; + return this->cobject(); } + template inline const T& Foam::HashTable::const_iterator::operator()() const { - return elmtPtr_->obj_; + return this->cobject(); } @@ -446,43 +494,18 @@ inline typename Foam::HashTable::const_iterator& Foam::HashTable::const_iterator::operator++() { - if - ( - !(elmtPtr_ = elmtPtr_->next_) - && ++hashIndex_ < hashTable_.tableSize_ - && !(elmtPtr_ = hashTable_.table_[hashIndex_]) - ) - { - while - ( - ++hashIndex_ < hashTable_.tableSize_ - && !(elmtPtr_ = hashTable_.table_[hashIndex_]) - ) - {} - } - + this->increment(); return *this; } template inline typename Foam::HashTable::const_iterator -Foam::HashTable::const_iterator::operator++ -( - int -) +Foam::HashTable::const_iterator::operator++(int) { - const_iterator tmp = *this; - ++*this; - return tmp; -} - - -template -inline -const Key& Foam::HashTable::const_iterator::key() const -{ - return elmtPtr_->key_; + const_iterator old = *this; + this->increment(); + return old; } @@ -490,41 +513,7 @@ template inline typename Foam::HashTable::const_iterator Foam::HashTable::cbegin() const { - label i = 0; - - if (nElmts_) - { - while (table_ && !table_[i] && ++i < tableSize_) - {} - } - else - { - i = tableSize_; - } - - if (i == tableSize_) - { -# ifdef FULLDEBUG - if (debug) - { - Info<< "HashTable is empty\n"; - } -# endif - - return HashTable::endConstIter_; - } - else - { - return const_iterator(*this, table_[i], i); - } -} - - -template -inline const typename Foam::HashTable::const_iterator& -Foam::HashTable::cend() const -{ - return HashTable::endConstIter_; + return const_iterator(this); } @@ -536,12 +525,4 @@ Foam::HashTable::begin() const } -template -inline const typename Foam::HashTable::const_iterator& -Foam::HashTable::end() const -{ - return HashTable::endConstIter_; -} - - // ************************************************************************* // diff --git a/src/foam/containers/HashTables/HashTable/HashTableIO.C b/src/foam/containers/HashTables/HashTable/HashTableIO.C index 04367c4ff..9c3bfee4a 100644 --- a/src/foam/containers/HashTables/HashTable/HashTableIO.C +++ b/src/foam/containers/HashTables/HashTable/HashTableIO.C @@ -32,16 +32,19 @@ License template Foam::HashTable::HashTable(Istream& is, const label size) : - HashTableName(), + HashTableCore(), nElmts_(0), - tableSize_(canonicalSize(size)), - table_(new hashedEntry*[tableSize_]), - endIter_(*this, NULL, 0), - endConstIter_(*this, NULL, 0) + tableSize_(HashTableCore::canonicalSize(size)), + table_(NULL) { - for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++) + if (tableSize_) { - table_[hashIdx] = 0; + table_ = new hashedEntry*[tableSize_]; + + for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++) + { + table_[hashIdx] = 0; + } } operator>>(is, *this); diff --git a/src/foam/containers/HashTables/StaticHashTable/StaticHashTable.C b/src/foam/containers/HashTables/StaticHashTable/StaticHashTable.C index 0dafd4dee..401f373bc 100644 --- a/src/foam/containers/HashTables/StaticHashTable/StaticHashTable.C +++ b/src/foam/containers/HashTables/StaticHashTable/StaticHashTable.C @@ -32,8 +32,7 @@ License // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // -template -Foam::label Foam::StaticHashTable::canonicalSize(const label size) +Foam::label Foam::StaticHashTableCore::canonicalSize(const label size) { if (size < 1) { @@ -63,8 +62,8 @@ Foam::label Foam::StaticHashTable::canonicalSize(const label size) template Foam::StaticHashTable::StaticHashTable(const label size) : - StaticHashTableName(), - keys_(canonicalSize(size)), + StaticHashTableCore(), + keys_(StaticHashTableCore::canonicalSize(size)), objects_(keys_.size()), nElmts_(0), endIter_(*this, keys_.size(), 0), @@ -88,7 +87,7 @@ Foam::StaticHashTable::StaticHashTable const StaticHashTable& ht ) : - StaticHashTableName(), + StaticHashTableCore(), keys_(ht.keys_), objects_(ht.objects_), nElmts_(ht.nElmts_), @@ -97,14 +96,13 @@ Foam::StaticHashTable::StaticHashTable {} - template Foam::StaticHashTable::StaticHashTable ( - const Xfer< StaticHashTable >& ht + const Xfer >& ht ) : - StaticHashTableName(), + StaticHashTableCore(), keys_(0), objects_(0), nElmts_(0), @@ -223,15 +221,15 @@ Foam::StaticHashTable::find template Foam::List Foam::StaticHashTable::toc() const { - List tofc(nElmts_); - label i = 0; + List keys(nElmts_); + label keyI = 0; for (const_iterator iter = cbegin(); iter != cend(); ++iter) { - tofc[i++] = iter.key(); + keys[keyI++] = iter.key(); } - return tofc; + return keys; } @@ -318,24 +316,9 @@ bool Foam::StaticHashTable::erase(const iterator& cit) if (it.elemIndex_ < 0) { // No previous element in the local list - - // Search back for previous non-zero table entry - while (--it.hashIndex_ >= 0 && !objects_[it.hashIndex_].size()) - {} - - if (it.hashIndex_ >= 0) - { - // The last element in the local list - it.elemIndex_ = objects_[it.hashIndex_].size() - 1; - } - else - { - // No previous found. Mark with special value which is - // - not end() - // - handled by operator++ - it.hashIndex_ = -1; - it.elemIndex_ = 0; - } + // Mark with as special value (see notes in HashTable) + it.hashIndex_ = -it.hashIndex_ - 1; + it.elemIndex_ = 0; } nElmts_--; @@ -406,7 +389,7 @@ Foam::label Foam::StaticHashTable::erase template void Foam::StaticHashTable::resize(const label sz) { - label newSize = canonicalSize(sz); + label newSize = StaticHashTableCore::canonicalSize(sz); if (newSize == keys_.size()) { @@ -467,7 +450,6 @@ void Foam::StaticHashTable::clearStorage() } - template void Foam::StaticHashTable::transfer ( @@ -542,18 +524,8 @@ bool Foam::StaticHashTable::operator== const StaticHashTable& rhs ) const { - // Are all my elements in rhs? - for (const_iterator iter = cbegin(); iter != cend(); ++iter) - { - const_iterator fnd = rhs.find(iter.key()); + // sizes (number of keys) must match - 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()); @@ -563,6 +535,7 @@ bool Foam::StaticHashTable::operator== return false; } } + return true; } diff --git a/src/foam/containers/HashTables/StaticHashTable/StaticHashTable.H b/src/foam/containers/HashTables/StaticHashTable/StaticHashTable.H index 0a2826ce9..77e2603d0 100644 --- a/src/foam/containers/HashTables/StaticHashTable/StaticHashTable.H +++ b/src/foam/containers/HashTables/StaticHashTable/StaticHashTable.H @@ -72,10 +72,31 @@ template Ostream& operator<< /*---------------------------------------------------------------------------*\ - Class StaticHashTableName Declaration + Class StaticHashTableCore Declaration \*---------------------------------------------------------------------------*/ -TemplateName(StaticHashTable); +//- Template-invariant bits for StaticHashTable +struct StaticHashTableCore +{ + //- Return a canonical (power-of-two) size + static label canonicalSize(const label); + + //- Construct null + StaticHashTableCore() + {} + + //- Define template name and debug + ClassName("StaticHashTable"); + + //- A zero-sized end iterator + struct iteratorEnd + { + //- Construct null + iteratorEnd() + {} + }; +}; + /*---------------------------------------------------------------------------*\ @@ -85,7 +106,7 @@ TemplateName(StaticHashTable); template class StaticHashTable : - public StaticHashTableName + public StaticHashTableCore { // Private data type for table entries @@ -108,6 +129,7 @@ class StaticHashTable //- Assign a new hashed entry to a possibly already existing key bool set(const Key&, const T& newElmt, bool protect); + public: @@ -156,11 +178,11 @@ public: StaticHashTable(const StaticHashTable&); //- Construct by transferring the parameter contents - StaticHashTable(const Xfer< StaticHashTable >&); + StaticHashTable(const Xfer >&); - // Destructor - ~StaticHashTable(); + //- Destructor + ~StaticHashTable(); // Member Functions @@ -220,11 +242,11 @@ public: void clearStorage(); //- Transfer the contents of the argument table into this table - // and annull the argument table. + // and annul the argument table. void transfer(StaticHashTable&); //- Transfer contents to the Xfer container - inline Xfer< StaticHashTable > xfer(); + inline Xfer > xfer(); // Member Operators @@ -248,6 +270,7 @@ public: //- The opposite of the equality operation. bool operator!=(const StaticHashTable&) const; + // STL type definitions //- Type of values the StaticHashTable contains. @@ -290,6 +313,7 @@ public: //- Index of current element at hashIndex label elemIndex_; + public: // Constructors diff --git a/src/foam/containers/HashTables/StaticHashTable/StaticHashTableName.C b/src/foam/containers/HashTables/StaticHashTable/StaticHashTableCore.C similarity index 95% rename from src/foam/containers/HashTables/StaticHashTable/StaticHashTableName.C rename to src/foam/containers/HashTables/StaticHashTable/StaticHashTableCore.C index 9ec16b7ca..9fabfe8e0 100644 --- a/src/foam/containers/HashTables/StaticHashTable/StaticHashTableName.C +++ b/src/foam/containers/HashTables/StaticHashTable/StaticHashTableCore.C @@ -27,6 +27,10 @@ License // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // -defineTypeNameAndDebug(Foam::StaticHashTableName, 0); +namespace Foam +{ +defineTypeNameAndDebug(StaticHashTableCore, 0); +} + // ************************************************************************* // diff --git a/src/foam/containers/HashTables/StaticHashTable/StaticHashTableI.H b/src/foam/containers/HashTables/StaticHashTable/StaticHashTableI.H index c7bbb38da..2c59db4ad 100644 --- a/src/foam/containers/HashTables/StaticHashTable/StaticHashTableI.H +++ b/src/foam/containers/HashTables/StaticHashTable/StaticHashTableI.H @@ -78,7 +78,7 @@ inline bool Foam::StaticHashTable::set template -inline Foam::Xfer< Foam::StaticHashTable > +inline Foam::Xfer > Foam::StaticHashTable::xfer() { return xferMove(*this); @@ -266,8 +266,13 @@ Foam::StaticHashTable::Iterator TableRef >::operator++() { - // Check for special value from erase. (sets hashIndex to -1) - if (hashIndex_ >= 0) + // A negative index is a special value from erase + // (see notes in HashTable) + if (hashIndex_ < 0) + { + hashIndex_ = -(hashIndex_+1) - 1; + } + else { // Try the next element on the local list elemIndex_++; @@ -411,6 +416,4 @@ Foam::StaticHashTable::end() const } -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - // ************************************************************************* // diff --git a/src/foam/containers/HashTables/StaticHashTable/StaticHashTableIO.C b/src/foam/containers/HashTables/StaticHashTable/StaticHashTableIO.C index e71184f84..6307d55e8 100644 --- a/src/foam/containers/HashTables/StaticHashTable/StaticHashTableIO.C +++ b/src/foam/containers/HashTables/StaticHashTable/StaticHashTableIO.C @@ -36,9 +36,9 @@ Foam::StaticHashTable::StaticHashTable const label size ) : - StaticHashTableName(), - keys_(size), - objects_(size), + StaticHashTableCore(), + keys_(StaticHashTableCore::canonicalSize(size)), + objects_(StaticHashTableCore::canonicalSize(size)), nElmts_(0), endIter_(*this, keys_.size(), 0), endConstIter_(*this, keys_.size(), 0)