From 8eefc7b347b9d5c94dfce1751cbff4cbca140774 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 8 Jan 2019 12:25:30 +0100 Subject: [PATCH] ENH: partial reorganization of HashTable internals (#1160) - relocate the pair_entry (HashTable) and unary_entry (HashSet) into the Detail namespace and add output handling. The output handling at this level removes the reliance on zero::null output (HashSet) and allows direct support of pointers. This means that the following now works HashTable tbl; os << tbl; It also means that we don't need to overload operator<< for HashPtrTable anymore. - avoid delete/new when calling HashSet::set(). If the entry already exists there is no reason to remove it and add another one with the same content. STYLE: HashTable iterators now have a val() method - identical to the object() iterator method, but shorter to type. --- .../containers/HashTables/HashOps/HashOps.H | 4 +- .../HashTables/HashPtrTable/HashPtrTable.C | 12 +- .../HashTables/HashPtrTable/HashPtrTable.H | 9 - .../HashTables/HashPtrTable/HashPtrTableIO.C | 43 +-- .../HashTables/HashTable/HashTable.C | 60 ++--- .../HashTables/HashTable/HashTable.H | 157 +++-------- .../HashTables/HashTable/HashTableCore.C | 6 +- .../HashTables/HashTable/HashTableCore.H | 10 +- .../HashTables/HashTable/HashTableDetail.H | 247 ++++++++++++++++++ .../HashTables/HashTable/HashTableI.H | 24 +- .../HashTables/HashTable/HashTableIO.C | 48 ++-- .../HashTables/HashTable/HashTableIter.C | 2 +- .../HashTables/HashTable/HashTableIterI.H | 15 ++ .../Lists/ListOps/ListOpsTemplates.C | 10 +- 14 files changed, 383 insertions(+), 264 deletions(-) create mode 100644 src/OpenFOAM/containers/HashTables/HashTable/HashTableDetail.H diff --git a/src/OpenFOAM/containers/HashTables/HashOps/HashOps.H b/src/OpenFOAM/containers/HashTables/HashOps/HashOps.H index 8782df0810..dee518a007 100644 --- a/src/OpenFOAM/containers/HashTables/HashOps/HashOps.H +++ b/src/OpenFOAM/containers/HashTables/HashOps/HashOps.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -151,7 +151,7 @@ List values(const HashTable& tbl, const bool doSort=false) forAllConstIters(tbl, iter) { - output[i] = iter.object(); + output[i] = iter.val(); ++i; } diff --git a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.C b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.C index e9626ae2ed..1d80e537d2 100644 --- a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.C +++ b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,7 +38,7 @@ Foam::HashPtrTable::HashPtrTable { for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter) { - const T* ptr = iter.object(); + const T* ptr = iter.val(); if (ptr) { this->set(iter.key(), new T(*ptr)); @@ -77,7 +77,7 @@ Foam::autoPtr Foam::HashPtrTable::remove(iterator& iter) { if (iter.good()) { - autoPtr aptr(iter.object()); + autoPtr aptr(iter.val()); this->parent_type::erase(iter); return aptr; } @@ -99,7 +99,7 @@ bool Foam::HashPtrTable::erase(iterator& iter) { if (iter.good()) { - T* ptr = iter.object(); + T* ptr = iter.val(); if (this->parent_type::erase(iter)) { @@ -129,7 +129,7 @@ void Foam::HashPtrTable::clear() { for (iterator iter = this->begin(); iter != this->end(); ++iter) { - delete iter.object(); + delete iter.val(); } this->parent_type::clear(); @@ -155,7 +155,7 @@ void Foam::HashPtrTable::operator= for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter) { - const T* ptr = iter.object(); + const T* ptr = iter.val(); if (ptr) { this->set(iter.key(), new T(*ptr)); diff --git a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.H b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.H index 5e6b5514d1..ebfb983a81 100644 --- a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.H +++ b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTable.H @@ -54,9 +54,6 @@ template class HashPtrTable; template Istream& operator>>(Istream& is, HashPtrTable& tbl); -template -Ostream& operator<<(Ostream& os, const HashPtrTable& tbl); - /*---------------------------------------------------------------------------*\ Class HashPtrTable Declaration @@ -171,12 +168,6 @@ public: HashPtrTable& tbl ); - friend Ostream& operator<< - ( - Ostream& os, - const HashPtrTable& tbl - ); - // Housekeeping diff --git a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTableIO.C b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTableIO.C index e44b20e2d5..394c31891a 100644 --- a/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTableIO.C +++ b/src/OpenFOAM/containers/HashTables/HashPtrTable/HashPtrTableIO.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -153,7 +153,7 @@ void Foam::HashPtrTable::write(Ostream& os) const { for (const_iterator iter = this->cbegin(); iter != this->cend(); ++iter) { - const T* ptr = iter.object(); + const T* ptr = iter.val(); if (ptr) { ptr->write(os); @@ -198,43 +198,4 @@ Foam::Istream& Foam::operator>>(Istream& is, HashPtrTable& tbl) } -template -Foam::Ostream& Foam::operator<< -( - Ostream& os, - const HashPtrTable& tbl -) -{ - const label len = tbl.size(); - - if (len) - { - // Size and start list delimiter - os << nl << len << nl << token::BEGIN_LIST << nl; - - // Contents - for (auto iter = tbl.cbegin(); iter != tbl.cend(); ++iter) - { - const T* ptr = iter.object(); - - os << iter.key(); - if (ptr) - { - os << token::SPACE << *ptr; - } - os << nl; - } - os << token::END_LIST; // End list delimiter - } - else - { - // Empty hash table - os << len << token::BEGIN_LIST << token::END_LIST; - } - - os.check(FUNCTION_NAME); - return os; -} - - // ************************************************************************* // diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C index f00f2adb4b..62ff6c9ae4 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -65,7 +65,7 @@ Foam::HashTable::HashTable(const HashTable& ht) { for (const_iterator iter = ht.cbegin(); iter != ht.cend(); ++iter) { - insert(iter.key(), iter.object()); + insert(iter.key(), iter.val()); } } @@ -87,12 +87,12 @@ Foam::HashTable::HashTable(HashTable&& rhs) template Foam::HashTable::HashTable ( - std::initializer_list> lst + std::initializer_list> list ) : - HashTable(2*lst.size()) + HashTable(2*list.size()) { - for (const auto& keyval : lst) + for (const auto& keyval : list) { insert(keyval.first, keyval.second); } @@ -172,7 +172,7 @@ Foam::List Foam::HashTable::tocKeys } } - list.setSize(count); + list.resize(count); Foam::sort(list); return list; @@ -192,13 +192,13 @@ Foam::List Foam::HashTable::tocValues for (const_iterator iter = cbegin(); iter != cend(); ++iter) { - if ((pred(iter.object()) ? !invert : invert)) + if ((pred(iter.val()) ? !invert : invert)) { list[count++] = iter.key(); } } - list.setSize(count); + list.resize(count); Foam::sort(list); return list; @@ -218,13 +218,13 @@ Foam::List Foam::HashTable::tocEntries for (const_iterator iter = cbegin(); iter != cend(); ++iter) { - if ((pred(iter.key(), iter.object()) ? !invert : invert)) + if ((pred(iter.key(), iter.val()) ? !invert : invert)) { list[count++] = iter.key(); } } - list.setSize(count); + list.resize(count); Foam::sort(list); return list; @@ -265,7 +265,7 @@ Foam::label Foam::HashTable::countValues for (const_iterator iter = cbegin(); iter != cend(); ++iter) { - if ((pred(iter.object()) ? !invert : invert)) + if ((pred(iter.val()) ? !invert : invert)) { ++count; } @@ -287,7 +287,7 @@ Foam::label Foam::HashTable::countEntries for (const_iterator iter = cbegin(); iter != cend(); ++iter) { - if ((pred(iter.key(), iter.object()) ? !invert : invert)) + if ((pred(iter.key(), iter.val()) ? !invert : invert)) { ++count; } @@ -334,10 +334,7 @@ bool Foam::HashTable::setEntry if (double(size_)/capacity_ > 0.8 && capacity_ < maxTableSize) { #ifdef FULLDEBUG - if (debug) - { - InfoInFunction << "Doubling table size\n"; - } + DebugInFunction << "Doubling table size\n"; #endif resize(2*capacity_); @@ -347,6 +344,13 @@ bool Foam::HashTable::setEntry { // Overwrite current entry (Perl convention). + // Can skip if the value is not stored anyhow (Eg, HashSet) + // - this avoids a useless delete/new + if (!node_type::stores_value()) + { + return true; + } + node_type* ep = curr->next_; // next in the linked list // In some cases the delete/new could be avoided in favour of move @@ -370,11 +374,7 @@ bool Foam::HashTable::setEntry { // Do not overwrite existing entry (STL 'insert' convention) #ifdef FULLDEBUG - if (debug) - { - InfoInFunction - << "Cannot insert " << key << " already in hash table\n"; - } + DebugInFunction << "Not inserting " << key << ": already in table\n"; #endif return false; } @@ -553,10 +553,7 @@ void Foam::HashTable::resize(const label sz) if (newCapacity == oldCapacity) { #ifdef FULLDEBUG - if (debug) - { - InfoInFunction << "New table size == old table size\n"; - } + DebugInFunction << "New table size == old table size\n"; #endif return; @@ -567,8 +564,7 @@ void Foam::HashTable::resize(const label sz) if (size_) { WarningInFunction - << "HashTable contains " << size_ << " cannot resize(0)" - << endl; + << "HashTable contains " << size_ << " cannot resize(0)" << nl; } else { @@ -711,7 +707,7 @@ Foam::label Foam::HashTable::filterValues // Matches? either prune (pruning) or keep (!pruning) if ( - (pred(iter.object()) ? pruning : !pruning) + (pred(iter.val()) ? pruning : !pruning) && erase(iter) ) { @@ -738,7 +734,7 @@ Foam::label Foam::HashTable::filterEntries // Matches? either prune (pruning) or keep (!pruning) if ( - (pred(iter.key(), iter.object()) ? pruning : !pruning) + (pred(iter.key(), iter.val()) ? pruning : !pruning) && erase(iter) ) { @@ -778,7 +774,7 @@ void Foam::HashTable::operator= for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) { - insert(iter.key(), iter.object()); + insert(iter.key(), iter.val()); } } @@ -840,7 +836,7 @@ bool Foam::HashTable::operator== { const const_iterator other(this->cfind(iter.key())); - if (!other.found() || other.object() != iter.object()) + if (!other.found() || other.val() != iter.val()) { return false; } @@ -873,7 +869,7 @@ Foam::HashTable& Foam::HashTable::operator+= { for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter) { - insert(iter.key(), iter.object()); + insert(iter.key(), iter.val()); } } else diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H index 8b6f4ae10a..d3f297e088 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H @@ -46,8 +46,7 @@ Description Note For historical reasons, dereferencing the table iterator (eg, \a *iter) returns a reference to the stored object value - value rather than the stored key/object value like std::unordered_map - does. + rather than the stored key/val pair like std::unordered_map does. The HashTable iterator: \code @@ -55,7 +54,7 @@ Note { Info<< "val:" << *iter << nl << "key:" << iter.key() << nl; - << "val:" << iter.object() << nl; + << "val:" << iter.val() << nl; } \endcode whereas for the \c std::unordered_map iterator: @@ -84,6 +83,7 @@ SourceFiles #include "word.H" #include "zero.H" #include "Hash.H" +#include "HashTableDetail.H" #include "HashTableCore.H" #include @@ -103,7 +103,7 @@ template class FixedList; template class HashTable; template -Istream& operator>>(Istream& is, HashTable& L); +Istream& operator>>(Istream& is, HashTable& tbl); template Ostream& operator<<(Ostream& os, const HashTable& tbl); @@ -118,118 +118,14 @@ class HashTable : public HashTableCore { - // Private types for table entries + // Types - //- Structure with a (K,V) tuple and a linked-list for collisions - // Could store key/object as std::pair, but no particular advantage - // unless the iterator dereference type changes. - struct pair_entry - { - //- Type of key - typedef Key key_type; - - //- Object content type - typedef T mapped_type; - - //- The lookup key - key_type key_; - - //- The data object - mapped_type obj_; - - //- Addressing (next in collision list) - pair_entry* next_; - - //- Construct from key, object, next pointer - pair_entry(const Key& key, const T& obj, pair_entry* next) - : - key_(key), - obj_(obj), - next_(next) - {} - - //- The key - const key_type& key() const - { - return key_; - } - - //- The mapped object - const mapped_type& mapped() const - { - return obj_; - } - mapped_type& mapped() - { - return obj_; - } - - private: - //- No copy construct - pair_entry(const pair_entry&) = delete; - - //- No copy assignment - void operator=(const pair_entry&) = delete; - }; - - - //- Structure with a single (K) value and a linked-list for collisions - struct unary_entry - { - //- Type of key - typedef Key key_type; - - //- Object content type - typedef zero::null mapped_type; - - //- Content storage type to the entry - typedef key_type value_type; - - //- The lookup key == content - key_type key_; - - //- Addressing (next in collision list) - unary_entry* next_; - - //- Construct from key, (ununsed) object, next pointer - unary_entry(const Key& key, const T&, unary_entry* next) - : - key_(key), - next_(next) - {} - - //- The key - const key_type& key() const - { - return key_; - } - - //- Dummy mapped object - const mapped_type& mapped() const - { - return zeroNullElement; - } - mapped_type& mapped() - { - return zeroNullElement; - } - - - private: - //- No copy construct - unary_entry(const unary_entry&) = delete; - - //- No copy assignment - void operator=(const unary_entry&) = delete; - }; - - - //- Hashed node with a linked-list for collisions + //- Table entry. A hashed node with a linked-list for collisions typedef typename std::conditional < std::is_same::type>::value, - unary_entry, - pair_entry + Detail::HashTableSingle, + Detail::HashTablePair >::type node_type; @@ -251,6 +147,10 @@ class HashTable // No checks for zero-sized tables. inline label hashKeyIndex(const Key& key) const; + //- Read entry (key, val) and assign + // \return True if the new entry was set. + bool addEntry(Istream& is, const bool overwrite = false); + //- Assign a new hash-entry to a possibly already existing key. // \return True if the new entry was set. bool setEntry(const Key& key, const T& obj, const bool overwrite); @@ -335,7 +235,7 @@ public: HashTable(this_type&& rhs); //- Construct from an initializer list - HashTable(std::initializer_list> lst); + HashTable(std::initializer_list> list); //- Destructor @@ -689,6 +589,9 @@ protected: //- The key associated with the iterator inline const Key& key() const; + //- Write the (key, val) pair + inline Ostream& print(Ostream& os) const; + // Member Operators @@ -742,7 +645,13 @@ protected: //- Increment to the next position inline void increment(); - //- The object associated with the iterator + //- The value associated with the iterator + inline mapped_type& val() const + { + return entry_->mapped(); + } + + //- The object (value) associated with the iterator inline mapped_type& object() const { return entry_->mapped(); @@ -793,12 +702,15 @@ public: // Member functions/operators + //- Non-const access to referenced object (value) + using Iterator::val; + //- Non-const access to referenced object using Iterator::object; //- Non-const access to referenced object - inline reference operator*() const { return this->object(); } - inline reference operator()() const { return this->object(); } + inline reference operator*() const { return this->val(); } + inline reference operator()() const { return this->val(); } inline iterator& operator++(); inline iterator operator++(int); @@ -852,12 +764,15 @@ public: // Member functions/operators - //- Const access to referenced object + //- Const access to referenced value + using Iterator::val; + + //- Const access to referenced object (value) using Iterator::object; - //- Const access to referenced object - inline reference operator*() const { return this->object(); } - inline reference operator()() const { return this->object(); } + //- Const access to referenced value + inline reference operator*() const { return this->val(); } + inline reference operator()() const { return this->val(); } inline const_iterator& operator++(); inline const_iterator operator++(int); @@ -966,7 +881,7 @@ public: friend Istream& operator>> ( Istream& is, - HashTable& L + HashTable& tbl ); friend Ostream& operator<< diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableCore.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTableCore.C index 059be27e3e..e93a23c7bc 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableCore.C +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableCore.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,14 +30,12 @@ License namespace Foam { -defineTypeNameAndDebug(HashTableCore, 0); + defineTypeNameAndDebug(HashTableCore, 0); } // Approximately labelMax/4 const Foam::label Foam::HashTableCore::maxTableSize(1L << (sizeof(label)*8-3)); -Foam::zero::null Foam::HashTableCore::zeroNullElement; - // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableCore.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTableCore.H index 76feeb2105..8c6e599d95 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableCore.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableCore.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,7 +40,6 @@ SourceFiles #include "uLabel.H" #include "className.H" #include "nullObject.H" -#include "zero.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -113,13 +112,6 @@ struct HashTableCore inline const IteratorType& end() const; inline const IteratorType& cend() const; }; - - -protected: - - //- A static zero::null for dereferencing as a dummy HashSet element - static zero::null zeroNullElement; - }; diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableDetail.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTableDetail.H new file mode 100644 index 0000000000..5d3baece87 --- /dev/null +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableDetail.H @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::Detail::HashTablePair + +Description + Internal storage type for HashTable + +SourceFiles + HashTableDetail.H + +\*---------------------------------------------------------------------------*/ + +#ifndef HashTableDetail_H +#define HashTableDetail_H + +#include "zero.H" +#include +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declarations +class Ostream; + +namespace Detail +{ + +/*---------------------------------------------------------------------------*\ + Class Detail::HashTablePair Declaration +\*---------------------------------------------------------------------------*/ + +//- Internal storage type for HashTable entries +// Structure with a (K,V) tuple and a linked-list for collisions +// Could store key/val as std::pair, but no particular advantage +// unless the iterator dereference type changes. +template +struct HashTablePair +{ + // Types + + //- Type of key + typedef Key key_type; + + //- Type of content + typedef T mapped_type; + + //- This struct stores a value + static constexpr bool stores_value() + { + return true; + } + + + // Member Data + + //- The lookup key + key_type key_; + + //- The mapped data + mapped_type val_; + + //- Addressing (next in collision list) + HashTablePair* next_; + + + // Member Functions + + //- No copy construct + HashTablePair(const HashTablePair&) = delete; + + //- No copy assignment + void operator=(const HashTablePair&) = delete; + + + //- Construct from key, value, next pointer + HashTablePair + ( + const key_type& key, + const mapped_type& val, + HashTablePair* next + ) + : + key_(key), + val_(val), + next_(next) + {} + + + //- The key + const key_type& key() const + { + return key_; + } + + //- The mapped value + const mapped_type& mapped() const + { + return val_; + } + + //- The mapped value + mapped_type& mapped() + { + return val_; + } + + //- Write (key, val) pair - for pointer types + template + typename std::enable_if::value, void>::type + print(Ostream& os) const + { + os << key_; + + if (val_) + { + os << ' ' << *val_; + } + } + + //- Write (key, val) pair - for non-pointer types + template + typename std::enable_if::value, void>::type + print(Ostream& os) const + { + os << key_ << ' ' << val_; + } +}; + + +/*---------------------------------------------------------------------------*\ + Class Detail::HashTableSingle Declaration +\*---------------------------------------------------------------------------*/ + +//- Internal storage type for HashSet entries +// Structure with a single (K) value and a linked-list for collisions +template +struct HashTableSingle +{ + // Types + + //- Type of key + typedef Key key_type; + + //- Type of content + typedef Foam::zero::null mapped_type; + + //- Content storage type to the entry + typedef key_type value_type; + + //- This struct does not store a value + static constexpr bool stores_value() + { + return false; + } + + // Member Data + + //- The lookup key == content + key_type key_; + + //- Addressing (next in collision list) + HashTableSingle* next_; + + + // Member Functions + + //- No copy construct + HashTableSingle(const HashTableSingle&) = delete; + + //- No copy assignment + void operator=(const HashTableSingle&) = delete; + + + //- Construct from key, (ununsed) value, next pointer + HashTableSingle + ( + const key_type& key, + const mapped_type&, + HashTableSingle* next + ) + : + key_(key), + next_(next) + {} + + + //- The key + const key_type& key() const + { + return key_; + } + + //- The mapped value (dummy) + const mapped_type& mapped() const + { + return Foam::zero::null::dummy; + } + + //- The mapped value (dummy) + mapped_type& mapped() + { + return Foam::zero::null::dummy; + } + + //- Write the key. There is no value + void print(Ostream& os) const + { + os << key_; + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Detail +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H index 47b1b0a91d..79f5524336 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -118,10 +118,10 @@ template inline bool Foam::HashTable::insert ( const Key& key, - const T& obj + const T& val ) { - return this->setEntry(key, obj, false); // No overwrite + return this->setEntry(key, val, false); // No overwrite } @@ -129,10 +129,10 @@ template inline bool Foam::HashTable::set ( const Key& key, - const T& obj + const T& val ) { - return this->setEntry(key, obj, true); // Overwrite + return this->setEntry(key, val, true); // Overwrite } @@ -144,7 +144,7 @@ inline const T& Foam::HashTable::lookup ) const { const const_iterator iter(this->cfind(key)); - return iter.found() ? iter.object() : deflt; + return iter.found() ? iter.val() : deflt; } @@ -163,7 +163,7 @@ inline T& Foam::HashTable::operator[](const Key& key) << exit(FatalError); } - return iter.object(); + return iter.val(); } @@ -180,7 +180,7 @@ inline const T& Foam::HashTable::operator[](const Key& key) const << exit(FatalError); } - return iter.object(); + return iter.val(); } @@ -191,11 +191,11 @@ inline T& Foam::HashTable::operator()(const Key& key) if (iter.found()) { - return iter.object(); + return iter.val(); } this->insert(key, mapped_type()); - return find(key).object(); + return find(key).val(); } @@ -210,11 +210,11 @@ inline T& Foam::HashTable::operator() if (iter.found()) { - return iter.object(); + return iter.val(); } this->insert(key, deflt); - return find(key).object(); + return find(key).val(); } diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C index 9cd7c7b263..108b1f153c 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,6 +27,28 @@ License #include "Istream.H" #include "Ostream.H" +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template +bool Foam::HashTable::addEntry(Istream& is, const bool overwrite) +{ + typename node_type::key_type key; + typename node_type::mapped_type val; + + is >> key >> val; + + const bool ok = this->setEntry(key, val, overwrite); + + is.fatalCheck + ( + "HashTable::addEntry(Istream&) : " + "reading entry" + ); + + return ok; +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template @@ -143,8 +165,6 @@ Foam::Istream& Foam::operator>> HashTable& L ) { - is.fatalCheck(FUNCTION_NAME); - // Anull existing table L.clear(); @@ -176,15 +196,7 @@ Foam::Istream& Foam::operator>> { for (label i=0; i> key; - L.insert(key, pTraits(is)); - - is.fatalCheck - ( - "operator>>(Istream&, HashTable&) : " - "reading entry" - ); + L.addEntry(is); } } else @@ -218,15 +230,7 @@ Foam::Istream& Foam::operator>> { is.putBack(lastToken); - Key key; - is >> key; - L.insert(key, pTraits(is)); - - is.fatalCheck - ( - "operator>>(Istream&, HashTable&) : " - "reading entry" - ); + L.addEntry(is); is >> lastToken; } @@ -262,7 +266,7 @@ Foam::Ostream& Foam::operator<< // Contents for (auto iter = tbl.cbegin(); iter != tbl.cend(); ++iter) { - os << iter.key() << token::SPACE << iter.object() << nl; + iter.print(os) << nl; } os << token::END_LIST; // End list delimiter diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIter.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIter.C index 9a1b792fca..17acf8786e 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIter.C +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIter.C @@ -77,7 +77,7 @@ bool Foam::HashTable::iterator_erase } // Decrease count - size_--; + --size_; // The previous element in the singly linked list node_type* prev = nullptr; diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIterI.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIterI.H index c693df431c..66022483e6 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIterI.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIterI.H @@ -133,6 +133,21 @@ inline const Key& Foam::HashTable::Iterator::key() const } +template +template +inline Foam::Ostream& Foam::HashTable::Iterator::print +( + Ostream& os +) const +{ + if (entry_) + { + entry_->print(os); + } + return os; +} + + template template inline Foam::HashTable::Iterator::operator diff --git a/src/OpenFOAM/containers/Lists/ListOps/ListOpsTemplates.C b/src/OpenFOAM/containers/Lists/ListOps/ListOpsTemplates.C index df023d3b28..805d1b31ba 100644 --- a/src/OpenFOAM/containers/Lists/ListOps/ListOpsTemplates.C +++ b/src/OpenFOAM/containers/Lists/ListOps/ListOpsTemplates.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2015-2018 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2015-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -249,7 +249,7 @@ void Foam::inplaceMapKey // Could enforce (oldIdx < oldToNew.size()) // ... or just rely on FULLDEBUG from UList - output.insert(oldToNew[oldIdx], iter.object()); + output.insert(oldToNew[oldIdx], iter.val()); } } @@ -268,7 +268,7 @@ Foam::label Foam::inplaceMapValue for (auto iter = input.begin(); iter != input.end(); ++iter) { - const label oldIdx = iter.object(); + const label oldIdx = iter.val(); if (oldIdx >= 0) { // Could enforce (oldIdx < oldToNew.size()) @@ -278,7 +278,7 @@ Foam::label Foam::inplaceMapValue if (oldIdx != newIdx) { - iter.object() = newIdx; + iter.val() = newIdx; ++nChanged; } } @@ -304,7 +304,7 @@ Foam::label Foam::inplaceMapValue for (auto iter = input.begin(); iter != input.end(); ++iter) { - label& value = iter.object(); + label& value = iter.val(); auto mapIter = mapper.find(value); if (mapIter.found() && value != *mapIter)