diff --git a/applications/test/HashSet/Test-hashSet.C b/applications/test/HashSet/Test-hashSet.C index 0b219f2e3d..55640829fb 100644 --- a/applications/test/HashSet/Test-hashSet.C +++ b/applications/test/HashSet/Test-hashSet.C @@ -197,8 +197,12 @@ int main(int argc, char *argv[]) Info<< "setD has no 11" << endl; } + Info<< "setB : " << flatOutput(setB) << endl; Info<< "setD : " << flatOutput(setD) << endl; + setD -= setB; + Info<< "setD -= setB : " << flatOutput(setD) << endl; + // This should not work (yet?) // setD[12] = true; diff --git a/applications/test/HashTable/Test-hashTable.C b/applications/test/HashTable/Test-hashTable.C index 31bff05b0f..173356b238 100644 --- a/applications/test/HashTable/Test-hashTable.C +++ b/applications/test/HashTable/Test-hashTable.C @@ -25,6 +25,7 @@ License #include "HashTable.H" #include "List.H" +#include "FlatOutput.H" #include "IOstreams.H" #include "IStringStream.H" #include "OStringStream.H" @@ -163,15 +164,15 @@ int main() << "\ntable2" << table2 << nl; - Info<< "\ntable3" << table3 - << "\nclearStorage table3 ... "; - table3.clearStorage(); - Info<< table3 << nl; + Info<< "\ntable3" << table2 + << "\nclearStorage table2 ... "; + table2.clearStorage(); + Info<< table2 << nl; table1 = { - {"aca", 3.0}, - {"aaw", 6.0}, + {"abc", 3.0}, + {"def", 6.0}, {"acr", 8.0}, {"aec", 10.0} }; @@ -195,6 +196,25 @@ int main() // List table1vals(table1.begin(), table1.end()); // wordList table1keys(table1.begin(), table1.end()); + Info<< "\nFrom table1: " << flatOutput(table1.sortedToc()) << nl + << "retain keys: " << flatOutput(table3.sortedToc()) << nl; + + table1.retain(table3); + Info<< "-> " << flatOutput(table1.sortedToc()) << nl; + + Info<< "Lookup non-existent" << nl; + + Info<< table1.lookup("missing-const", 1.2345e+6) + << " // const-access" << nl; + + Info<< table1("missing-inadvertent", 3.14159) + << " // (inadvertent?) non-const access" << nl; + + Info<< table1("missing-autovivify") + << " // Known auto-vivification (non-const access)" << nl; + + Info<<"\ntable1: " << table1 << endl; + Info<< "\nDone\n"; return 0; diff --git a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.C b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.C index 321b8dd5df..77ab200a42 100644 --- a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.C +++ b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.C @@ -227,16 +227,9 @@ void Foam::HashSet::operator|=(const HashSet& rhs) template -void Foam::HashSet::operator&=(const HashSet& rhs) +inline void Foam::HashSet::operator&=(const HashSet& rhs) { - // Remove elements not also found in rhs - for (iterator iter = this->begin(); iter != this->end(); ++iter) - { - if (!rhs.found(iter.key())) - { - this->erase(iter); - } - } + this->parent_type::retain(rhs); } @@ -259,13 +252,9 @@ void Foam::HashSet::operator^=(const HashSet& rhs) template -void Foam::HashSet::operator-=(const HashSet& rhs) +inline void Foam::HashSet::operator-=(const HashSet& rhs) { - // Remove rhs elements from lhs - for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) - { - this->erase(iter.key()); - } + this->parent_type::erase(rhs); } diff --git a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H index 300fc11132..d6171ad585 100644 --- a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H +++ b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H @@ -277,7 +277,7 @@ public: void operator|=(const HashSet& rhs); //- Only retain entries found in both HashSets - void operator&=(const HashSet& rhs); + inline void operator&=(const HashSet& rhs); //- Only retain unique entries (xor) void operator^=(const HashSet& rhs); @@ -289,7 +289,7 @@ public: } //- Remove entries listed in the given HashSet from this HashSet - void operator-=(const HashSet& rhs); + inline void operator-=(const HashSet& rhs); // IOstream Operator diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C index b0b96c5b19..5916a753bf 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C @@ -257,7 +257,7 @@ template bool Foam::HashTable::set ( const Key& key, - const T& newEntry, + const T& obj, const bool protect ) { @@ -284,7 +284,7 @@ bool Foam::HashTable::set if (!existing) { // Not found, insert it at the head - table_[hashIdx] = new hashedEntry(key, newEntry, table_[hashIdx]); + table_[hashIdx] = new hashedEntry(key, obj, table_[hashIdx]); nElmts_++; if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize) @@ -316,7 +316,7 @@ bool Foam::HashTable::set { // Found - overwrite existing entry // this corresponds to the Perl convention - hashedEntry* ep = new hashedEntry(key, newEntry, existing->next_); + hashedEntry* ep = new hashedEntry(key, obj, existing->next_); // Replace existing element - within list or insert at the head if (prev) @@ -450,15 +450,15 @@ Foam::label Foam::HashTable::erase const HashTable& other ) { - // Remove other keys from this table const label nTotal = this->size(); label changed = 0; - if (other.size() < nTotal) + using other_iter = + typename HashTable::const_iterator; + + if (other.size() <= nTotal) { - // other is smaller, use its keys for removal - using other_iter = - typename HashTable::const_iterator; + // The other is smaller/same-size, use its keys for removal for ( @@ -475,7 +475,7 @@ Foam::label Foam::HashTable::erase } else { - // other is same/larger: iterate ourselves and check for key in other + // We are smaller: remove if found in the other hash for ( iterator iter = begin(); @@ -494,6 +494,39 @@ Foam::label Foam::HashTable::erase } +template +template +Foam::label Foam::HashTable::retain +( + const HashTable& other +) +{ + const label nTotal = this->size(); + label changed = 0; + + if (other.empty()) + { + // Trivial case + changed = nTotal; + this->clear(); + } + else + { + // Inverted logic: remove if *not* found in the other hash + + for (iterator iter = begin(); iter != end(); ++iter) + { + if (!other.found(iter.key()) && erase(iter)) + { + ++changed; + } + } + } + + return changed; +} + + template void Foam::HashTable::resize(const label sz) { diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H index bd60050ee4..53cf8da553 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H @@ -44,6 +44,7 @@ Note SourceFiles HashTableI.H HashTable.C + HashTableCoreI.H HashTableCore.C HashTableIO.C @@ -247,7 +248,7 @@ private: //- Assign a new hash-entry to a possibly already existing key. // Return true if the new entry was set. - bool set(const Key& key, const T& newEntry, const bool protect); + bool set(const Key& key, const T& obj, const bool protect); protected: @@ -307,17 +308,20 @@ public: //- Return true if the hash table is empty inline bool empty() const; - //- Return true if hashedEntry is found in table + //- Return true if hashed entry is found in table bool found(const Key& key) const; - //- Find and return an iterator set at the hashedEntry + //- Find and return an iterator set at the hashed entry // If not found iterator = end() iterator find(const Key& key); - //- Find and return an const_iterator set at the hashedEntry + //- Find and return an const_iterator set at the hashed entry // If not found iterator = end() const_iterator find(const Key& key) const; + //- Return hashed entry if it exists, or return the given default + inline const T& lookup(const Key& key, const T& deflt) const; + //- Return the table of contents List toc() const; @@ -327,42 +331,50 @@ public: // Edit - //- Insert a new hashedEntry + //- Insert a new entry // Return true if the entry inserted, which means that it did // not previously exist in the table. - inline bool insert(const Key& key, const T& newEntry); + inline bool insert(const Key& key, const T& obj); - //- Assign a new hashedEntry, overwriting existing entries. + //- Assign a new entry, overwriting existing entries. // Returns true. - inline bool set(const Key& key, const T& newEntry); + inline bool set(const Key& key, const T& obj); - //- Erase a hashedEntry specified by given iterator + //- Erase an entry specified by given iterator // This invalidates the iterator until the next ++ operation bool erase(const iterator& iter); - //- Erase a hashedEntry specified by the given key + //- Erase an entry specified by the given key bool erase(const Key& key); - //- Remove entries given by the listed keys from this HashTable + //- Remove table entries given by the listed keys // Return the number of elements removed label erase(const UList& keys); - //- Remove entries given by the listed keys from this HashTable + //- Remove table entries given by the listed keys // Return the number of elements removed template label erase(const FixedList& keys); - //- Remove entries given by the listed keys from this HashTable + //- Remove table entries given by the listed keys // Return the number of elements removed label erase(std::initializer_list keys); - //- Remove entries given by the given keys from this HashTable + //- Remove table entries given by keys of the other hash-table. // Return the number of elements removed. - // The parameter HashTable needs the same type of key, but the + // + // The other hash-table must have the same type of key, but the // type of values held and the hashing function are arbitrary. template label erase(const HashTable& other); + //- Retain table entries given by keys of the other hash-table. + // + // The other hash-table must have the same type of key, but the + // type of values held and the hashing function are arbitrary. + template + label retain(const HashTable& other); + //- Resize the hash table for efficiency void resize(const label sz); @@ -383,10 +395,10 @@ public: // Member Operators - //- Find and return a hashedEntry + //- Find and return a hashed entry. FatalError if it does not exist. inline T& operator[](const Key& key); - //- Find and return a hashedEntry + //- Find and return a hashed entry. FatalError if it does not exist. inline const T& operator[](const Key& key) const; //- Return existing entry or create a new entry. @@ -394,6 +406,12 @@ public: // value-initialized. For primitives, this will be zero. inline T& operator()(const Key& key); + //- Return existing entry or insert a new entry. + inline T& operator()(const Key& key, const T& deflt); + + //- Return hashed entry if it exists, or return the given default + inline const T& operator()(const Key& key, const T& deflt) const; + //- Assignment void operator=(const HashTable& rhs); diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H index f8df243759..5391ca78b1 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H @@ -79,10 +79,10 @@ template inline bool Foam::HashTable::insert ( const Key& key, - const T& newEntry + const T& obj ) { - return this->set(key, newEntry, true); + return this->set(key, obj, true); } @@ -90,10 +90,10 @@ template inline bool Foam::HashTable::set ( const Key& key, - const T& newEntry + const T& obj ) { - return this->set(key, newEntry, false); + return this->set(key, obj, false); } @@ -105,6 +105,18 @@ Foam::HashTable::xfer() } +template +inline const T& Foam::HashTable::lookup +( + const Key& key, + const T& deflt +) const +{ + const_iterator iter = this->find(key); + return iter.found() ? iter.object() : deflt; +} + + // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template @@ -156,6 +168,36 @@ inline T& Foam::HashTable::operator()(const Key& key) } +template +inline T& Foam::HashTable::operator() +( + const Key& key, + const T& deflt +) +{ + iterator iter = this->find(key); + + if (iter.found()) + { + return iter.object(); + } + + this->insert(key, deflt); + return find(key).object(); +} + + +template +inline const T& Foam::HashTable::operator() +( + const Key& key, + const T& deflt +) const +{ + return this->lookup(key, deflt); +} + + // * * * * * * * * * * * * * * * iterator base * * * * * * * * * * * * * * * // template diff --git a/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTable.C b/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTable.C index 948a451d47..ec30dfc20a 100644 --- a/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTable.C +++ b/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTable.C @@ -203,7 +203,7 @@ template bool Foam::StaticHashTable::set ( const Key& key, - const T& newEntry, + const T& obj, const bool protect ) { @@ -229,7 +229,7 @@ bool Foam::StaticHashTable::set localObjects.setSize(existing+1); localKeys[existing] = key; - localObjects[existing] = newEntry; + localObjects[existing] = obj; nElmts_++; } @@ -250,7 +250,7 @@ bool Foam::StaticHashTable::set { // Found - overwrite existing entry // this corresponds to the Perl convention - objects_[hashIdx][existing] = newEntry; + objects_[hashIdx][existing] = obj; } return true; diff --git a/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTable.H b/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTable.H index 639a434d65..5b0a3ef8a5 100644 --- a/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTable.H +++ b/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTable.H @@ -121,10 +121,10 @@ class StaticHashTable //- Return the hash index of the Key within the current table size. // No checks for zero-sized tables. - inline label hashKeyIndex(const Key&) const; + inline label hashKeyIndex(const Key& key) const; //- Assign a new hashed entry to a possibly already existing key - bool set(const Key&, const T& newElmt, bool protect); + bool set(const Key& key, const T& obj, bool protect); public: diff --git a/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTableI.H b/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTableI.H index cebb3852aa..2e6b5db0ea 100644 --- a/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTableI.H +++ b/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTableI.H @@ -26,8 +26,6 @@ License #include "error.H" #include "IOstreams.H" -// * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * // - // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * // template @@ -59,10 +57,10 @@ template inline bool Foam::StaticHashTable::insert ( const Key& key, - const T& newEntry + const T& obj ) { - return set(key, newEntry, true); + return set(key, obj, true); } @@ -70,10 +68,10 @@ template inline bool Foam::StaticHashTable::set ( const Key& key, - const T& newEntry + const T& obj ) { - return set(key, newEntry, false); + return set(key, obj, false); }