mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: HashSet, HashTable, HashPtrTable merge() method
- name and functionality similar to std::unordered_map (C++17). Formalizes what had been previously been implemented in IOobjectList but now manages without pointer deletion/creation.
This commit is contained in:
@ -73,6 +73,22 @@ void printMinMax(const HashSet<Key, Hash>& set)
|
||||
}
|
||||
|
||||
|
||||
template<class Key, class Hash>
|
||||
void printHashSet(const HashSet<Key, Hash>& table)
|
||||
{
|
||||
Info<< table.size() << '(' << nl;
|
||||
|
||||
for (const auto& key : table.sortedToc())
|
||||
{
|
||||
const auto iter = table.find(key);
|
||||
|
||||
Info<< " " << key << " : " << Foam::name(&(iter.key())) << nl;
|
||||
}
|
||||
|
||||
Info<< ')' << nl;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
@ -84,33 +100,33 @@ int main(int argc, char *argv[])
|
||||
<< typeid(HashSet<label>::hasher).name() << nl << nl;
|
||||
|
||||
hashedWordList words
|
||||
{
|
||||
({
|
||||
"abc",
|
||||
"def",
|
||||
"ghi"
|
||||
};
|
||||
});
|
||||
words = { "def", "ghi", "xy", "all", "end", "all" };
|
||||
|
||||
wordHashSet setA
|
||||
{
|
||||
({
|
||||
"xx",
|
||||
"yy",
|
||||
"zz"
|
||||
};
|
||||
});
|
||||
|
||||
setA = { "kjhk", "kjhk2", "abced" };
|
||||
|
||||
HashTable<label> tableA
|
||||
{
|
||||
({
|
||||
{ "value1", 1 },
|
||||
{ "value2", 2 },
|
||||
{ "value3", 3 }
|
||||
};
|
||||
});
|
||||
|
||||
HashTable<nil> tableB;
|
||||
tableB.insert("value4", nil());
|
||||
tableB.insert("value5", nil());
|
||||
tableB.insert("value6", nil());
|
||||
tableB.emplace("value4");
|
||||
tableB.emplace("value5");
|
||||
tableB.emplace("value6");
|
||||
|
||||
Info<< "tableA keys: "; tableA.writeKeys(Info) << endl;
|
||||
|
||||
@ -123,11 +139,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
Map<label> mapA
|
||||
{
|
||||
({
|
||||
{ 1, 1 },
|
||||
{ 2, 2 },
|
||||
{ 3, 3 }
|
||||
};
|
||||
});
|
||||
mapA.set(4, 4);
|
||||
|
||||
Info<< "hashedWordList: " << words << nl
|
||||
@ -185,9 +201,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
labelHashSet setB
|
||||
{
|
||||
({
|
||||
1, 11, 42
|
||||
};
|
||||
});
|
||||
|
||||
Info<<"Set with min/max:" << minMax(setB)
|
||||
<< " min:" << min(setB) << " max:" << max(setB) << nl;
|
||||
@ -309,6 +325,26 @@ int main(int argc, char *argv[])
|
||||
Info<< "setA1: " << setA1 << nl
|
||||
<< "setB1: " << setB1 << nl;
|
||||
|
||||
|
||||
// Merging
|
||||
{
|
||||
wordHashSet set0({ "abc", "kjhk", "kjhk2" });
|
||||
wordHashSet set1({ "abc", "def", "ghi", "jkl" });
|
||||
|
||||
Info<< nl
|
||||
<< "Set0" << nl;
|
||||
printHashSet(set0);
|
||||
Info<< "Set1" << nl;
|
||||
printHashSet(set1);
|
||||
|
||||
set1.merge(set0);
|
||||
|
||||
Info<< "merged 0" << nl;
|
||||
printHashSet(set0);
|
||||
Info<< "merged 1" << nl;
|
||||
printHashSet(set1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -79,26 +79,56 @@ public:
|
||||
};
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void printTable(const HashPtrTable<T, Key, Hash>& table)
|
||||
{
|
||||
Info<< table.size() << '(' << nl;
|
||||
|
||||
for (const auto& key : table.sortedToc())
|
||||
{
|
||||
const auto iter = table.find(key);
|
||||
|
||||
Info
|
||||
<< " " << iter.key() << " (" << Foam::name(&(iter.key()))
|
||||
<< ") : ";
|
||||
|
||||
if (iter.val())
|
||||
{
|
||||
Info<< *(iter.val());
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "nullptr";
|
||||
}
|
||||
|
||||
Info<< " (" << Foam::name(iter.val()) << ")" << nl;;
|
||||
}
|
||||
|
||||
Info<< ')' << nl;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
HashTable<label, Foam::string> table1
|
||||
{
|
||||
HashTable<Label, Foam::string> table0
|
||||
({
|
||||
{"abc", 123},
|
||||
{"kjhk", 10},
|
||||
{"kjhk2", 12}
|
||||
};
|
||||
});
|
||||
|
||||
Info<< "table1: " << table1 << nl
|
||||
<< "toc: " << flatOutput(table1.toc()) << nl;
|
||||
Info<< "table0: " << table0 << nl
|
||||
<< "toc: " << flatOutput(table0.toc()) << nl;
|
||||
|
||||
HashTable<label, label, Hash<label>> table2
|
||||
{
|
||||
({
|
||||
{3, 10},
|
||||
{5, 12},
|
||||
{7, 16}
|
||||
};
|
||||
});
|
||||
|
||||
Info<< "table2: " << table2 << nl
|
||||
<< "toc: " << flatOutput(table2.toc()) << nl;
|
||||
@ -127,7 +157,7 @@ int main(int argc, char *argv[])
|
||||
table1.insert("ghi", 15);
|
||||
table1.insert("jkl", 20);
|
||||
|
||||
Info<< nl << "Table toc: " << flatOutput(table1.toc()) << nl;
|
||||
Info<< nl << "Table toc: " << flatOutput(table1.sortedToc()) << nl;
|
||||
|
||||
for (const word k : { "abc" })
|
||||
{
|
||||
@ -153,16 +183,30 @@ int main(int argc, char *argv[])
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nl
|
||||
<< "Table0: " << flatOutput(table0.sortedToc()) << nl
|
||||
<< "Table1: " << flatOutput(table1.sortedToc()) << nl;
|
||||
|
||||
table1.merge(table0);
|
||||
|
||||
Info<< "merged 0: " << flatOutput(table0.sortedToc()) << nl
|
||||
<< "merged 1: " << flatOutput(table1.sortedToc()) << nl;
|
||||
}
|
||||
|
||||
{
|
||||
HashPtrTable<Label> ptable0(0);
|
||||
ptable0.emplace("abc", 123),
|
||||
ptable0.emplace("kjhk", 10);
|
||||
ptable0.emplace("kjhk2", 12);
|
||||
|
||||
HashPtrTable<Label> ptable1(0);
|
||||
ptable1.insert("abc", autoPtr<Label>::New(5));
|
||||
ptable1.insert("def", autoPtr<Label>::New(10));
|
||||
ptable1.insert("ghi", autoPtr<Label>::New(15));
|
||||
ptable1.insert("jkl", autoPtr<Label>::New(20));
|
||||
ptable1.emplace("def", 10);
|
||||
ptable1.emplace("ghi", 15);
|
||||
ptable1.emplace("jkl", 20);
|
||||
|
||||
Info<< nl << "PtrTable toc: " << flatOutput(ptable1.toc()) << nl;
|
||||
Info<< nl << "PtrTable toc: " << flatOutput(ptable1.sortedToc()) << nl;
|
||||
|
||||
for (const word k : { "abc" })
|
||||
{
|
||||
@ -242,6 +286,20 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nl
|
||||
<< "Table0" << nl;
|
||||
printTable(ptable0);
|
||||
|
||||
Info<< "Table1" << nl;
|
||||
printTable(ptable1);
|
||||
|
||||
ptable1.merge(ptable0);
|
||||
|
||||
Info<< "merged 0" << nl;
|
||||
printTable(ptable0);
|
||||
Info<< "merged 1" << nl;
|
||||
printTable(ptable1);
|
||||
|
||||
Info<< nl << "Ending scope" << nl;
|
||||
}
|
||||
|
||||
@ -277,6 +335,28 @@ int main(int argc, char *argv[])
|
||||
Info<< "got with " << (*iter).size() << nl;
|
||||
}
|
||||
|
||||
Info<< nl
|
||||
<< "Test (DIY) insert_or_assign" << nl;
|
||||
|
||||
label nKeys = 0;
|
||||
|
||||
for (const auto& key : { "abc", "foo", "mno", "xyz" })
|
||||
{
|
||||
Info<< key;
|
||||
if (ltable1.contains(key))
|
||||
{
|
||||
Info<< " : " << ltable1[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " : n/a";
|
||||
}
|
||||
|
||||
/// ltable1.insert_or_assign(key, identity(++nKeys));
|
||||
ltable1(key) = identity(++nKeys);
|
||||
|
||||
Info<< " --> " << ltable1[key] << nl;
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "\nEnd\n" << endl;
|
||||
|
||||
@ -334,7 +334,7 @@ int main(int argc, char *argv[])
|
||||
Info<< "==target==" << nl; reportDetail(objects);
|
||||
Info<< "==source==" << nl; reportDetail(other);
|
||||
|
||||
objects.merge(std::move(other));
|
||||
objects.merge(other);
|
||||
Info<< nl << "After merge" << nl;
|
||||
|
||||
Info<< "==target==" << nl; reportDetail(objects);
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -150,6 +150,30 @@ void Foam::HashPtrTable<T, Key, Hash>::clear()
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashPtrTable<T, Key, Hash>::merge
|
||||
(
|
||||
HashPtrTable<T, Key, Hash>& source
|
||||
)
|
||||
{
|
||||
// Use parent merge (of raw pointer entries)
|
||||
// and by-pass any pointer deletions etc.
|
||||
parent_type::merge(static_cast<parent_type&>(source));
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashPtrTable<T, Key, Hash>::merge
|
||||
(
|
||||
HashPtrTable<T, Key, Hash>&& source
|
||||
)
|
||||
{
|
||||
// Use parent merge (of raw pointer entries)
|
||||
// and by-pass any pointer deletions etc.
|
||||
parent_type::merge(static_cast<parent_type&>(source));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -173,6 +173,16 @@ public:
|
||||
//- Clear all entries from table and delete any allocated pointers
|
||||
void clear();
|
||||
|
||||
//- Attempts to extract entries from source parameter and insert them
|
||||
//- into \c this, does not overwrite existing entries.
|
||||
//- The source will contains any items that could not be merged.
|
||||
void merge(HashPtrTable<T, Key, Hash>& source);
|
||||
|
||||
//- Attempts to extract entries from source parameter and insert them
|
||||
//- into \c this, does not overwrite existing entries.
|
||||
//- The source will contains any items that could not be merged.
|
||||
void merge(HashPtrTable<T, Key, Hash>&& source);
|
||||
|
||||
|
||||
// Reading/writing
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -232,6 +232,20 @@ inline Foam::label Foam::HashSet<Key, Hash>::unset
|
||||
}
|
||||
|
||||
|
||||
template<class Key, class Hash>
|
||||
void Foam::HashSet<Key, Hash>::merge(HashSet<Key, Hash>& source)
|
||||
{
|
||||
parent_type::merge(source);
|
||||
}
|
||||
|
||||
|
||||
template<class Key, class Hash>
|
||||
void Foam::HashSet<Key, Hash>::merge(HashSet<Key, Hash>&& source)
|
||||
{
|
||||
parent_type::merge(source);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class Key, class Hash>
|
||||
|
||||
@ -197,7 +197,7 @@ public:
|
||||
//- Same as insert (no value to overwrite)
|
||||
bool set(const Key& key)
|
||||
{
|
||||
return insert(key);
|
||||
return this->parent_type::emplace(key);
|
||||
}
|
||||
|
||||
//- Unset the specified key - same as erase
|
||||
@ -207,6 +207,16 @@ public:
|
||||
return this->parent_type::erase(key);
|
||||
}
|
||||
|
||||
//- Attempts to extract entries from source parameter and insert them
|
||||
//- into \c this, does not overwrite existing entries.
|
||||
//- The source will contains any items that could not be merged.
|
||||
void merge(HashSet<Key, Hash>& source);
|
||||
|
||||
//- Attempts to extract entries from source parameter and insert them
|
||||
//- into \c this, does not overwrite existing entries.
|
||||
//- The source will contains any items that could not be merged.
|
||||
void merge(HashSet<Key, Hash>&& source);
|
||||
|
||||
|
||||
// Convenience
|
||||
|
||||
@ -370,7 +380,7 @@ public:
|
||||
//- Add entries to this HashSet
|
||||
this_type& operator|=(const this_type& rhs);
|
||||
|
||||
//- Only retain entries found in both HashSets
|
||||
//- Only retain entries contained in both HashSets
|
||||
inline this_type& operator&=(const this_type& rhs);
|
||||
|
||||
//- Only retain unique entries (xor)
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -359,7 +359,8 @@ bool Foam::HashTable<T, Key, Hash>::setEntry
|
||||
{
|
||||
if (!capacity_)
|
||||
{
|
||||
resize(2);
|
||||
// Same as default sizing
|
||||
resize(128);
|
||||
}
|
||||
|
||||
const label index = hashKeyIndex(key);
|
||||
@ -384,13 +385,9 @@ bool Foam::HashTable<T, Key, Hash>::setEntry
|
||||
new node_type(table_[index], key, std::forward<Args>(args)...);
|
||||
|
||||
++size_;
|
||||
if (double(size_)/capacity_ > 0.8 && capacity_ < maxTableSize)
|
||||
if (0.8*capacity_ < size_) // Resize after 80% fill factor
|
||||
{
|
||||
#ifdef FULLDEBUG
|
||||
DebugInFunction << "Doubling table size\n";
|
||||
#endif
|
||||
|
||||
resize(2*capacity_);
|
||||
if (capacity_ < maxTableSize) resize(2*capacity_);
|
||||
}
|
||||
}
|
||||
else if (overwrite)
|
||||
@ -425,10 +422,7 @@ bool Foam::HashTable<T, Key, Hash>::setEntry
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not overwrite existing entry (STL 'insert' convention)
|
||||
#ifdef FULLDEBUG
|
||||
DebugInFunction << "Not inserting " << key << ": already in table\n";
|
||||
#endif
|
||||
// Not overwriting existing entry
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -436,6 +430,52 @@ bool Foam::HashTable<T, Key, Hash>::setEntry
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::insert_node(node_type* entry)
|
||||
{
|
||||
if (!entry) return;
|
||||
|
||||
if (!capacity_)
|
||||
{
|
||||
// Same as default sizing
|
||||
resize(128);
|
||||
}
|
||||
|
||||
const label index = hashKeyIndex(entry->key());
|
||||
|
||||
node_type* curr = nullptr;
|
||||
//node_type* prev = nullptr;
|
||||
|
||||
for (node_type* ep = table_[index]; ep; ep = ep->next_)
|
||||
{
|
||||
if (entry->key() == ep->key())
|
||||
{
|
||||
curr = ep;
|
||||
break;
|
||||
}
|
||||
//prev = ep;
|
||||
}
|
||||
|
||||
if (!curr)
|
||||
{
|
||||
// Not found, insert it at the head
|
||||
table_[index] = entry;
|
||||
|
||||
++size_;
|
||||
if (0.8*capacity_ < size_) // Resize after 80% fill factor
|
||||
{
|
||||
if (capacity_ < maxTableSize) resize(2*capacity_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Not inserting " << entry->key() << ": already in table\n"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::erase(const iterator& iter)
|
||||
{
|
||||
@ -444,9 +484,7 @@ bool Foam::HashTable<T, Key, Hash>::erase(const iterator& iter)
|
||||
// The parameter should be (iterator&), but then the compiler doesn't find
|
||||
// it correctly and tries to call as (iterator) instead.
|
||||
|
||||
iterator& it = const_cast<iterator&>(iter);
|
||||
|
||||
return iterator_erase(it.entry_, it.index_);
|
||||
return iterator_erase(const_cast<iterator&>(iter));
|
||||
}
|
||||
|
||||
|
||||
@ -454,7 +492,7 @@ template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
|
||||
{
|
||||
iterator iter(find(key));
|
||||
return erase(iter);
|
||||
return iterator_erase(iter);
|
||||
}
|
||||
|
||||
|
||||
@ -605,10 +643,6 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||
|
||||
if (newCapacity == oldCapacity)
|
||||
{
|
||||
#ifdef FULLDEBUG
|
||||
DebugInFunction << "New table size == old table size\n";
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
else if (!newCapacity)
|
||||
@ -617,7 +651,8 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||
if (size_)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "HashTable contains " << size_ << " cannot resize(0)" << nl;
|
||||
<< "HashTable contains " << size_
|
||||
<< " elements, cannot resize(0)" << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -646,8 +681,7 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||
|
||||
// Move to new table[] but with new chaining.
|
||||
|
||||
label nMove = size_; // Allow early completion
|
||||
for (label i=0; nMove && i < oldCapacity; ++i)
|
||||
for (label i = 0, nPending = size_; nPending && i < oldCapacity; ++i)
|
||||
{
|
||||
for (node_type* ep = oldTable[i]; ep; /*nil*/)
|
||||
{
|
||||
@ -661,8 +695,8 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||
table_[newIdx] = ep;
|
||||
}
|
||||
|
||||
ep = next; // continue in the linked-list
|
||||
--nMove; // note any early completion
|
||||
ep = next; // continue in the linked-list
|
||||
--nPending; // note any early completion
|
||||
}
|
||||
oldTable[i] = nullptr;
|
||||
}
|
||||
@ -809,6 +843,46 @@ Foam::label Foam::HashTable<T, Key, Hash>::filterEntries
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::merge(HashTable<T, Key, Hash>& source)
|
||||
{
|
||||
// Self-merge implicitly a no-op
|
||||
|
||||
if (node_type::stores_value())
|
||||
{
|
||||
// key/val pair
|
||||
for (iterator iter = source.begin(); iter != source.end(); ++iter)
|
||||
{
|
||||
if (!contains(iter.key()))
|
||||
{
|
||||
node_type* entry = source.iterator_extract(iter);
|
||||
this->insert_node(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// key only, does not store a value.
|
||||
// Since the key is const, juggling the node does not work
|
||||
|
||||
for (iterator iter = source.begin(); iter != source.end(); ++iter)
|
||||
{
|
||||
if (emplace(iter.key()))
|
||||
{
|
||||
source.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::merge(HashTable<T, Key, Hash>&& source)
|
||||
{
|
||||
merge(source);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
|
||||
@ -206,6 +206,17 @@ private:
|
||||
template<class... Args>
|
||||
bool setEntry(const bool overwrite, const Key& key, Args&&... args);
|
||||
|
||||
//- Insert node (low-level). The node must not previously exist!
|
||||
void insert_node(node_type* entry);
|
||||
|
||||
//- Low-level entry erasure using iterator internals.
|
||||
// This invalidates the iterator until the next ++ operation.
|
||||
// \return True if the corresponding entry existed and was removed
|
||||
bool iterator_erase(iterator& iter);
|
||||
|
||||
//- Unlink node from iterator (low-level).
|
||||
node_type* iterator_extract(iterator& iter);
|
||||
|
||||
//- Read hash table
|
||||
Istream& readTable(Istream& is);
|
||||
|
||||
@ -532,6 +543,16 @@ public:
|
||||
//- Transfer contents into this table.
|
||||
void transfer(HashTable<T, Key, Hash>& rhs);
|
||||
|
||||
//- Attempts to extract entries from source parameter and insert them
|
||||
//- into \c this, does not overwrite existing entries.
|
||||
//- The source will contains any items that could not be merged.
|
||||
void merge(HashTable<T, Key, Hash>& source);
|
||||
|
||||
//- Attempts to extract entries from source parameter and insert them
|
||||
//- into \c this, does not overwrite existing entries.
|
||||
//- The source will contains any items that could not be merged.
|
||||
void merge(HashTable<T, Key, Hash>&& source);
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
@ -714,11 +735,6 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
//- Low-level entry erasure using iterator internals.
|
||||
// This invalidates the iterator until the next ++ operation.
|
||||
// \return True if the corresponding entry existed and was removed
|
||||
bool iterator_erase(node_type*& entry, label& index);
|
||||
|
||||
public:
|
||||
|
||||
//- Forward iterator with non-const access
|
||||
|
||||
@ -198,6 +198,32 @@ inline bool Foam::HashTable<T, Key, Hash>::set
|
||||
}
|
||||
|
||||
|
||||
// FUTURE?
|
||||
// If 'key' already exists, assign \c std::forward<T>(obj) to the
|
||||
// entry. If it does not exist, uses insert()
|
||||
//
|
||||
// template<class T, class Key, class Hash>
|
||||
// inline void Foam::HashTable<T, Key, Hash>::insert_or_assign
|
||||
// (
|
||||
// const Key& key,
|
||||
// T&& obj
|
||||
// )
|
||||
// {
|
||||
// iterator iter(this->find(key));
|
||||
//
|
||||
// if (iter.good())
|
||||
// {
|
||||
// iter.val() = std::forward<T>(obj);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// this->setEntry(true, key, std::forward<T>(obj));
|
||||
// // iter = this->find(key);
|
||||
// }
|
||||
// // return iter.val();
|
||||
// }
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const T& Foam::HashTable<T, Key, Hash>::lookup
|
||||
(
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -39,7 +39,7 @@ Foam::HashTable<T, Key, Hash>::Iterator<Const>::Iterator
|
||||
container_(tbl),
|
||||
index_(0)
|
||||
{
|
||||
if (tbl->size())
|
||||
if (container_ && container_->size())
|
||||
{
|
||||
const label index = container_->hashKeyIndex(key);
|
||||
|
||||
@ -62,12 +62,11 @@ Foam::HashTable<T, Key, Hash>::Iterator<Const>::Iterator
|
||||
// Any changes here may need changes in the iterator increment() method
|
||||
//
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::iterator_erase
|
||||
(
|
||||
node_type*& entry,
|
||||
label& index
|
||||
)
|
||||
bool Foam::HashTable<T, Key, Hash>::iterator_erase(iterator& iter)
|
||||
{
|
||||
node_type* entry = iter.entry_;
|
||||
const label index = iter.index_;
|
||||
|
||||
// Safeguard against the following:
|
||||
// - empty table
|
||||
// - nullptr entry
|
||||
@ -98,8 +97,8 @@ bool Foam::HashTable<T, Key, Hash>::iterator_erase
|
||||
// Had previous element in linked list - reposition to there
|
||||
prev->next_ = entry->next_;
|
||||
delete entry;
|
||||
entry = prev;
|
||||
|
||||
iter.entry_ = prev;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -108,7 +107,7 @@ bool Foam::HashTable<T, Key, Hash>::iterator_erase
|
||||
delete entry;
|
||||
|
||||
// Assign any non-nullptr value so it doesn't look like end()
|
||||
entry = reinterpret_cast<node_type*>(this);
|
||||
iter.entry_ = reinterpret_cast<node_type*>(this);
|
||||
|
||||
// Mark the present index to continue and bring it back to the present
|
||||
// location with the next index.
|
||||
@ -116,10 +115,72 @@ bool Foam::HashTable<T, Key, Hash>::iterator_erase
|
||||
// Save: (-index-1), which has no ambiguity for index 0.
|
||||
// Retrieve: (-(index+1))
|
||||
|
||||
index = (-index - 1);
|
||||
iter.index_ = (-index - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Any changes here may need changes in the iterator increment() method
|
||||
//
|
||||
template<class T, class Key, class Hash>
|
||||
typename Foam::HashTable<T, Key, Hash>::node_type*
|
||||
Foam::HashTable<T, Key, Hash>::iterator_extract(iterator& iter)
|
||||
{
|
||||
node_type* entry = iter.entry_;
|
||||
const label index = iter.index_;
|
||||
|
||||
// Safeguard against the following:
|
||||
// - empty table
|
||||
// - nullptr entry
|
||||
// - end iterator (which is also a nullptr)
|
||||
// - negative index from a previous erase. See comment below.
|
||||
if (!size_ || !entry || index < 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Decrease count
|
||||
--size_;
|
||||
|
||||
// The previous element in the singly linked list
|
||||
node_type* prev = nullptr;
|
||||
|
||||
for (node_type* ep = table_[index]; ep; ep = ep->next_)
|
||||
{
|
||||
if (ep == entry)
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev = ep;
|
||||
}
|
||||
|
||||
if (prev)
|
||||
{
|
||||
// Had previous element in linked list - reposition iterator to there
|
||||
prev->next_ = entry->next_;
|
||||
iter.entry_ = prev;
|
||||
|
||||
entry->next_ = nullptr;
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Was first element on linked list
|
||||
table_[index] = entry->next_;
|
||||
iter.entry_ = table_[index];
|
||||
entry->next_ = nullptr;
|
||||
|
||||
// Mark the present index to continue and bring it back to the present
|
||||
// location with the next index.
|
||||
//
|
||||
// Save: (-index-1), which has no ambiguity for index 0.
|
||||
// Retrieve: (-(index+1))
|
||||
|
||||
iter.index_ = (-index - 1);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -70,7 +70,8 @@ inline Foam::HashTable<T, Key, Hash>::Iterator<Const>::Iterator
|
||||
|
||||
|
||||
//
|
||||
// Any changes here may need changes in iterator_erase() method too
|
||||
// Any changes here may need changes in iterator_erase(), iterator_extract()
|
||||
// methods too
|
||||
//
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
|
||||
@ -152,36 +152,6 @@ Foam::IOobjectList::IOobjectList
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::label Foam::IOobjectList::merge(IOobjectList&& other)
|
||||
{
|
||||
// Remove by name to avoid uncertainties about invalid iterators
|
||||
|
||||
label count = 0;
|
||||
|
||||
wordList keys(other.toc());
|
||||
|
||||
for (const word& key : keys)
|
||||
{
|
||||
if (!found(key))
|
||||
{
|
||||
if (IOobject::debug)
|
||||
{
|
||||
InfoInFunction << "Merge " << key << nl;
|
||||
}
|
||||
|
||||
if (add(other.remove(key)))
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
const Foam::IOobject* Foam::IOobjectList::cfindObject
|
||||
|
||||
@ -224,19 +224,11 @@ public:
|
||||
|
||||
// Basic methods
|
||||
|
||||
//- Move insert IOobject into the list
|
||||
inline bool add(autoPtr<IOobject>&& objectPtr);
|
||||
|
||||
//- Move insert IOobject into the list
|
||||
inline bool add(autoPtr<IOobject>& objectPtr);
|
||||
|
||||
//- Add objects from other to this list without overwriting
|
||||
//- existing keys.
|
||||
// After calling this, the other parameter will contains any items
|
||||
// that could not be merged.
|
||||
//
|
||||
// \return number of items merged
|
||||
label merge(IOobjectList&& other);
|
||||
//- Move insert IOobject into the list
|
||||
inline bool add(autoPtr<IOobject>&& objectPtr);
|
||||
|
||||
//- Remove object from the list, by name or by iterator.
|
||||
//
|
||||
@ -362,7 +354,7 @@ public:
|
||||
// word checkType = volScalarField::typeName;
|
||||
//
|
||||
// Info<< checkType << "="
|
||||
// << (classes.found(checkType) ? classes[checkType].size() : 0)
|
||||
// << (classes.contains(checkType) ? classes[checkType].size() : 0)
|
||||
// << nl;
|
||||
// \endcode
|
||||
// Using the two-parameter HashTable::lookup method lets us avoid
|
||||
|
||||
@ -109,7 +109,7 @@ inline Foam::IOobjectList::IOobjectList
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::IOobjectList::add(autoPtr<IOobject>&& objectPtr)
|
||||
inline bool Foam::IOobjectList::add(autoPtr<IOobject>& objectPtr)
|
||||
{
|
||||
if (objectPtr)
|
||||
{
|
||||
@ -120,7 +120,7 @@ inline bool Foam::IOobjectList::add(autoPtr<IOobject>&& objectPtr)
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::IOobjectList::add(autoPtr<IOobject>& objectPtr)
|
||||
inline bool Foam::IOobjectList::add(autoPtr<IOobject>&& objectPtr)
|
||||
{
|
||||
if (objectPtr)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user