diff --git a/applications/test/HashTable1/Test-HashTable1.C b/applications/test/HashTable1/Test-HashTable1.C index 6f92ffcd8f..75e4eeda2d 100644 --- a/applications/test/HashTable1/Test-HashTable1.C +++ b/applications/test/HashTable1/Test-HashTable1.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2021 OpenCFD Ltd. + Copyright (C) 2017-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,7 +33,7 @@ License #include "IOstreams.H" #include "StringStream.H" #include "ListOps.H" -#include "StringListOps.H" +#include "stringListOps.H" using namespace Foam; @@ -71,9 +71,18 @@ int main() << "table1 [" << table1.size() << "] " << endl; forAllConstIters(table1, iter) { - Info<< iter.key() << " => " << iter() << nl; + Info<< iter.key() << " => " << iter.val() << nl; } + + Info<< "\ntable1 sorted() :" << endl; + for (const auto& iter : table1.sorted()) + { + Info<< " " << iter.key() << " => " << iter.val() << nl; + } + Info<< endl; + + table1.set("acr", 108); table1.set("adx", 109); table1.set("aec", 100); @@ -82,6 +91,22 @@ int main() Info<< "\noverwrote some values table1: " << table1 << endl; + + // Test writable sorted access + for (auto& iter : table1.sorted()) + { + // Should not compile: iter.key() = "illegal"; + iter.val() *= 2; + } + + Info<< "\nInplace modified - via sorted() access :" << endl; + for (const auto& iter : table1.sorted()) + { + Info<< " " << iter.key() << " => " << iter.val() << nl; + } + Info<< endl; + + Info<< "\ntest find:" << endl; Info<< table1.find("aaa")() << nl << table1.find("aba")() << nl diff --git a/applications/test/ITstream/Test-ITstream.C b/applications/test/ITstream/Test-ITstream.C index 1503a43977..30d74df2ab 100644 --- a/applications/test/ITstream/Test-ITstream.C +++ b/applications/test/ITstream/Test-ITstream.C @@ -34,7 +34,7 @@ Description #include "argList.H" #include "ITstream.H" #include "ListOps.H" -#include "StringListOps.H" +#include "stringListOps.H" using namespace Foam; diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C index c4801b8c80..fac18c0c67 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2021 OpenCFD Ltd. + Copyright (C) 2017-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -26,12 +26,13 @@ License \*---------------------------------------------------------------------------*/ -#ifndef HashTable_C -#define HashTable_C +#ifndef Foam_HashTable_C +#define Foam_HashTable_C #include "HashTable.H" #include "List.H" #include "FixedList.H" +#include "UPtrList.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -156,6 +157,45 @@ Foam::List Foam::HashTable::sortedToc } +template +Foam::UPtrList::node_type> +Foam::HashTable::sorted() const +{ + UPtrList list(size_); + + label count = 0; + + for (const_iterator iter = cbegin(); iter != cend(); ++iter) + { + list.set(count++, iter.node()); + } + + Foam::sort(list); + + return list; +} + + +template +Foam::UPtrList::node_type> +Foam::HashTable::sorted() +{ + UPtrList list(size_); + + label count = 0; + + for (iterator iter = begin(); iter != end(); ++iter) + { + list.set(count++, iter.node()); + } + + Foam::sort(list); + + return list; +} + + + template template Foam::List Foam::HashTable::tocKeys diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H index 7296b8c18d..cbcdd84179 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H @@ -34,7 +34,8 @@ Description depends on the method used to generate the hash key index, the table capacity, insertion order etc. When the key order is important, use the sortedToc() method to obtain a list of sorted - keys and use that for further access. + keys and use that for further access, or the sorted() method + to obtain a UPtrList of entries to traverse in sorted order. Internally the table uses closed addressing into a flat storage space with collisions handled by linked-list chaining. @@ -80,8 +81,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef HashTable_H -#define HashTable_H +#ifndef Foam_HashTable_H +#define Foam_HashTable_H #include "word.H" #include "zero.H" @@ -102,6 +103,7 @@ namespace Foam template class List; template class UList; +template class UPtrList; template class FixedList; template class HashTable; @@ -120,9 +122,15 @@ class HashTable : public HashTableCore { - // Types +public: - //- Table entry. A hashed node with a linked-list for collisions + // Data Types + + //- The template instance used for this HashTable + typedef HashTable this_type; + + //- A table entry (node) that encapsulates the key/val tuple + //- with an additional linked-list entry for hash collisions typedef typename std::conditional < std::is_same::type>::value, @@ -131,42 +139,6 @@ class HashTable >::type node_type; - // Private Data - - //- The number of nodes currently stored in table - label size_; - - //- Number of nodes allocated in table - label capacity_; - - //- The table of primary nodes - node_type** table_; - - - // Private Member Functions - - //- Return the hash index of the Key within the current table size. - // No checks for zero-sized tables. - inline label hashKeyIndex(const Key& key) const; - - //- Assign a new hash-entry to a possibly already existing key. - // \return True if the new entry was set. - template - bool setEntry(const bool overwrite, const Key& key, Args&&... args); - - //- Read hash table - Istream& readTable(Istream& is); - - //- Write hash table - Ostream& writeTable(Ostream& os) const; - - -public: - - //- The template instance used for this HashTable - typedef HashTable this_type; - - // STL type definitions //- The second template parameter, type of keys used. @@ -209,6 +181,39 @@ public: //- Forward iterator with const access class const_iterator; + +private: + + // Private Data + + //- The number of nodes currently stored in table + label size_; + + //- Number of nodes allocated in table + label capacity_; + + //- The table of primary nodes + node_type** table_; + + + // Private Member Functions + + //- Return the hash index of the Key within the current table size. + // No checks for zero-sized tables. + inline label hashKeyIndex(const Key& key) const; + + //- Assign a new hash-entry to a possibly already existing key. + // \return True if the new entry was set. + template + bool setEntry(const bool overwrite, const Key& key, Args&&... args); + + //- Read hash table + Istream& readTable(Istream& is); + + //- Write hash table + Ostream& writeTable(Ostream& os) const; + + protected: //- Internally used base for iterator and const_iterator @@ -220,6 +225,7 @@ protected: //- An iterator with non-const access to HashTable internals. friend class Iterator; + public: // Constructors @@ -336,6 +342,17 @@ public: ) const; + // Sorted entries + + //- Const access to the hash-table contents in sorted order + //- (sorted by keys). + UPtrList sorted() const; + + //- Non-const access to the hash-table contents in sorted order + //- (sorted by keys). + UPtrList sorted(); + + // Counting //- Count the number of keys that satisfy the unary predicate @@ -701,6 +718,7 @@ public: using iterator_category = std::forward_iterator_tag; using difference_type = this_type::difference_type; + using node_type = this_type::node_type; using key_type = this_type::key_type; using mapped_type = this_type::mapped_type; using value_type = this_type::value_type; @@ -724,25 +742,37 @@ public: // Member Functions/Operators + //- Const access to the entry (node) + const node_type* node() const noexcept + { + return Iterator::entry_; + } + + //- Non-const access to the entry (node) + node_type* node() noexcept + { + return Iterator::entry_; + } + //- Const access to referenced object (value) - inline const_reference val() const + const_reference val() const { return Iterator::entry_->cval(); } //- Non-const access to referenced object (value) - inline reference val() + reference val() { return Iterator::entry_->val(); } //- Const access to referenced object (value) - inline const_reference operator*() const { return this->val(); } - inline const_reference operator()() const { return this->val(); } + const_reference operator*() const { return this->val(); } + const_reference operator()() const { return this->val(); } //- Non-const access to referenced object (value) - inline reference operator*() { return this->val(); } - inline reference operator()() { return this->val(); } + reference operator*() { return this->val(); } + reference operator()() { return this->val(); } inline iterator& operator++(); inline iterator operator++(int); @@ -762,6 +792,7 @@ public: using iterator_category = std::forward_iterator_tag; using difference_type = this_type::difference_type; + using node_type = this_type::node_type; using key_type = this_type::key_type; using mapped_type = const this_type::mapped_type; using value_type = const this_type::value_type; @@ -799,15 +830,21 @@ public: // Member Functions/Operators + //- Const access to the entry (node) + const node_type* node() const noexcept + { + return Iterator::entry_; + } + //- Const access to referenced object (value) - inline reference val() const + reference val() const { return Iterator::entry_->cval(); } //- Const access to referenced object (value) - inline reference operator*() const { return this->val(); } - inline reference operator()() const { return this->val(); } + reference operator*() const { return this->val(); } + reference operator()() const { return this->val(); } inline const_iterator& operator++(); inline const_iterator operator++(int); @@ -853,8 +890,8 @@ public: {} //- Return the key - inline reference operator*() const { return this->key(); } - inline reference operator()() const { return this->key(); } + reference operator*() const { return this->key(); } + reference operator()() const { return this->key(); } inline key_iterator_base& operator++() { diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableDetail.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTableDetail.H index 5272915538..dadd621297 100644 --- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableDetail.H +++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableDetail.H @@ -34,8 +34,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef HashTableDetail_H -#define HashTableDetail_H +#ifndef Foam_HashTableDetail_H +#define Foam_HashTableDetail_H #include "zero.H" #include @@ -73,13 +73,13 @@ template struct isPointerLike> : std::true_type {}; \*---------------------------------------------------------------------------*/ //- Internal storage type for HashTable entries -// Structure with a (K,V) tuple and a linked-list for collisions +// Comprises a (K,V) tuple and a linked-list entry for hash collisions. // Could store key/val as std::pair, but no particular advantage // unless the iterator dereference type changes. template struct HashTablePair { - // Types + // Data Types //- Type of key typedef K key_type; @@ -87,26 +87,26 @@ struct HashTablePair //- Type of content typedef V mapped_type; - //- This struct stores a value + //- This class stores a value static constexpr bool stores_value() noexcept { return true; } - // Member Data + // Data //- The lookup key - key_type key_; + const K key_; //- The mapped data - mapped_type val_; + V val_; //- Addressing (next in collision list) HashTablePair* next_; - // Member Functions + // Generated Methods //- No copy construct HashTablePair(const HashTablePair&) = delete; @@ -115,6 +115,8 @@ struct HashTablePair void operator=(const HashTablePair&) = delete; + // Constructors + //- Construct from next pointer, key, contents template HashTablePair @@ -130,24 +132,39 @@ struct HashTablePair {} + // Member Functions + //- The key - const key_type& key() const + const key_type& key() const noexcept { return key_; } //- Const access to the mapped value - const mapped_type& cval() const + const mapped_type& cval() const noexcept + { + return val_; + } + + //- Const access to the mapped value + const mapped_type& val() const noexcept { return val_; } //- Non-const access to the mapped value - mapped_type& val() + mapped_type& val() noexcept { return val_; } + + //- Compare keys + bool operator<(const HashTablePair& rhs) const + { + return key_ < rhs.key_; + } + //- Write (key, val) pair - for pointer types template typename std::enable_if @@ -190,38 +207,38 @@ struct HashTablePair \*---------------------------------------------------------------------------*/ //- Internal storage type for HashSet entries -// Structure with a single (K) value and a linked-list for collisions +// Comprises a single (K) value and a linked-list entry for hash collisions template struct HashTableSingle { - // Types + // Data Types //- Type of key typedef K key_type; - //- Type of content + //- Type of content (no content: placeholder) typedef Foam::zero::null mapped_type; //- Content storage type to the entry typedef key_type value_type; - //- This struct does not store a value + //- This class does not store any value static constexpr bool stores_value() noexcept { return false; } - // Member Data + // Data //- The lookup key == content - key_type key_; + const K key_; //- Addressing (next in collision list) HashTableSingle* next_; - // Member Functions + // Generated Methods //- No copy construct HashTableSingle(const HashTableSingle&) = delete; @@ -230,6 +247,8 @@ struct HashTableSingle void operator=(const HashTableSingle&) = delete; + // Constructors + //- Construct from next pointer, key, (unused) contents template HashTableSingle @@ -244,25 +263,40 @@ struct HashTableSingle {} + // Member Functions + //- The key - const key_type& key() const + const key_type& key() const noexcept { return key_; } //- Const access to the (dummy) mapped value - const mapped_type& cval() const + const mapped_type& cval() const noexcept + { + return Foam::zero::null::dummy; + } + + //- Const access to the (dummy) mapped value + const mapped_type& val() const noexcept { return Foam::zero::null::dummy; } //- Non-const access to the (dummy) mapped value - mapped_type& val() + mapped_type& val() noexcept { return Foam::zero::null::dummy; } - //- Write the key. There is no value + + //- Compare keys + bool operator<(const HashTableSingle& rhs) const + { + return key_ < rhs.key_; + } + + //- Write the key. There is no value to write. void print(Ostream& os) const { os << key_;