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:
|
// Main program:
|
||||||
|
|
||||||
@ -84,33 +100,33 @@ int main(int argc, char *argv[])
|
|||||||
<< typeid(HashSet<label>::hasher).name() << nl << nl;
|
<< typeid(HashSet<label>::hasher).name() << nl << nl;
|
||||||
|
|
||||||
hashedWordList words
|
hashedWordList words
|
||||||
{
|
({
|
||||||
"abc",
|
"abc",
|
||||||
"def",
|
"def",
|
||||||
"ghi"
|
"ghi"
|
||||||
};
|
});
|
||||||
words = { "def", "ghi", "xy", "all", "end", "all" };
|
words = { "def", "ghi", "xy", "all", "end", "all" };
|
||||||
|
|
||||||
wordHashSet setA
|
wordHashSet setA
|
||||||
{
|
({
|
||||||
"xx",
|
"xx",
|
||||||
"yy",
|
"yy",
|
||||||
"zz"
|
"zz"
|
||||||
};
|
});
|
||||||
|
|
||||||
setA = { "kjhk", "kjhk2", "abced" };
|
setA = { "kjhk", "kjhk2", "abced" };
|
||||||
|
|
||||||
HashTable<label> tableA
|
HashTable<label> tableA
|
||||||
{
|
({
|
||||||
{ "value1", 1 },
|
{ "value1", 1 },
|
||||||
{ "value2", 2 },
|
{ "value2", 2 },
|
||||||
{ "value3", 3 }
|
{ "value3", 3 }
|
||||||
};
|
});
|
||||||
|
|
||||||
HashTable<nil> tableB;
|
HashTable<nil> tableB;
|
||||||
tableB.insert("value4", nil());
|
tableB.emplace("value4");
|
||||||
tableB.insert("value5", nil());
|
tableB.emplace("value5");
|
||||||
tableB.insert("value6", nil());
|
tableB.emplace("value6");
|
||||||
|
|
||||||
Info<< "tableA keys: "; tableA.writeKeys(Info) << endl;
|
Info<< "tableA keys: "; tableA.writeKeys(Info) << endl;
|
||||||
|
|
||||||
@ -123,11 +139,11 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<label> mapA
|
Map<label> mapA
|
||||||
{
|
({
|
||||||
{ 1, 1 },
|
{ 1, 1 },
|
||||||
{ 2, 2 },
|
{ 2, 2 },
|
||||||
{ 3, 3 }
|
{ 3, 3 }
|
||||||
};
|
});
|
||||||
mapA.set(4, 4);
|
mapA.set(4, 4);
|
||||||
|
|
||||||
Info<< "hashedWordList: " << words << nl
|
Info<< "hashedWordList: " << words << nl
|
||||||
@ -185,9 +201,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
labelHashSet setB
|
labelHashSet setB
|
||||||
{
|
({
|
||||||
1, 11, 42
|
1, 11, 42
|
||||||
};
|
});
|
||||||
|
|
||||||
Info<<"Set with min/max:" << minMax(setB)
|
Info<<"Set with min/max:" << minMax(setB)
|
||||||
<< " min:" << min(setB) << " max:" << max(setB) << nl;
|
<< " min:" << min(setB) << " max:" << max(setB) << nl;
|
||||||
@ -309,6 +325,26 @@ int main(int argc, char *argv[])
|
|||||||
Info<< "setA1: " << setA1 << nl
|
Info<< "setA1: " << setA1 << nl
|
||||||
<< "setB1: " << setB1 << 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;
|
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:
|
// Main program:
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
HashTable<label, Foam::string> table1
|
HashTable<Label, Foam::string> table0
|
||||||
{
|
({
|
||||||
|
{"abc", 123},
|
||||||
{"kjhk", 10},
|
{"kjhk", 10},
|
||||||
{"kjhk2", 12}
|
{"kjhk2", 12}
|
||||||
};
|
});
|
||||||
|
|
||||||
Info<< "table1: " << table1 << nl
|
Info<< "table0: " << table0 << nl
|
||||||
<< "toc: " << flatOutput(table1.toc()) << nl;
|
<< "toc: " << flatOutput(table0.toc()) << nl;
|
||||||
|
|
||||||
HashTable<label, label, Hash<label>> table2
|
HashTable<label, label, Hash<label>> table2
|
||||||
{
|
({
|
||||||
{3, 10},
|
{3, 10},
|
||||||
{5, 12},
|
{5, 12},
|
||||||
{7, 16}
|
{7, 16}
|
||||||
};
|
});
|
||||||
|
|
||||||
Info<< "table2: " << table2 << nl
|
Info<< "table2: " << table2 << nl
|
||||||
<< "toc: " << flatOutput(table2.toc()) << nl;
|
<< "toc: " << flatOutput(table2.toc()) << nl;
|
||||||
@ -127,7 +157,7 @@ int main(int argc, char *argv[])
|
|||||||
table1.insert("ghi", 15);
|
table1.insert("ghi", 15);
|
||||||
table1.insert("jkl", 20);
|
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" })
|
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);
|
HashPtrTable<Label> ptable1(0);
|
||||||
ptable1.insert("abc", autoPtr<Label>::New(5));
|
ptable1.insert("abc", autoPtr<Label>::New(5));
|
||||||
ptable1.insert("def", autoPtr<Label>::New(10));
|
ptable1.emplace("def", 10);
|
||||||
ptable1.insert("ghi", autoPtr<Label>::New(15));
|
ptable1.emplace("ghi", 15);
|
||||||
ptable1.insert("jkl", autoPtr<Label>::New(20));
|
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" })
|
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;
|
Info<< nl << "Ending scope" << nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,6 +335,28 @@ int main(int argc, char *argv[])
|
|||||||
Info<< "got with " << (*iter).size() << nl;
|
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;
|
Info<< "\nEnd\n" << endl;
|
||||||
|
|||||||
@ -334,7 +334,7 @@ int main(int argc, char *argv[])
|
|||||||
Info<< "==target==" << nl; reportDetail(objects);
|
Info<< "==target==" << nl; reportDetail(objects);
|
||||||
Info<< "==source==" << nl; reportDetail(other);
|
Info<< "==source==" << nl; reportDetail(other);
|
||||||
|
|
||||||
objects.merge(std::move(other));
|
objects.merge(other);
|
||||||
Info<< nl << "After merge" << nl;
|
Info<< nl << "After merge" << nl;
|
||||||
|
|
||||||
Info<< "==target==" << nl; reportDetail(objects);
|
Info<< "==target==" << nl; reportDetail(objects);
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2017-2021 OpenCFD Ltd.
|
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
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 * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -173,6 +173,16 @@ public:
|
|||||||
//- Clear all entries from table and delete any allocated pointers
|
//- Clear all entries from table and delete any allocated pointers
|
||||||
void clear();
|
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
|
// Reading/writing
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2018-2022 OpenCFD Ltd.
|
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
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 * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class Key, class Hash>
|
template<class Key, class Hash>
|
||||||
|
|||||||
@ -197,7 +197,7 @@ public:
|
|||||||
//- Same as insert (no value to overwrite)
|
//- Same as insert (no value to overwrite)
|
||||||
bool set(const Key& key)
|
bool set(const Key& key)
|
||||||
{
|
{
|
||||||
return insert(key);
|
return this->parent_type::emplace(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Unset the specified key - same as erase
|
//- Unset the specified key - same as erase
|
||||||
@ -207,6 +207,16 @@ public:
|
|||||||
return this->parent_type::erase(key);
|
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
|
// Convenience
|
||||||
|
|
||||||
@ -370,7 +380,7 @@ public:
|
|||||||
//- Add entries to this HashSet
|
//- Add entries to this HashSet
|
||||||
this_type& operator|=(const this_type& rhs);
|
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);
|
inline this_type& operator&=(const this_type& rhs);
|
||||||
|
|
||||||
//- Only retain unique entries (xor)
|
//- Only retain unique entries (xor)
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -359,7 +359,8 @@ bool Foam::HashTable<T, Key, Hash>::setEntry
|
|||||||
{
|
{
|
||||||
if (!capacity_)
|
if (!capacity_)
|
||||||
{
|
{
|
||||||
resize(2);
|
// Same as default sizing
|
||||||
|
resize(128);
|
||||||
}
|
}
|
||||||
|
|
||||||
const label index = hashKeyIndex(key);
|
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)...);
|
new node_type(table_[index], key, std::forward<Args>(args)...);
|
||||||
|
|
||||||
++size_;
|
++size_;
|
||||||
if (double(size_)/capacity_ > 0.8 && capacity_ < maxTableSize)
|
if (0.8*capacity_ < size_) // Resize after 80% fill factor
|
||||||
{
|
{
|
||||||
#ifdef FULLDEBUG
|
if (capacity_ < maxTableSize) resize(2*capacity_);
|
||||||
DebugInFunction << "Doubling table size\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
resize(2*capacity_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (overwrite)
|
else if (overwrite)
|
||||||
@ -425,10 +422,7 @@ bool Foam::HashTable<T, Key, Hash>::setEntry
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Do not overwrite existing entry (STL 'insert' convention)
|
// Not overwriting existing entry
|
||||||
#ifdef FULLDEBUG
|
|
||||||
DebugInFunction << "Not inserting " << key << ": already in table\n";
|
|
||||||
#endif
|
|
||||||
return false;
|
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>
|
template<class T, class Key, class Hash>
|
||||||
bool Foam::HashTable<T, Key, Hash>::erase(const iterator& iter)
|
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
|
// The parameter should be (iterator&), but then the compiler doesn't find
|
||||||
// it correctly and tries to call as (iterator) instead.
|
// it correctly and tries to call as (iterator) instead.
|
||||||
|
|
||||||
iterator& it = const_cast<iterator&>(iter);
|
return iterator_erase(const_cast<iterator&>(iter));
|
||||||
|
|
||||||
return iterator_erase(it.entry_, it.index_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -454,7 +492,7 @@ template<class T, class Key, class Hash>
|
|||||||
bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
|
bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
|
||||||
{
|
{
|
||||||
iterator iter(find(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)
|
if (newCapacity == oldCapacity)
|
||||||
{
|
{
|
||||||
#ifdef FULLDEBUG
|
|
||||||
DebugInFunction << "New table size == old table size\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!newCapacity)
|
else if (!newCapacity)
|
||||||
@ -617,7 +651,8 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
|||||||
if (size_)
|
if (size_)
|
||||||
{
|
{
|
||||||
WarningInFunction
|
WarningInFunction
|
||||||
<< "HashTable contains " << size_ << " cannot resize(0)" << nl;
|
<< "HashTable contains " << size_
|
||||||
|
<< " elements, cannot resize(0)" << nl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -646,8 +681,7 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
|||||||
|
|
||||||
// Move to new table[] but with new chaining.
|
// Move to new table[] but with new chaining.
|
||||||
|
|
||||||
label nMove = size_; // Allow early completion
|
for (label i = 0, nPending = size_; nPending && i < oldCapacity; ++i)
|
||||||
for (label i=0; nMove && i < oldCapacity; ++i)
|
|
||||||
{
|
{
|
||||||
for (node_type* ep = oldTable[i]; ep; /*nil*/)
|
for (node_type* ep = oldTable[i]; ep; /*nil*/)
|
||||||
{
|
{
|
||||||
@ -662,7 +696,7 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ep = next; // continue in the linked-list
|
ep = next; // continue in the linked-list
|
||||||
--nMove; // note any early completion
|
--nPending; // note any early completion
|
||||||
}
|
}
|
||||||
oldTable[i] = nullptr;
|
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 * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
|
|||||||
@ -206,6 +206,17 @@ private:
|
|||||||
template<class... Args>
|
template<class... Args>
|
||||||
bool setEntry(const bool overwrite, const Key& key, Args&&... 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
|
//- Read hash table
|
||||||
Istream& readTable(Istream& is);
|
Istream& readTable(Istream& is);
|
||||||
|
|
||||||
@ -532,6 +543,16 @@ public:
|
|||||||
//- Transfer contents into this table.
|
//- Transfer contents into this table.
|
||||||
void transfer(HashTable<T, Key, Hash>& rhs);
|
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
|
// 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:
|
public:
|
||||||
|
|
||||||
//- Forward iterator with non-const access
|
//- 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>
|
template<class T, class Key, class Hash>
|
||||||
inline const T& Foam::HashTable<T, Key, Hash>::lookup
|
inline const T& Foam::HashTable<T, Key, Hash>::lookup
|
||||||
(
|
(
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2017 OpenCFD Ltd.
|
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -39,7 +39,7 @@ Foam::HashTable<T, Key, Hash>::Iterator<Const>::Iterator
|
|||||||
container_(tbl),
|
container_(tbl),
|
||||||
index_(0)
|
index_(0)
|
||||||
{
|
{
|
||||||
if (tbl->size())
|
if (container_ && container_->size())
|
||||||
{
|
{
|
||||||
const label index = container_->hashKeyIndex(key);
|
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
|
// Any changes here may need changes in the iterator increment() method
|
||||||
//
|
//
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
bool Foam::HashTable<T, Key, Hash>::iterator_erase
|
bool Foam::HashTable<T, Key, Hash>::iterator_erase(iterator& iter)
|
||||||
(
|
|
||||||
node_type*& entry,
|
|
||||||
label& index
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
|
node_type* entry = iter.entry_;
|
||||||
|
const label index = iter.index_;
|
||||||
|
|
||||||
// Safeguard against the following:
|
// Safeguard against the following:
|
||||||
// - empty table
|
// - empty table
|
||||||
// - nullptr entry
|
// - nullptr entry
|
||||||
@ -98,8 +97,8 @@ bool Foam::HashTable<T, Key, Hash>::iterator_erase
|
|||||||
// Had previous element in linked list - reposition to there
|
// Had previous element in linked list - reposition to there
|
||||||
prev->next_ = entry->next_;
|
prev->next_ = entry->next_;
|
||||||
delete entry;
|
delete entry;
|
||||||
entry = prev;
|
|
||||||
|
|
||||||
|
iter.entry_ = prev;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +107,7 @@ bool Foam::HashTable<T, Key, Hash>::iterator_erase
|
|||||||
delete entry;
|
delete entry;
|
||||||
|
|
||||||
// Assign any non-nullptr value so it doesn't look like end()
|
// 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
|
// Mark the present index to continue and bring it back to the present
|
||||||
// location with the next index.
|
// 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.
|
// Save: (-index-1), which has no ambiguity for index 0.
|
||||||
// Retrieve: (-(index+1))
|
// Retrieve: (-(index+1))
|
||||||
|
|
||||||
index = (-index - 1);
|
iter.index_ = (-index - 1);
|
||||||
|
|
||||||
return true;
|
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<class T, class Key, class Hash>
|
||||||
template<bool Const>
|
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
|
const Foam::IOobject* Foam::IOobjectList::cfindObject
|
||||||
|
|||||||
@ -224,19 +224,11 @@ public:
|
|||||||
|
|
||||||
// Basic methods
|
// Basic methods
|
||||||
|
|
||||||
//- Move insert IOobject into the list
|
|
||||||
inline bool add(autoPtr<IOobject>&& objectPtr);
|
|
||||||
|
|
||||||
//- Move insert IOobject into the list
|
//- Move insert IOobject into the list
|
||||||
inline bool add(autoPtr<IOobject>& objectPtr);
|
inline bool add(autoPtr<IOobject>& objectPtr);
|
||||||
|
|
||||||
//- Add objects from other to this list without overwriting
|
//- Move insert IOobject into the list
|
||||||
//- existing keys.
|
inline bool add(autoPtr<IOobject>&& objectPtr);
|
||||||
// After calling this, the other parameter will contains any items
|
|
||||||
// that could not be merged.
|
|
||||||
//
|
|
||||||
// \return number of items merged
|
|
||||||
label merge(IOobjectList&& other);
|
|
||||||
|
|
||||||
//- Remove object from the list, by name or by iterator.
|
//- Remove object from the list, by name or by iterator.
|
||||||
//
|
//
|
||||||
@ -362,7 +354,7 @@ public:
|
|||||||
// word checkType = volScalarField::typeName;
|
// word checkType = volScalarField::typeName;
|
||||||
//
|
//
|
||||||
// Info<< checkType << "="
|
// Info<< checkType << "="
|
||||||
// << (classes.found(checkType) ? classes[checkType].size() : 0)
|
// << (classes.contains(checkType) ? classes[checkType].size() : 0)
|
||||||
// << nl;
|
// << nl;
|
||||||
// \endcode
|
// \endcode
|
||||||
// Using the two-parameter HashTable::lookup method lets us avoid
|
// Using the two-parameter HashTable::lookup method lets us avoid
|
||||||
|
|||||||
@ -109,7 +109,7 @@ inline Foam::IOobjectList::IOobjectList
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
inline bool Foam::IOobjectList::add(autoPtr<IOobject>&& objectPtr)
|
inline bool Foam::IOobjectList::add(autoPtr<IOobject>& objectPtr)
|
||||||
{
|
{
|
||||||
if (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)
|
if (objectPtr)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user