mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'feature-hash-table' into 'develop'
Improvements to HashTable internals See merge request Development/OpenFOAM-plus!158
This commit is contained in:
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,6 +26,7 @@ Description
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "hashedWordList.H"
|
||||
#include "nil.H"
|
||||
#include "HashSet.H"
|
||||
#include "Map.H"
|
||||
#include "labelPairHashes.H"
|
||||
@ -69,6 +70,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
Info<< "tableA keys: "; tableA.writeKeys(Info) << endl;
|
||||
|
||||
Info<< "tableB content: " << tableB << endl;
|
||||
|
||||
auto keyIterPair = tableA.keys();
|
||||
for (const auto& i : keyIterPair)
|
||||
{
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
Test-hashTable.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-hashTable
|
||||
3
applications/test/HashTable1/Make/files
Normal file
3
applications/test/HashTable1/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-HashTable1.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-HashTable1
|
||||
@ -30,7 +30,6 @@ Description
|
||||
#include "HashTable.H"
|
||||
#include "HashPtrTable.H"
|
||||
#include "Map.H"
|
||||
#include "StaticHashTable.H"
|
||||
#include "cpuTime.H"
|
||||
|
||||
using namespace Foam;
|
||||
@ -57,7 +56,6 @@ int main(int argc, char *argv[])
|
||||
// ie, a
|
||||
// Map<label> map(2 * nSize);
|
||||
// HashTable<label, label, Hash<label>> map(2 * nSize);
|
||||
// StaticHashTable<label, label, Hash<label>> map(2 * nSize);
|
||||
HashTable<label, label, Hash<label>> map(2 * nSize);
|
||||
|
||||
Info<< "Constructed map of size: " << nSize;
|
||||
|
||||
3
applications/test/HashTable4/Make/files
Normal file
3
applications/test/HashTable4/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-HashTable4.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-HashTable4
|
||||
2
applications/test/HashTable4/Make/options
Normal file
2
applications/test/HashTable4/Make/options
Normal file
@ -0,0 +1,2 @@
|
||||
/* EXE_INC = -I$(LIB_SRC)/cfdTools/include */
|
||||
/* EXE_LIBS = -lfiniteVolume */
|
||||
312
applications/test/HashTable4/Test-HashTable4.C
Normal file
312
applications/test/HashTable4/Test-HashTable4.C
Normal file
@ -0,0 +1,312 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Description
|
||||
Test HashTable resizing
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argList.H"
|
||||
#include "HashSet.H"
|
||||
#include "HashTable.H"
|
||||
#include "Map.H"
|
||||
#include "cpuTime.H"
|
||||
#include "memInfo.H"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
// #undef ORDERED
|
||||
// #define ORDERED
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
template<class T>
|
||||
Ostream& printInfo(Ostream& os, const HashTable<T, T, Hash<T>>& ht)
|
||||
{
|
||||
os << " (size " << ht.size() << " capacity " << ht.capacity() << ") ";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template<class K, class V>
|
||||
inline void insertElem
|
||||
(
|
||||
#ifdef ORDERED
|
||||
std::set<K>& container,
|
||||
#else
|
||||
std::unordered_set<K, Hash<K>>& container,
|
||||
#endif
|
||||
K k,
|
||||
V v
|
||||
)
|
||||
{
|
||||
container.insert(k);
|
||||
}
|
||||
|
||||
|
||||
template<class K, class V>
|
||||
inline void insertElem
|
||||
(
|
||||
#ifdef ORDERED
|
||||
std::map<K, V>& container,
|
||||
#else
|
||||
std::unordered_map<K, V, Hash<K>>& container,
|
||||
#endif
|
||||
K k,
|
||||
V v
|
||||
)
|
||||
{
|
||||
container.insert(std::make_pair(k, v));
|
||||
}
|
||||
|
||||
|
||||
template<class K, class V>
|
||||
inline void insertElem
|
||||
(
|
||||
HashSet<K, Hash<K>>& container,
|
||||
K k,
|
||||
V v
|
||||
)
|
||||
{
|
||||
container.insert(k);
|
||||
}
|
||||
|
||||
|
||||
template<class K, class V>
|
||||
inline void insertElem
|
||||
(
|
||||
HashTable<K, V, Hash<K>>& container,
|
||||
K k,
|
||||
V v
|
||||
)
|
||||
{
|
||||
container.insert(k, v);
|
||||
}
|
||||
|
||||
|
||||
template<class Container>
|
||||
inline void loopInsert(Container& container, const label n)
|
||||
{
|
||||
for (label i = 0; i < n; i++)
|
||||
{
|
||||
insertElem(container, i, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Container>
|
||||
inline unsigned long loopFind(const Container& container, const label n)
|
||||
{
|
||||
const auto endIter = container.end();
|
||||
unsigned long sum = 0;
|
||||
|
||||
for (label i = 0; i < n; i++)
|
||||
{
|
||||
if (container.find(i) != endIter)
|
||||
{
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const label nLoops = 200;
|
||||
const label nFind = 10;
|
||||
const label nElem = 1000000;
|
||||
|
||||
argList::noBanner();
|
||||
argList::addBoolOption("std", "use std::unordered_map or std::set");
|
||||
argList::addBoolOption("set", "test HashSet");
|
||||
argList::addBoolOption("find", "test find");
|
||||
|
||||
argList args(argc, argv);
|
||||
|
||||
const bool optStd = args.optionFound("std");
|
||||
const bool optSet = args.optionFound("set");
|
||||
const bool optFnd = args.optionFound("find");
|
||||
|
||||
|
||||
cpuTime timer;
|
||||
memInfo mem;
|
||||
|
||||
Info<< "insert " << nElem << " (int) elements";
|
||||
if (optFnd)
|
||||
{
|
||||
Info<< ", then find " << (nFind*nLoops) << " times\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " repeated " << nLoops << " times " << endl;
|
||||
}
|
||||
|
||||
if (false)
|
||||
{
|
||||
// verify that resizing around (0) doesn't fail
|
||||
HashTable<label, label, Hash<label>> map(32);
|
||||
printInfo(Info, map) << endl;
|
||||
|
||||
map.insert(10, 1000);
|
||||
|
||||
map.resize(0);
|
||||
printInfo(Info, map) << endl;
|
||||
|
||||
map.resize(10);
|
||||
printInfo(Info, map) << endl;
|
||||
|
||||
map.clear();
|
||||
printInfo(Info, map) << endl;
|
||||
|
||||
map.resize(0);
|
||||
printInfo(Info, map) << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (optStd)
|
||||
{
|
||||
if (optFnd)
|
||||
{
|
||||
#ifdef ORDERED
|
||||
Info<< "using stl::set" << endl;
|
||||
std::set<label> map;
|
||||
#else
|
||||
Info<< "using stl::unordered_set" << endl;
|
||||
std::unordered_set<label, Hash<label>> map(32);
|
||||
#endif
|
||||
|
||||
loopInsert(map, nElem);
|
||||
(void)timer.cpuTimeIncrement();
|
||||
|
||||
unsigned long sum = 0;
|
||||
for (label loopi = 0; loopi < nFind*nLoops; ++loopi)
|
||||
{
|
||||
sum += loopFind(map, nElem);
|
||||
}
|
||||
|
||||
// check result (suppress compiler optimizations?)
|
||||
if (sum == 0)
|
||||
{
|
||||
Info<<"sum=0\n";
|
||||
}
|
||||
}
|
||||
else if (optSet)
|
||||
{
|
||||
#ifdef ORDERED
|
||||
Info<< "using stl::set" << endl;
|
||||
#else
|
||||
Info<< "using stl::unordered_set" << endl;
|
||||
#endif
|
||||
|
||||
for (label loopi = 0; loopi < nLoops; ++loopi)
|
||||
{
|
||||
#ifdef ORDERED
|
||||
std::set<label> map;
|
||||
#else
|
||||
std::unordered_set<label, Hash<label>> map(32);
|
||||
#endif
|
||||
|
||||
loopInsert(map, nElem);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ORDERED
|
||||
Info<< "using stl::map" << endl;
|
||||
#else
|
||||
Info<< "using stl::unordered_set" << endl;
|
||||
#endif
|
||||
|
||||
for (label loopi = 0; loopi < nLoops; ++loopi)
|
||||
{
|
||||
#ifdef ORDERED
|
||||
std::map<label, label> map;
|
||||
#else
|
||||
std::unordered_map<label, label, Hash<label>> map(32);
|
||||
#endif
|
||||
|
||||
loopInsert(map, nElem);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (optFnd)
|
||||
{
|
||||
Info<< "using HashSet" << endl;
|
||||
|
||||
HashSet<label, Hash<label>> map(32);
|
||||
|
||||
loopInsert(map, nElem);
|
||||
(void)timer.cpuTimeIncrement();
|
||||
|
||||
unsigned long sum = 0;
|
||||
for (label loopi = 0; loopi < nFind*nLoops; ++loopi)
|
||||
{
|
||||
sum += loopFind(map, nElem);
|
||||
}
|
||||
|
||||
// check result (suppress compiler optimizations?)
|
||||
if (sum == 0)
|
||||
{
|
||||
Info<<"sum=0\n";
|
||||
}
|
||||
}
|
||||
else if (optSet)
|
||||
{
|
||||
Info<< "using HashSet" << endl;
|
||||
for (label loopi = 0; loopi < nLoops; ++loopi)
|
||||
{
|
||||
HashSet<label, Hash<label>> map(32);
|
||||
|
||||
loopInsert(map, nElem);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "using HashTable" << endl;
|
||||
for (label loopi = 0; loopi < nLoops; ++loopi)
|
||||
{
|
||||
HashTable<label, label, Hash<label>> map(32);
|
||||
|
||||
loopInsert(map, nElem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< timer.cpuTimeIncrement() << " s\n";
|
||||
Info<< "mem info: " << mem.update() << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -31,14 +31,12 @@ Description
|
||||
#include "boolList.H"
|
||||
#include "PackedBoolList.H"
|
||||
#include "HashSet.H"
|
||||
#include "StaticHashTable.H"
|
||||
#include "cpuTime.H"
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
#undef TEST_STATIC_HASH
|
||||
#undef TEST_STD_BOOLLIST
|
||||
#undef TEST_STD_UNORDERED_SET
|
||||
|
||||
@ -84,20 +82,6 @@ int main(int argc, char *argv[])
|
||||
Info<< "populated labelHashSet in "
|
||||
<< timer.cpuTimeIncrement() << " s\n\n";
|
||||
|
||||
|
||||
#ifdef TEST_STATIC_HASH
|
||||
// fullStaticHash is really slow
|
||||
// give it lots of slots to help
|
||||
StaticHashTable<nil, label, Hash<label>> emptyStaticHash;
|
||||
StaticHashTable<nil, label, Hash<label>> fullStaticHash(100000);
|
||||
for (label i = 0; i < n; i++)
|
||||
{
|
||||
fullStaticHash.insert(i, nil());
|
||||
}
|
||||
Info<< "populated StaticHashTable in "
|
||||
<< timer.cpuTimeIncrement() << " s\n\n";
|
||||
#endif
|
||||
|
||||
#ifdef TEST_STD_UNORDERED_SET
|
||||
std::unordered_set<label, Foam::Hash<label>> emptyStdHash;
|
||||
std::unordered_set<label, Foam::Hash<label>> fullStdHash;
|
||||
@ -112,10 +96,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
emptyHash.printInfo(Info);
|
||||
fullHash.printInfo(Info);
|
||||
#ifdef TEST_STATIC_HASH
|
||||
emptyStaticHash.printInfo(Info);
|
||||
fullStaticHash.printInfo(Info);
|
||||
#endif
|
||||
#ifdef TEST_STD_UNORDERED_SET
|
||||
printInfo(emptyStdHash);
|
||||
printInfo(fullStdHash);
|
||||
@ -305,37 +285,6 @@ int main(int argc, char *argv[])
|
||||
<< " sum " << sum << nl;
|
||||
|
||||
|
||||
#ifdef TEST_STATIC_HASH
|
||||
// Read empty StaticHashTable
|
||||
sum = 0;
|
||||
for (label iter = 0; iter < nIters; ++iter)
|
||||
{
|
||||
forAll(unpacked, i)
|
||||
{
|
||||
sum += emptyStaticHash.found(i);
|
||||
}
|
||||
}
|
||||
std::cout
|
||||
<< "Reading empty StaticHash:" << timer.cpuTimeIncrement()
|
||||
<< " s" << nl
|
||||
<< " sum " << sum << nl;
|
||||
|
||||
// Read full StaticHashTable
|
||||
sum = 0;
|
||||
for (label iter = 0; iter < nIters; ++iter)
|
||||
{
|
||||
forAll(unpacked, i)
|
||||
{
|
||||
sum += fullStaticHash.found(i);
|
||||
}
|
||||
}
|
||||
std::cout
|
||||
<< "Reading full StaticHash:" << timer.cpuTimeIncrement()
|
||||
<< " s" << nl
|
||||
<< " sum " << sum << nl;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TEST_STD_UNORDERED_SET
|
||||
// Read empty stl set
|
||||
sum = 0;
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
Test-staticHashTable.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-staticHashTable
|
||||
@ -1,170 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "StaticHashTable.H"
|
||||
#include "IOstreams.H"
|
||||
#include "StringStream.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// use define so we can easily test other implementations
|
||||
#define HASHTABLE_CLASS StaticHashTable
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main()
|
||||
{
|
||||
HASHTABLE_CLASS<double> table1(13);
|
||||
|
||||
table1.insert("aaa", 1.0);
|
||||
table1.insert("aba", 2.0);
|
||||
table1.insert("aca", 3.0);
|
||||
table1.insert("ada", 4.0);
|
||||
table1.insert("aeq", 5.0);
|
||||
table1.insert("aaw", 6.0);
|
||||
table1.insert("abs", 7.0);
|
||||
table1.insert("acr", 8.0);
|
||||
table1.insert("adx", 9.0);
|
||||
table1.insert("aec", 10.0);
|
||||
|
||||
table1.erase("aaw");
|
||||
table1.erase("abs");
|
||||
|
||||
Info<< "\ntable1 toc: " << table1.toc() << endl;
|
||||
table1.printInfo(Info)
|
||||
<< "table1 [" << table1.size() << "] " << endl;
|
||||
forAllIter(HASHTABLE_CLASS<double>, table1, iter)
|
||||
{
|
||||
Info<< iter.key() << " => " << iter() << nl;
|
||||
}
|
||||
|
||||
table1.set("acr", 108);
|
||||
table1.set("adx", 109);
|
||||
table1.set("aec", 100);
|
||||
table1("aaw") -= 1000;
|
||||
table1("aeq") += 1000;
|
||||
|
||||
Info<< "\noverwrote some values table1: " << table1 << endl;
|
||||
|
||||
Info<< "\ntest find:" << endl;
|
||||
Info<< table1.find("aaa")() << nl
|
||||
<< table1.find("aba")() << nl
|
||||
<< table1.find("aca")() << nl
|
||||
<< table1.find("ada")() << nl
|
||||
<< table1.find("aeq")() << nl
|
||||
<< table1.find("acr")() << nl
|
||||
<< table1.find("adx")() << nl
|
||||
<< table1.find("aec")() << nl
|
||||
<< table1["aaa"] << nl;
|
||||
|
||||
{
|
||||
OStringStream os;
|
||||
os << table1;
|
||||
HASHTABLE_CLASS<double> readTable(IStringStream(os.str())(), 100);
|
||||
|
||||
Info<< "Istream constructor:" << readTable << endl;
|
||||
}
|
||||
|
||||
|
||||
HASHTABLE_CLASS<double> table2(table1);
|
||||
HASHTABLE_CLASS<double> table3(table1.xfer());
|
||||
|
||||
Info<< "\ncopy table1 -> table2" << nl
|
||||
<< "transfer table1 -> table3 via the xfer() method" << nl;
|
||||
|
||||
Info<< "\ntable1" << table1 << nl
|
||||
<< "\ntable2" << table2 << nl
|
||||
<< "\ntable3" << table3 << nl;
|
||||
|
||||
Info<< "\nerase table2 by iterator" << nl;
|
||||
forAllIter(HASHTABLE_CLASS<double>, table2, iter)
|
||||
{
|
||||
Info<< "erasing " << iter.key() << " => " << iter() << " ... ";
|
||||
table2.erase(iter);
|
||||
Info<< "erased" << endl;
|
||||
}
|
||||
|
||||
Info<< "\ntable1" << table1 << nl
|
||||
<< "\ntable2" << table2 << nl
|
||||
<< "\ntable3" << table3 << nl;
|
||||
|
||||
table3.resize(1);
|
||||
Info<< "\nresize(1) table3" << nl;
|
||||
table3.printInfo(Info)
|
||||
<< table3 << nl;
|
||||
|
||||
table3.resize(10000);
|
||||
Info<< "\nresize(10000) table3" << nl;
|
||||
table3.printInfo(Info)
|
||||
<< table3 << nl;
|
||||
|
||||
HASHTABLE_CLASS<double> table4;
|
||||
|
||||
table4 = table3;
|
||||
Info<< "\ncopy table3 -> table4 " << table4 << nl;
|
||||
|
||||
Info<< "\nclear table4 ... ";
|
||||
table4.clear();
|
||||
Info<< "[" << table4.size() << "] " << table4 << nl;
|
||||
|
||||
table1 = table3;
|
||||
Info<< "\ncopy table3 -> table1 (previously transferred)" << table1 << nl;
|
||||
|
||||
Info<< "test table1 == table3 : " << (table1 == table3) << nl;
|
||||
table1.erase(table1.begin());
|
||||
Info<< "removed an element - test table1 != table3 : "
|
||||
<< (table1 != table3) << nl;
|
||||
|
||||
// insert a few things into table2
|
||||
table2.set("ada", 14.0);
|
||||
table2.set("aeq", 15.0);
|
||||
table2.set("aaw", 16.0);
|
||||
table2.set("abs", 17.0);
|
||||
table2.set("adx", 20.0);
|
||||
|
||||
Info<< "\ntable1" << table1 << nl
|
||||
<< "\ntable2" << table2 << nl;
|
||||
|
||||
label nErased = table1.erase(table2);
|
||||
|
||||
Info<< "\nerase table2 keys from table1 (removed "
|
||||
<< nErased << " elements)" << nl
|
||||
<< "\ntable1" << table1 << nl
|
||||
<< "\ntable2" << table2 << nl;
|
||||
|
||||
|
||||
Info<< "\ntable3" << table3
|
||||
<< "\nclearStorage table3 ... ";
|
||||
table3.clearStorage();
|
||||
Info<< table3 << nl;
|
||||
|
||||
Info<< "\nDone\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -61,6 +61,10 @@ int main(int argc, char *argv[])
|
||||
nil x;
|
||||
cout<<"nil:" << sizeof(x) << nl;
|
||||
}
|
||||
{
|
||||
zero x;
|
||||
cout<<"zero:" << sizeof(x) << nl;
|
||||
}
|
||||
{
|
||||
bool x(0);
|
||||
cout<<"bool:" << sizeof(x) << nl;
|
||||
@ -93,6 +97,10 @@ int main(int argc, char *argv[])
|
||||
cout<<"double:" << sizeof(double) << nl;
|
||||
}
|
||||
|
||||
{
|
||||
cout<<"string:" << sizeof(Foam::string) << nl;
|
||||
}
|
||||
|
||||
|
||||
Info << "---\nEnd\n" << endl;
|
||||
|
||||
|
||||
@ -65,7 +65,7 @@ export WM_COMPILER_TYPE=system
|
||||
|
||||
#- Compiler:
|
||||
# WM_COMPILER = Gcc | Gcc4[8-9] | Gcc5[1-4] | Gcc6[1-3] | GccKNL
|
||||
# | Clang | Clang3[8-9] | Clang40 | Icc | IccKNL | Cray
|
||||
# | Clang | Clang3[8-9] | Gcc[45]0 | Icc | IccKNL | Cray
|
||||
export WM_COMPILER=Gcc
|
||||
unset WM_COMPILER_ARCH WM_COMPILER_LIB_ARCH
|
||||
|
||||
|
||||
@ -82,7 +82,10 @@ case ThirdParty:
|
||||
set clang_version=llvm-3.9.1
|
||||
breaksw
|
||||
case Clang40:
|
||||
set clang_version=llvm-4.0.0
|
||||
set clang_version=llvm-4.0.1
|
||||
breaksw
|
||||
case Clang50:
|
||||
set clang_version=llvm-5.0.0
|
||||
breaksw
|
||||
default:
|
||||
/bin/cat << UNKNOWN_COMPILER
|
||||
|
||||
@ -81,7 +81,10 @@ ThirdParty)
|
||||
clang_version=llvm-3.9.1
|
||||
;;
|
||||
Clang40)
|
||||
clang_version=llvm-4.0.0
|
||||
clang_version=llvm-4.0.1
|
||||
;;
|
||||
Clang50)
|
||||
clang_version=llvm-5.0.0
|
||||
;;
|
||||
*)
|
||||
/bin/cat << UNKNOWN_COMPILER 1>&2
|
||||
|
||||
@ -337,7 +337,6 @@ DebugSwitches
|
||||
SpalartAllmarasIDDES 0;
|
||||
SphereDrag 0;
|
||||
StandardWallInteraction 0;
|
||||
StaticHashTable 0;
|
||||
StochasticDispersionRAS 0;
|
||||
SuperBee 0;
|
||||
SuperBeeV 0;
|
||||
|
||||
@ -61,7 +61,7 @@ setenv WM_COMPILER_TYPE system
|
||||
|
||||
#- Compiler:
|
||||
# WM_COMPILER = Gcc | Gcc4[8-9] | Gcc5[1-4] | Gcc6[1-3] | GccKNL
|
||||
# | Clang | Clang3[8-9] | Clang40 | Icc | IccKNL | Cray
|
||||
# | Clang | Clang3[8-9] | Gcc[45]0 | Icc | IccKNL | Cray
|
||||
setenv WM_COMPILER Gcc
|
||||
setenv WM_COMPILER_ARCH # defined but empty
|
||||
unsetenv WM_COMPILER_LIB_ARCH
|
||||
|
||||
@ -147,7 +147,6 @@ primitives/Barycentric/barycentric/barycentric.C
|
||||
primitives/Barycentric2D/barycentric2D/barycentric2D.C
|
||||
|
||||
containers/HashTables/HashTable/HashTableCore.C
|
||||
containers/HashTables/StaticHashTable/StaticHashTableCore.C
|
||||
containers/Lists/SortableList/ParSortableListName.C
|
||||
containers/Lists/PackedList/PackedListCore.C
|
||||
containers/Lists/PackedList/PackedBoolList.C
|
||||
|
||||
@ -28,6 +28,13 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::HashPtrTable<T, Key, Hash>::HashPtrTable()
|
||||
:
|
||||
parent_type()
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::HashPtrTable<T, Key, Hash>::HashPtrTable(const label size)
|
||||
:
|
||||
@ -157,6 +164,7 @@ void Foam::HashPtrTable<T, Key, Hash>::operator=
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
#include "HashPtrTableIO.C"
|
||||
|
||||
@ -91,8 +91,11 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null with default table size
|
||||
HashPtrTable();
|
||||
|
||||
//- Construct given initial table size
|
||||
HashPtrTable(const label size = 128);
|
||||
explicit HashPtrTable(const label size);
|
||||
|
||||
//- Construct from Istream using given Istream constructor class
|
||||
template<class INew>
|
||||
@ -102,7 +105,7 @@ public:
|
||||
HashPtrTable(Istream& is);
|
||||
|
||||
//- Construct from dictionary with default dictionary constructor class
|
||||
HashPtrTable(const dictionary& dict);
|
||||
explicit HashPtrTable(const dictionary& dict);
|
||||
|
||||
//- Construct as copy
|
||||
HashPtrTable(const this_type& ht);
|
||||
@ -127,7 +130,7 @@ public:
|
||||
//- Erase an entry specified by the given key
|
||||
bool erase(const Key& key);
|
||||
|
||||
//- Clear all entries from table
|
||||
//- Clear all entries from table and deleting any allocated pointers
|
||||
void clear();
|
||||
|
||||
//- Write
|
||||
|
||||
@ -41,7 +41,7 @@ void Foam::HashPtrTable<T, Key, Hash>::read(Istream& is, const INew& inewt)
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"HashPtrTable<T, Key, Hash>::read(Istream&, const INew&) : "
|
||||
"HashPtrTable::read(Istream&, const INew&) : "
|
||||
"reading first token"
|
||||
);
|
||||
|
||||
@ -50,7 +50,7 @@ void Foam::HashPtrTable<T, Key, Hash>::read(Istream& is, const INew& inewt)
|
||||
const label s = firstToken.labelToken();
|
||||
|
||||
// Read beginning of contents
|
||||
const char delimiter = is.readBeginList("HashPtrTable<T, Key, Hash>");
|
||||
const char delimiter = is.readBeginList("HashPtrTable");
|
||||
|
||||
if (s)
|
||||
{
|
||||
@ -69,8 +69,8 @@ void Foam::HashPtrTable<T, Key, Hash>::read(Istream& is, const INew& inewt)
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"HashPtrTable<T, Key, Hash>::"
|
||||
"read(Istream&, const INew&) : reading entry"
|
||||
"HashPtrTable::read(Istream&, const INew&) : "
|
||||
"reading entry"
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -114,7 +114,7 @@ void Foam::HashPtrTable<T, Key, Hash>::read(Istream& is, const INew& inewt)
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"HashPtrTable<T, Key, Hash>::read(Istream&, const INew&) : "
|
||||
"HashPtrTable::read(Istream&, const INew&) : "
|
||||
"reading entry"
|
||||
);
|
||||
|
||||
@ -155,7 +155,7 @@ void Foam::HashPtrTable<T, Key, Hash>::read
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashPtrTable<T, Key, Hash>::write(Ostream& os) const
|
||||
{
|
||||
for (const_iterator iter = this->begin(); iter != this->end(); ++iter)
|
||||
for (const_iterator iter = this->cbegin(); iter != this->cend(); ++iter)
|
||||
{
|
||||
const T* ptr = iter.object();
|
||||
if (ptr)
|
||||
@ -209,29 +209,34 @@ Foam::Ostream& Foam::operator<<
|
||||
const HashPtrTable<T, Key, Hash>& tbl
|
||||
)
|
||||
{
|
||||
using const_iterator = typename HashPtrTable<T, Key, Hash>::const_iterator;
|
||||
const label sz = tbl.size();
|
||||
|
||||
// Write size and start delimiter
|
||||
os << nl << tbl.size() << nl << token::BEGIN_LIST << nl;
|
||||
|
||||
// Write contents
|
||||
for (const_iterator iter = tbl.cbegin(); iter != tbl.cend(); ++iter)
|
||||
if (sz)
|
||||
{
|
||||
const T* ptr = iter.object();
|
||||
// Size and start list delimiter
|
||||
os << nl << sz << nl << token::BEGIN_LIST << nl;
|
||||
|
||||
os << iter.key();
|
||||
if (ptr)
|
||||
// Contents
|
||||
for (auto iter = tbl.cbegin(); iter != tbl.cend(); ++iter)
|
||||
{
|
||||
os << token::SPACE << *ptr;
|
||||
const T* ptr = iter.object();
|
||||
|
||||
os << iter.key();
|
||||
if (ptr)
|
||||
{
|
||||
os << token::SPACE << *ptr;
|
||||
}
|
||||
os << nl;
|
||||
}
|
||||
os << nl;
|
||||
os << token::END_LIST; // End list delimiter
|
||||
}
|
||||
else
|
||||
{
|
||||
// Empty hash table
|
||||
os << sz << token::BEGIN_LIST << token::END_LIST;
|
||||
}
|
||||
|
||||
// Write end delimiter
|
||||
os << token::END_LIST;
|
||||
|
||||
os.check(FUNCTION_NAME);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
@ -79,7 +79,7 @@ inline Foam::label Foam::HashSet<Key, Hash>::assignMultiple
|
||||
template<class Key, class Hash>
|
||||
Foam::HashSet<Key, Hash>::HashSet(const UList<Key>& lst)
|
||||
:
|
||||
HashTable<nil, Key, Hash>(2*lst.size())
|
||||
parent_type(2*lst.size())
|
||||
{
|
||||
for (const auto& k : lst)
|
||||
{
|
||||
@ -92,7 +92,7 @@ template<class Key, class Hash>
|
||||
template<unsigned Size>
|
||||
Foam::HashSet<Key, Hash>::HashSet(const FixedList<Key, Size>& lst)
|
||||
:
|
||||
HashTable<nil, Key, Hash>(2*lst.size())
|
||||
parent_type(2*lst.size())
|
||||
{
|
||||
for (const auto& k : lst)
|
||||
{
|
||||
@ -104,7 +104,7 @@ Foam::HashSet<Key, Hash>::HashSet(const FixedList<Key, Size>& lst)
|
||||
template<class Key, class Hash>
|
||||
Foam::HashSet<Key, Hash>::HashSet(std::initializer_list<Key> lst)
|
||||
:
|
||||
HashTable<nil, Key, Hash>(2*lst.size())
|
||||
parent_type(2*lst.size())
|
||||
{
|
||||
for (const auto& k : lst)
|
||||
{
|
||||
@ -120,7 +120,7 @@ Foam::HashSet<Key, Hash>::HashSet
|
||||
const HashTable<AnyType, Key, AnyHash>& tbl
|
||||
)
|
||||
:
|
||||
HashTable<nil, Key, Hash>(tbl.capacity())
|
||||
parent_type(tbl.capacity())
|
||||
{
|
||||
using other_iter =
|
||||
typename HashTable<AnyType, Key, AnyHash>::const_iterator;
|
||||
@ -349,7 +349,7 @@ template<class Key, class Hash>
|
||||
inline typename Foam::HashSet<Key, Hash>::const_iterator
|
||||
Foam::HashSet<Key, Hash>::begin() const
|
||||
{
|
||||
return HashTableCore::iterator_begin<const_iterator>
|
||||
return HashTableCore::iterator_cbegin<const_iterator>
|
||||
(
|
||||
static_cast<const parent_type&>(*this)
|
||||
);
|
||||
@ -360,7 +360,7 @@ template<class Key, class Hash>
|
||||
inline typename Foam::HashSet<Key, Hash>::const_iterator
|
||||
Foam::HashSet<Key, Hash>::cbegin() const
|
||||
{
|
||||
return HashTableCore::iterator_begin<const_iterator>
|
||||
return HashTableCore::iterator_cbegin<const_iterator>
|
||||
(
|
||||
static_cast<const parent_type&>(*this)
|
||||
);
|
||||
@ -379,7 +379,7 @@ template<class Key, class Hash>
|
||||
inline const typename Foam::HashSet<Key, Hash>::const_iterator&
|
||||
Foam::HashSet<Key, Hash>::end() const
|
||||
{
|
||||
return HashTableCore::iterator_end<const_iterator>();
|
||||
return HashTableCore::iterator_cend<const_iterator>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -25,7 +25,24 @@ Class
|
||||
Foam::HashSet
|
||||
|
||||
Description
|
||||
A HashTable with keys but without contents.
|
||||
A HashTable with keys but without contents that is similar to
|
||||
\c std::unordered_set.
|
||||
The entries are considered \a unordered since their placement
|
||||
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.
|
||||
|
||||
Note
|
||||
The HashSet iterator dereferences to the key, so the following
|
||||
range-for works as expected:
|
||||
\code
|
||||
HashSet<label> someLabels{10, 20, 30, 40, ...};
|
||||
for (const label i : someLabels)
|
||||
{
|
||||
Info<< "val:" << i << nl;
|
||||
}
|
||||
\endcode
|
||||
|
||||
Typedef
|
||||
Foam::wordHashSet
|
||||
@ -45,7 +62,6 @@ Description
|
||||
#define HashSet_H
|
||||
|
||||
#include "HashTable.H"
|
||||
#include "nil.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -66,7 +82,7 @@ Ostream& operator<<(Ostream& os, const HashSet<Key, Hash>& tbl);
|
||||
template<class Key=word, class Hash=string::hash>
|
||||
class HashSet
|
||||
:
|
||||
public HashTable<nil, Key, Hash>
|
||||
public HashTable<zero::null, Key, Hash>
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
@ -94,7 +110,7 @@ public:
|
||||
typedef HashSet<Key, Hash> this_type;
|
||||
|
||||
//- The template instance used for the parent HashTable
|
||||
typedef HashTable<nil, Key, Hash> parent_type;
|
||||
typedef HashTable<zero::null, Key, Hash> parent_type;
|
||||
|
||||
//- An iterator, returning reference to the key
|
||||
using iterator = typename parent_type::key_iterator;
|
||||
@ -105,13 +121,19 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null with default (128) table size
|
||||
HashSet()
|
||||
:
|
||||
parent_type()
|
||||
{}
|
||||
|
||||
//- Construct given initial size
|
||||
HashSet(const label size = 128)
|
||||
explicit HashSet(const label size)
|
||||
:
|
||||
parent_type(size)
|
||||
{}
|
||||
|
||||
//- Construct from Istream
|
||||
//- Construct from Istream with default table size
|
||||
HashSet(Istream& is)
|
||||
:
|
||||
parent_type(is)
|
||||
@ -140,13 +162,13 @@ public:
|
||||
{}
|
||||
|
||||
//- Construct by transferring the parameter contents
|
||||
HashSet(const Xfer<HashSet<Key, Hash>>& hs)
|
||||
HashSet(const Xfer<this_type>& hs)
|
||||
:
|
||||
parent_type(hs)
|
||||
{}
|
||||
|
||||
//- Construct by transferring the parameter contents
|
||||
HashSet(const Xfer<HashTable<nil, Key, Hash>>& hs)
|
||||
HashSet(const Xfer<parent_type>& hs)
|
||||
:
|
||||
parent_type(hs)
|
||||
{}
|
||||
@ -166,7 +188,7 @@ public:
|
||||
// not previously exist in the set.
|
||||
bool insert(const Key& key)
|
||||
{
|
||||
return this->parent_type::insert(key, nil());
|
||||
return this->parent_type::insert(key, zero::null());
|
||||
}
|
||||
|
||||
//- Insert keys from the list of Key
|
||||
@ -182,26 +204,26 @@ public:
|
||||
// \return The number of new elements inserted
|
||||
label insert(std::initializer_list<Key> lst);
|
||||
|
||||
//- Same as insert (cannot overwrite nil content)
|
||||
//- Same as insert (no value to overwrite)
|
||||
bool set(const Key& key)
|
||||
{
|
||||
return insert(key);
|
||||
}
|
||||
|
||||
//- Same as insert (cannot overwrite nil content)
|
||||
//- Same as insert (no value to overwrite)
|
||||
label set(const UList<Key>& lst)
|
||||
{
|
||||
return insert(lst);
|
||||
}
|
||||
|
||||
//- Same as insert (cannot overwrite nil content)
|
||||
//- Same as insert (no value to overwrite)
|
||||
template<unsigned Size>
|
||||
label set(const FixedList<Key, Size>& lst)
|
||||
{
|
||||
return insert(lst);
|
||||
}
|
||||
|
||||
//- Same as insert (cannot overwrite nil content)
|
||||
//- Same as insert (no value to overwrite)
|
||||
label set(std::initializer_list<Key> lst)
|
||||
{
|
||||
return insert(lst);
|
||||
@ -331,22 +353,22 @@ public:
|
||||
// Logical operations
|
||||
|
||||
//- Combine entries from HashSets
|
||||
void operator|=(const HashSet<Key, Hash>& rhs);
|
||||
void operator|=(const this_type& rhs);
|
||||
|
||||
//- Only retain entries found in both HashSets
|
||||
inline void operator&=(const HashSet<Key, Hash>& rhs);
|
||||
inline void operator&=(const this_type& rhs);
|
||||
|
||||
//- Only retain unique entries (xor)
|
||||
void operator^=(const HashSet<Key, Hash>& rhs);
|
||||
void operator^=(const this_type& rhs);
|
||||
|
||||
//- Add entries listed in the given HashSet to this HashSet
|
||||
inline void operator+=(const HashSet<Key, Hash>& rhs)
|
||||
inline void operator+=(const this_type& rhs)
|
||||
{
|
||||
this->operator|=(rhs);
|
||||
}
|
||||
|
||||
//- Remove entries listed in the given HashSet from this HashSet
|
||||
inline void operator-=(const HashSet<Key, Hash>& rhs);
|
||||
inline void operator-=(const this_type& rhs);
|
||||
|
||||
|
||||
// IOstream Operator
|
||||
|
||||
@ -61,21 +61,27 @@ Foam::label Foam::HashTable<T, Key, Hash>::eraseMultiple
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::HashTable<T, Key, Hash>::HashTable()
|
||||
:
|
||||
HashTable<T, Key, Hash>(128)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::HashTable<T, Key, Hash>::HashTable(const label size)
|
||||
:
|
||||
HashTableCore(),
|
||||
nElmts_(0),
|
||||
tableSize_(HashTableCore::canonicalSize(size)),
|
||||
size_(0),
|
||||
capacity_(HashTableCore::canonicalSize(size)),
|
||||
table_(nullptr)
|
||||
{
|
||||
if (tableSize_)
|
||||
if (capacity_)
|
||||
{
|
||||
table_ = new hashedEntry*[tableSize_];
|
||||
|
||||
for (label hashIdx = 0; hashIdx < tableSize_; ++hashIdx)
|
||||
table_ = new node_type*[capacity_];
|
||||
for (label i=0; i < capacity_; ++i)
|
||||
{
|
||||
table_[hashIdx] = nullptr;
|
||||
table_[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,7 +90,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(const label size)
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
|
||||
:
|
||||
HashTable<T, Key, Hash>(ht.tableSize_)
|
||||
HashTable<T, Key, Hash>(ht.capacity_)
|
||||
{
|
||||
for (const_iterator iter = ht.cbegin(); iter != ht.cend(); ++iter)
|
||||
{
|
||||
@ -96,10 +102,7 @@ Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::HashTable<T, Key, Hash>::HashTable(HashTable<T, Key, Hash>&& ht)
|
||||
:
|
||||
HashTableCore(),
|
||||
nElmts_(0),
|
||||
tableSize_(0),
|
||||
table_(nullptr)
|
||||
HashTable<T, Key, Hash>(0)
|
||||
{
|
||||
transfer(ht);
|
||||
}
|
||||
@ -111,10 +114,7 @@ Foam::HashTable<T, Key, Hash>::HashTable
|
||||
const Xfer<HashTable<T, Key, Hash>>& ht
|
||||
)
|
||||
:
|
||||
HashTableCore(),
|
||||
nElmts_(0),
|
||||
tableSize_(0),
|
||||
table_(nullptr)
|
||||
HashTable<T, Key, Hash>(0)
|
||||
{
|
||||
transfer(ht());
|
||||
}
|
||||
@ -150,110 +150,10 @@ Foam::HashTable<T, Key, Hash>::~HashTable()
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::found(const Key& key) const
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
{
|
||||
if (key == ep->key_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "Entry " << key << " not found in hash table\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
typename Foam::HashTable<T, Key, Hash>::iterator
|
||||
Foam::HashTable<T, Key, Hash>::find
|
||||
(
|
||||
const Key& key
|
||||
)
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
{
|
||||
if (key == ep->key_)
|
||||
{
|
||||
return iterator(this, ep, hashIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "Entry " << key << " not found in hash table\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return iterator();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::find
|
||||
(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
return this->cfind(key);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::cfind
|
||||
(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
{
|
||||
if (key == ep->key_)
|
||||
{
|
||||
return const_iterator(this, ep, hashIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "Entry " << key << " not found in hash table\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
|
||||
{
|
||||
List<Key> keyLst(nElmts_);
|
||||
List<Key> keyLst(size_);
|
||||
label count = 0;
|
||||
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
@ -297,7 +197,7 @@ Foam::List<Key> Foam::HashTable<T, Key, Hash>::tocKeys
|
||||
const bool invert
|
||||
) const
|
||||
{
|
||||
List<Key> keyLst(nElmts_);
|
||||
List<Key> keyLst(size_);
|
||||
label count = 0;
|
||||
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
@ -323,7 +223,7 @@ Foam::List<Key> Foam::HashTable<T, Key, Hash>::tocValues
|
||||
const bool invert
|
||||
) const
|
||||
{
|
||||
List<Key> keyLst(nElmts_);
|
||||
List<Key> keyLst(size_);
|
||||
label count = 0;
|
||||
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
@ -349,7 +249,7 @@ Foam::List<Key> Foam::HashTable<T, Key, Hash>::tocEntries
|
||||
const bool invert
|
||||
) const
|
||||
{
|
||||
List<Key> keyLst(nElmts_);
|
||||
List<Key> keyLst(size_);
|
||||
label count = 0;
|
||||
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
@ -438,36 +338,36 @@ bool Foam::HashTable<T, Key, Hash>::set
|
||||
(
|
||||
const Key& key,
|
||||
const T& obj,
|
||||
const bool protect
|
||||
const bool overwrite
|
||||
)
|
||||
{
|
||||
if (!tableSize_)
|
||||
if (!capacity_)
|
||||
{
|
||||
resize(2);
|
||||
}
|
||||
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
const label index = hashKeyIndex(key);
|
||||
|
||||
hashedEntry* existing = nullptr;
|
||||
hashedEntry* prev = nullptr;
|
||||
node_type* curr = nullptr;
|
||||
node_type* prev = nullptr;
|
||||
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
for (node_type* ep = table_[index]; ep; ep = ep->next_)
|
||||
{
|
||||
if (key == ep->key_)
|
||||
if (key == ep->key())
|
||||
{
|
||||
existing = ep;
|
||||
curr = ep;
|
||||
break;
|
||||
}
|
||||
prev = ep;
|
||||
}
|
||||
|
||||
if (!existing)
|
||||
if (!curr)
|
||||
{
|
||||
// Not found, insert it at the head
|
||||
table_[hashIdx] = new hashedEntry(key, obj, table_[hashIdx]);
|
||||
nElmts_++;
|
||||
table_[index] = new node_type(key, obj, table_[index]);
|
||||
++size_;
|
||||
|
||||
if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize)
|
||||
if (double(size_)/capacity_ > 0.8 && capacity_ < maxTableSize)
|
||||
{
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
@ -476,13 +376,35 @@ bool Foam::HashTable<T, Key, Hash>::set
|
||||
}
|
||||
#endif
|
||||
|
||||
resize(2*tableSize_);
|
||||
resize(2*capacity_);
|
||||
}
|
||||
}
|
||||
else if (protect)
|
||||
else if (overwrite)
|
||||
{
|
||||
// Found - but protected from overwriting
|
||||
// this corresponds to the STL 'insert' convention
|
||||
// Overwrite current entry (Perl convention).
|
||||
|
||||
node_type* ep = curr->next_; // next in the linked list
|
||||
|
||||
// In some cases the delete/new could be avoided in favour of move
|
||||
// assignment, but cannot be certain that all objects support this
|
||||
// or that it behaves the same as a copy construct.
|
||||
|
||||
delete curr;
|
||||
ep = new node_type(key, obj, ep);
|
||||
|
||||
// Replace current element - within list or insert at the head
|
||||
if (prev)
|
||||
{
|
||||
prev->next_ = ep;
|
||||
}
|
||||
else
|
||||
{
|
||||
table_[index] = ep;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not overwrite existing entry (STL 'insert' convention)
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
@ -492,99 +414,22 @@ bool Foam::HashTable<T, Key, Hash>::set
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found - overwrite existing entry
|
||||
// this corresponds to the Perl convention
|
||||
hashedEntry* ep = new hashedEntry(key, obj, existing->next_);
|
||||
|
||||
// Replace existing element - within list or insert at the head
|
||||
if (prev)
|
||||
{
|
||||
prev->next_ = ep;
|
||||
}
|
||||
else
|
||||
{
|
||||
table_[hashIdx] = ep;
|
||||
}
|
||||
|
||||
delete existing;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::iterator_base::erase()
|
||||
{
|
||||
// Note: entryPtr_ is nullptr for end(), so this catches that too
|
||||
if (entryPtr_)
|
||||
{
|
||||
// Search element before entryPtr_
|
||||
entry_type* prev = nullptr;
|
||||
|
||||
for
|
||||
(
|
||||
entry_type* ep = hashTable_->table_[hashIndex_];
|
||||
ep;
|
||||
ep = ep->next_
|
||||
)
|
||||
{
|
||||
if (ep == entryPtr_)
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev = ep;
|
||||
}
|
||||
|
||||
if (prev)
|
||||
{
|
||||
// Has an element before entryPtr - reposition to there
|
||||
prev->next_ = entryPtr_->next_;
|
||||
delete entryPtr_;
|
||||
entryPtr_ = prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
// entryPtr was first element on SLList
|
||||
hashTable_->table_[hashIndex_] = entryPtr_->next_;
|
||||
delete entryPtr_;
|
||||
|
||||
// Assign any non-nullptr value so it doesn't look like end()
|
||||
entryPtr_ = reinterpret_cast<hashedEntry*>(this);
|
||||
|
||||
// Mark with special hashIndex value to signal it has been rewound.
|
||||
// The next increment will bring it back to the present location.
|
||||
//
|
||||
// From the current position 'curPos', we wish to continue at
|
||||
// prevPos='curPos-1', which we mark as markPos='-curPos-1'.
|
||||
// The negative lets us notice it is special, the extra '-1'
|
||||
// is needed to avoid ambiguity for position '0'.
|
||||
// To retrieve prevPos, we would later use '-(markPos+1) - 1'
|
||||
hashIndex_ = -hashIndex_ - 1;
|
||||
}
|
||||
|
||||
hashTable_->nElmts_--;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::erase(const iterator& iter)
|
||||
{
|
||||
// NOTE: We use (const iterator&) here, but manipulate its contents anyhow.
|
||||
// NOTE: we use (const iterator&) here, but treat its contents as mutable.
|
||||
//
|
||||
// The parameter should be (iterator&), but then the compiler doesn't find
|
||||
// it correctly and tries to call as (iterator) instead.
|
||||
//
|
||||
// Adjust iterator after erase
|
||||
return const_cast<iterator&>(iter).erase();
|
||||
|
||||
iterator& it = const_cast<iterator&>(iter);
|
||||
|
||||
return iterator_erase(it.entry_, it.index_);
|
||||
}
|
||||
|
||||
|
||||
@ -599,7 +444,7 @@ bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::label Foam::HashTable<T, Key, Hash>::erase(const UList<Key>& keys)
|
||||
{
|
||||
return eraseMultiple(keys.begin(), keys.end());
|
||||
return eraseMultiple(keys.cbegin(), keys.cend());
|
||||
}
|
||||
|
||||
|
||||
@ -610,7 +455,7 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase
|
||||
const FixedList<Key, Size>& keys
|
||||
)
|
||||
{
|
||||
return eraseMultiple(keys.begin(), keys.end());
|
||||
return eraseMultiple(keys.cbegin(), keys.cend());
|
||||
}
|
||||
|
||||
|
||||
@ -634,17 +479,14 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase
|
||||
const label nTotal = this->size();
|
||||
label changed = 0;
|
||||
|
||||
using other_iter =
|
||||
typename HashTable<AnyType, Key, AnyHash>::const_iterator;
|
||||
|
||||
if (other.size() <= nTotal)
|
||||
{
|
||||
// The other is smaller/same-size, use its keys for removal
|
||||
|
||||
for
|
||||
(
|
||||
other_iter iter = other.begin();
|
||||
changed < nTotal && iter != other.end(); // terminate early
|
||||
auto iter = other.cbegin();
|
||||
changed < nTotal && iter != other.cend(); // Terminate early
|
||||
++iter
|
||||
)
|
||||
{
|
||||
@ -660,7 +502,7 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase
|
||||
for
|
||||
(
|
||||
iterator iter = begin();
|
||||
changed < nTotal && iter != end(); // terminate early
|
||||
changed < nTotal && iter != end(); // Terminate early
|
||||
++iter
|
||||
)
|
||||
{
|
||||
@ -711,9 +553,10 @@ Foam::label Foam::HashTable<T, Key, Hash>::retain
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||
{
|
||||
const label newSize = HashTableCore::canonicalSize(sz);
|
||||
const label newCapacity = HashTableCore::canonicalSize(sz);
|
||||
const label oldCapacity = capacity_;
|
||||
|
||||
if (newSize == tableSize_)
|
||||
if (newCapacity == oldCapacity)
|
||||
{
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
@ -724,46 +567,85 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HashTable<T, Key, Hash>* tmpTable = new HashTable<T, Key, Hash>(newSize);
|
||||
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
else if (!newCapacity)
|
||||
{
|
||||
tmpTable->insert(iter.key(), iter.object());
|
||||
// Special treatment for resize(0)
|
||||
if (size_)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "HashTable contains " << size_ << " cannot resize(0)"
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (table_)
|
||||
{
|
||||
delete[] table_;
|
||||
capacity_ = 0;
|
||||
}
|
||||
|
||||
table_ = nullptr;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const label oldSize = tableSize_;
|
||||
tableSize_ = tmpTable->tableSize_;
|
||||
tmpTable->tableSize_ = oldSize;
|
||||
// Swap primary table entries: size_ is left untouched
|
||||
|
||||
hashedEntry** oldTable = table_;
|
||||
table_ = tmpTable->table_;
|
||||
tmpTable->table_ = oldTable;
|
||||
auto oldTable = table_;
|
||||
capacity_ = newCapacity;
|
||||
|
||||
delete tmpTable;
|
||||
table_ = new node_type*[capacity_];
|
||||
for (label i=0; i < capacity_; ++i)
|
||||
{
|
||||
table_[i] = nullptr;
|
||||
}
|
||||
|
||||
// Move to new table[] but with new chaining.
|
||||
|
||||
label nMove = size_; // Allow early completion
|
||||
for (label i=0; nMove && i < oldCapacity; ++i)
|
||||
{
|
||||
for (node_type* ep = oldTable[i]; ep; /*nil*/)
|
||||
{
|
||||
node_type* next = ep->next_;
|
||||
|
||||
// Move to new location
|
||||
{
|
||||
const label newIdx = hashKeyIndex(ep->key());
|
||||
|
||||
ep->next_ = table_[newIdx]; // add to head
|
||||
table_[newIdx] = ep;
|
||||
}
|
||||
|
||||
ep = next; // continue in the linked-list
|
||||
--nMove; // note any early completion
|
||||
}
|
||||
oldTable[i] = nullptr;
|
||||
}
|
||||
|
||||
if (oldTable)
|
||||
{
|
||||
delete[] oldTable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::clear()
|
||||
{
|
||||
if (nElmts_)
|
||||
for (label i=0; size_ && i<capacity_; ++i)
|
||||
{
|
||||
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
||||
for (node_type* ep = table_[i]; ep; /*nil*/)
|
||||
{
|
||||
if (table_[hashIdx])
|
||||
{
|
||||
hashedEntry* ep = table_[hashIdx];
|
||||
while (hashedEntry* next = ep->next_)
|
||||
{
|
||||
delete ep;
|
||||
ep = next;
|
||||
}
|
||||
delete ep;
|
||||
table_[hashIdx] = nullptr;
|
||||
}
|
||||
node_type* next = ep->next_;
|
||||
|
||||
delete ep;
|
||||
|
||||
ep = next; // continue in the linked-list
|
||||
--size_; // note any early completion
|
||||
}
|
||||
nElmts_ = 0;
|
||||
table_[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -779,30 +661,31 @@ void Foam::HashTable<T, Key, Hash>::clearStorage()
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::swap(HashTable<T, Key, Hash>& ht)
|
||||
{
|
||||
Foam::Swap(table_, ht.table_);
|
||||
Foam::Swap(tableSize_, ht.tableSize_);
|
||||
Foam::Swap(nElmts_, ht.nElmts_);
|
||||
Foam::Swap(size_, ht.size_);
|
||||
Foam::Swap(capacity_, ht.capacity_);
|
||||
Foam::Swap(table_, ht.table_);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::transfer(HashTable<T, Key, Hash>& ht)
|
||||
{
|
||||
// As per the Destructor
|
||||
// As per destructor
|
||||
if (table_)
|
||||
{
|
||||
clear();
|
||||
delete[] table_;
|
||||
}
|
||||
|
||||
tableSize_ = ht.tableSize_;
|
||||
ht.tableSize_ = 0;
|
||||
size_ = ht.size_;
|
||||
ht.size_ = 0;
|
||||
|
||||
capacity_ = ht.capacity_;
|
||||
ht.capacity_ = 0;
|
||||
|
||||
table_ = ht.table_;
|
||||
ht.table_ = nullptr;
|
||||
|
||||
nElmts_ = ht.nElmts_;
|
||||
ht.nElmts_ = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -904,9 +787,9 @@ void Foam::HashTable<T, Key, Hash>::operator=
|
||||
}
|
||||
|
||||
// Could be zero-sized from a previous transfer()
|
||||
if (!tableSize_)
|
||||
if (!capacity_)
|
||||
{
|
||||
resize(rhs.tableSize_);
|
||||
resize(rhs.capacity_);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -927,7 +810,7 @@ void Foam::HashTable<T, Key, Hash>::operator=
|
||||
)
|
||||
{
|
||||
// Could be zero-sized from a previous transfer()
|
||||
if (!tableSize_)
|
||||
if (!capacity_)
|
||||
{
|
||||
resize(2*lst.size());
|
||||
}
|
||||
@ -975,7 +858,7 @@ bool Foam::HashTable<T, Key, Hash>::operator==
|
||||
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
const_iterator other = this->cfind(iter.key());
|
||||
const const_iterator other(this->cfind(iter.key()));
|
||||
|
||||
if (!other.found() || other.object() != iter.object())
|
||||
{
|
||||
@ -997,8 +880,11 @@ bool Foam::HashTable<T, Key, Hash>::operator!=
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Iterators, Friend Operators
|
||||
|
||||
#include "HashTableIter.C"
|
||||
#include "HashTableIO.C"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -25,14 +25,15 @@ Class
|
||||
Foam::HashTable
|
||||
|
||||
Description
|
||||
An STL-conforming hash table.
|
||||
A HashTable similar to \c std::unordered_map.
|
||||
The entries are considered \a unordered since their placement
|
||||
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.
|
||||
|
||||
Note
|
||||
Hashing index collisions are handled via chaining using a singly-linked
|
||||
list with the colliding entry being added to the head of the linked
|
||||
list. Thus copying the hash table (or indeed even resizing it) will
|
||||
often result in a different hash order. Use a sorted table-of-contents
|
||||
when the hash order is important.
|
||||
Internally the table uses closed addressing into a flat storage space
|
||||
with collisions handled by linked-list chaining.
|
||||
|
||||
The end iterator of all hash-tables has a nullptr to the hash entry.
|
||||
Thus avoid separate allocation for each table and use a single one with
|
||||
@ -41,10 +42,38 @@ Note
|
||||
a nullptr as its first data member.
|
||||
The nullObject is such an item (with a nullptr data member).
|
||||
|
||||
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.
|
||||
|
||||
The HashTable iterator:
|
||||
\code
|
||||
forAllConstIters(table, iter)
|
||||
{
|
||||
Info<< "val:" << *iter << nl
|
||||
<< "key:" << iter.key() << nl;
|
||||
<< "val:" << iter.object() << nl;
|
||||
}
|
||||
\endcode
|
||||
whereas for the \c std::unordered_map iterator:
|
||||
\code
|
||||
forAllConstIters(stdmap, iter)
|
||||
{
|
||||
Info<< "key/val:" << *iter << nl
|
||||
<< "key:" << iter->first << nl
|
||||
<< "val:" << iter->second << nl;
|
||||
}
|
||||
\endcode
|
||||
This difference is most evident when using range-for syntax.
|
||||
|
||||
SourceFiles
|
||||
HashTableI.H
|
||||
HashTableIterI.H
|
||||
HashTable.C
|
||||
HashTableIO.C
|
||||
HashTableIter.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -52,6 +81,7 @@ SourceFiles
|
||||
#define HashTable_H
|
||||
|
||||
#include "word.H"
|
||||
#include "zero.H"
|
||||
#include "Xfer.H"
|
||||
#include "Hash.H"
|
||||
#include "HashTableCore.H"
|
||||
@ -80,7 +110,7 @@ Ostream& operator<<(Ostream& os, const HashTable<T, Key, Hash>& tbl);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class HashTable Declaration
|
||||
Class HashTable Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class T, class Key=word, class Hash=string::hash>
|
||||
@ -88,6 +118,140 @@ class HashTable
|
||||
:
|
||||
public HashTableCore
|
||||
{
|
||||
// Private types for table entries
|
||||
|
||||
//- 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:
|
||||
//- Disallow default bitwise copy construct / assignment
|
||||
pair_entry(const pair_entry&) = delete;
|
||||
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:
|
||||
//- Disallow default bitwise copy construct / assignment
|
||||
unary_entry(const unary_entry&) = delete;
|
||||
void operator=(const unary_entry&) = delete;
|
||||
};
|
||||
|
||||
|
||||
//- Hashed node with a linked-list for collisions
|
||||
typedef typename std::conditional
|
||||
<
|
||||
std::is_same<zero::null, typename std::remove_cv<T>::type>::value,
|
||||
unary_entry,
|
||||
pair_entry
|
||||
>::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.
|
||||
bool set(const Key& key, const T& obj, const bool overwrite);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- The template instance used for this HashTable
|
||||
@ -96,18 +260,25 @@ public:
|
||||
|
||||
// STL type definitions
|
||||
|
||||
//- Type of keys that the HashTable uses.
|
||||
//- The second template parameter, type of keys used.
|
||||
typedef Key key_type;
|
||||
|
||||
//- Type of values that the HashTable contains.
|
||||
//- The first template parameter, type of objects contained.
|
||||
typedef T mapped_type;
|
||||
|
||||
//- Same as mapped_type for OpenFOAM HashTables
|
||||
// Note that this is different than the std::map definition.
|
||||
typedef T value_type;
|
||||
|
||||
//- The third template parameter, the hash index method.
|
||||
typedef Hash hasher;
|
||||
|
||||
//- The type used for storing into value_type objects.
|
||||
// This type is usually value_type&.
|
||||
// This type is usually 'value_type*'.
|
||||
typedef T* pointer;
|
||||
|
||||
//- The type used for storing into value_type objects.
|
||||
// This type is usually value_type&.
|
||||
// This type is usually 'value_type&'.
|
||||
typedef T& reference;
|
||||
|
||||
//- The type used for reading from constant value_type objects.
|
||||
@ -129,65 +300,14 @@ public:
|
||||
//- Forward iterator with const access
|
||||
class const_iterator;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private data type for table entries
|
||||
|
||||
//- Structure to hold a hashed entry, with a linked-list for collisions
|
||||
struct hashedEntry
|
||||
{
|
||||
//- The lookup key
|
||||
Key key_;
|
||||
|
||||
//- The data object
|
||||
T obj_;
|
||||
|
||||
//- Pointer to next hashedEntry in sub-list
|
||||
hashedEntry* next_;
|
||||
|
||||
//- Construct from key, object, next pointer
|
||||
inline hashedEntry(const Key& key, const T& obj, hashedEntry* next);
|
||||
|
||||
private:
|
||||
//- Disallow default bitwise copy construct
|
||||
hashedEntry(const hashedEntry&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const hashedEntry&) = delete;
|
||||
};
|
||||
|
||||
|
||||
// Private data: size of table, the table and current number of elements
|
||||
|
||||
//- The current number of elements in table
|
||||
label nElmts_;
|
||||
|
||||
//- Number of primary entries allocated in table
|
||||
label tableSize_;
|
||||
|
||||
//- The table of primary entries
|
||||
hashedEntry** 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.
|
||||
bool set(const Key& key, const T& obj, const bool protect);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
//- Internally used base for iterator and const_iterator
|
||||
class iterator_base;
|
||||
template<bool Const> class Iterator;
|
||||
|
||||
//- Friendship with the iterator_base is required.
|
||||
friend class iterator_base;
|
||||
//- Friendship with the base iterator is required.
|
||||
friend class Iterator<true>;
|
||||
friend class Iterator<false>;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
@ -205,20 +325,23 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given initial table size
|
||||
HashTable(const label size = 128);
|
||||
//- Construct null with default (128) table size
|
||||
HashTable();
|
||||
|
||||
//- Construct from Istream
|
||||
//- Construct given initial table size
|
||||
explicit HashTable(const label size);
|
||||
|
||||
//- Construct from Istream with default table size
|
||||
HashTable(Istream& is, const label size = 128);
|
||||
|
||||
//- Construct as copy
|
||||
HashTable(const HashTable<T, Key, Hash>& ht);
|
||||
HashTable(const this_type& ht);
|
||||
|
||||
//- Move construct
|
||||
HashTable(HashTable<T, Key, Hash>&& ht);
|
||||
HashTable(this_type&& ht);
|
||||
|
||||
//- Construct by transferring the parameter contents
|
||||
HashTable(const Xfer<HashTable<T, Key, Hash>>& ht);
|
||||
HashTable(const Xfer<this_type>& ht);
|
||||
|
||||
//- Construct from an initializer list
|
||||
HashTable(std::initializer_list<std::pair<Key, T>> lst);
|
||||
@ -242,19 +365,19 @@ public:
|
||||
inline bool empty() const;
|
||||
|
||||
//- Return true if hashed entry is found in table
|
||||
bool found(const Key& key) const;
|
||||
inline bool found(const Key& key) const;
|
||||
|
||||
//- Find and return an iterator set at the hashed entry
|
||||
// If not found iterator = end()
|
||||
iterator find(const Key& key);
|
||||
inline iterator find(const Key& key);
|
||||
|
||||
//- Find and return an const_iterator set at the hashed entry
|
||||
// If not found iterator = end()
|
||||
const_iterator find(const Key& key) const;
|
||||
inline const_iterator find(const Key& key) const;
|
||||
|
||||
//- Find and return an const_iterator set at the hashed entry
|
||||
// If not found iterator = end()
|
||||
const_iterator cfind(const Key& key) const;
|
||||
inline const_iterator cfind(const Key& key) const;
|
||||
|
||||
//- Return hashed entry if it exists, or return the given default
|
||||
inline const T& lookup(const Key& key, const T& deflt) const;
|
||||
@ -512,149 +635,157 @@ protected:
|
||||
// and prevent most external usage.
|
||||
// iterator and const_iterator have the same size, allowing
|
||||
// us to reinterpret_cast between them (if desired)
|
||||
class iterator_base
|
||||
|
||||
template<bool Const>
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
// Public typedefs
|
||||
using table_type = this_type;
|
||||
using key_type = this_type::key_type;
|
||||
// Typedefs
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = this_type::difference_type;
|
||||
using difference_type = this_type::difference_type;
|
||||
|
||||
private:
|
||||
using entry_type = hashedEntry;
|
||||
//- The HashTable container type
|
||||
using table_type = typename std::conditional
|
||||
<
|
||||
Const,
|
||||
const this_type,
|
||||
this_type
|
||||
>::type;
|
||||
|
||||
// Private Data
|
||||
//- The node-type being addressed
|
||||
using node_type = typename std::conditional
|
||||
<
|
||||
Const,
|
||||
const this_type::node_type,
|
||||
this_type::node_type
|
||||
>::type;
|
||||
|
||||
//- Currently selected entry.
|
||||
// MUST be the first member for easy comparison between iterators
|
||||
// and for reinterpret_cast from nullObject
|
||||
entry_type* entryPtr_;
|
||||
//- The key type
|
||||
using key_type = this_type::key_type;
|
||||
|
||||
//- Pointer to the hash-table for which this is an iterator
|
||||
// This allows use of the default bitwise copy/assignment
|
||||
table_type* hashTable_;
|
||||
//- The object type being addressed
|
||||
using mapped_type = typename std::conditional
|
||||
<
|
||||
Const,
|
||||
const this_type::mapped_type,
|
||||
this_type::mapped_type
|
||||
>::type;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- True if iterator points to an entry
|
||||
// This can be used directly instead of comparing to end()
|
||||
inline bool found() const;
|
||||
|
||||
//- The key associated with the iterator
|
||||
inline const Key& key() const;
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Compare hash-entry element pointers.
|
||||
// Independent of const/non-const access
|
||||
inline bool operator==(const Iterator<true>& iter) const;
|
||||
inline bool operator!=(const Iterator<true>& iter) const;
|
||||
|
||||
inline bool operator==(const Iterator<false>& iter) const;
|
||||
inline bool operator!=(const Iterator<false>& iter) const;
|
||||
|
||||
//- Current hash index within the hash-table data.
|
||||
// A signed value, since erase() uses a negative value to signal
|
||||
// the erasure state.
|
||||
label hashIndex_;
|
||||
|
||||
protected:
|
||||
friend class HashTable; // For begin/find constructors
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The selected entry.
|
||||
// MUST be the first member for easy comparison between iterators
|
||||
// and for reinterpret_cast from nullObject
|
||||
node_type* entry_;
|
||||
|
||||
//- The hash-table container being iterated on.
|
||||
// Using a pointer allows default bitwise copy/assignment
|
||||
table_type* container_;
|
||||
|
||||
//- Index within the hash-table data.
|
||||
// A signed value, since iterator_erase() needs a negative value
|
||||
// to mark the position.
|
||||
label index_;
|
||||
|
||||
|
||||
// Protected Constructors
|
||||
|
||||
//- Construct null (end iterator)
|
||||
inline Iterator();
|
||||
|
||||
//- Construct from begin of hash-table
|
||||
inline Iterator(bool, table_type* tbl);
|
||||
|
||||
//- Construct by finding key in hash table
|
||||
inline Iterator(table_type* tbl, const Key& key);
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Increment to the next position
|
||||
inline void increment();
|
||||
|
||||
//- The referenced object/value element
|
||||
inline T& element() const;
|
||||
//- The object associated with the iterator
|
||||
inline mapped_type& object() const
|
||||
{
|
||||
return entry_->mapped();
|
||||
}
|
||||
|
||||
//- Erase the entry at the current position
|
||||
bool erase();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null (end iterator)
|
||||
inline iterator_base();
|
||||
|
||||
//- Construct from begin of hash-table
|
||||
inline explicit iterator_base(const table_type* hashTbl);
|
||||
|
||||
//- Construct from hash table, element and hash index
|
||||
inline iterator_base
|
||||
(
|
||||
const table_type* hashTbl,
|
||||
const entry_type* elmt,
|
||||
const label hashIndex
|
||||
);
|
||||
|
||||
// Member functions/operators
|
||||
|
||||
//- True if iterator points to an entry
|
||||
// This can be used directly instead of comparing to end()
|
||||
inline bool found() const;
|
||||
|
||||
//- Return the Key corresponding to the iterator
|
||||
inline const Key& key() const;
|
||||
|
||||
//- Compare hash-entry element pointers
|
||||
inline bool operator==(const iterator_base& iter) const;
|
||||
inline bool operator!=(const iterator_base& iter) const;
|
||||
//- Permit an explicit cast to the other (const/non-const) searcher
|
||||
inline explicit operator const Iterator<!Const>&() const
|
||||
{
|
||||
return *reinterpret_cast<const Iterator<!Const>*>(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- 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:
|
||||
|
||||
//- An iterator wrapper for returning a reference to the key
|
||||
template<class WrappedIterator>
|
||||
class key_iterator_base
|
||||
:
|
||||
public WrappedIterator
|
||||
{
|
||||
public:
|
||||
using value_type = this_type::key_type;
|
||||
using pointer = const Key*;
|
||||
using reference = const Key&;
|
||||
|
||||
//- Implicit conversion
|
||||
inline key_iterator_base(const WrappedIterator& iter);
|
||||
|
||||
//- Return the key
|
||||
inline reference operator*() const;
|
||||
inline reference operator()() const;
|
||||
|
||||
inline key_iterator_base& operator++();
|
||||
inline key_iterator_base operator++(int);
|
||||
};
|
||||
|
||||
|
||||
// STL iterator
|
||||
|
||||
//- Forward iterator with non-const access
|
||||
class iterator
|
||||
:
|
||||
public iterator_base
|
||||
public Iterator<false>
|
||||
{
|
||||
friend class HashTable; // Uses iterator::erase() method
|
||||
using entry_type = hashedEntry;
|
||||
|
||||
public:
|
||||
// Typedefs
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = this_type::difference_type;
|
||||
|
||||
// Public typedefs
|
||||
using table_type = this_type;
|
||||
using value_type = this_type::value_type;
|
||||
using pointer = this_type::pointer;
|
||||
using reference = this_type::reference;
|
||||
using key_type = this_type::key_type;
|
||||
using mapped_type = this_type::mapped_type;
|
||||
using value_type = this_type::value_type;
|
||||
using pointer = this_type::pointer;
|
||||
using reference = this_type::reference;
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null (end iterator)
|
||||
inline iterator();
|
||||
inline iterator() {}
|
||||
|
||||
//- Construct from begin of hash-table
|
||||
inline explicit iterator(table_type* hashTbl);
|
||||
//- Copy construct from similar access type
|
||||
inline explicit iterator(const Iterator<false>& iter)
|
||||
:
|
||||
Iterator<false>(iter)
|
||||
{}
|
||||
|
||||
//- Construct from hash table, element and hash index
|
||||
// Used by the hash-table find() method.
|
||||
inline iterator
|
||||
(
|
||||
table_type* hashTbl,
|
||||
entry_type* elmt,
|
||||
const label hashIndex
|
||||
);
|
||||
|
||||
// Member functions/operators
|
||||
|
||||
//- Return non-const access to referenced object
|
||||
inline reference object() const;
|
||||
//- Non-const access to referenced object
|
||||
using Iterator<false>::object;
|
||||
|
||||
//- Return non-const access to referenced object
|
||||
inline reference operator*() const;
|
||||
inline reference operator()() const;
|
||||
//- Non-const access to referenced object
|
||||
inline reference operator*() const { return this->object(); }
|
||||
inline reference operator()() const { return this->object(); }
|
||||
|
||||
inline iterator& operator++();
|
||||
inline iterator operator++(int);
|
||||
@ -666,54 +797,111 @@ public:
|
||||
//- Forward iterator with const access
|
||||
class const_iterator
|
||||
:
|
||||
public iterator_base
|
||||
public Iterator<true>
|
||||
{
|
||||
using entry_type = const hashedEntry;
|
||||
|
||||
public:
|
||||
// Typedefs
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = this_type::difference_type;
|
||||
|
||||
// Public typedefs
|
||||
using table_type = const this_type;
|
||||
using value_type = const this_type::value_type;
|
||||
using pointer = this_type::const_pointer;
|
||||
using reference = this_type::const_reference;
|
||||
using key_type = this_type::key_type;
|
||||
using mapped_type = const this_type::mapped_type;
|
||||
using value_type = const this_type::value_type;
|
||||
using pointer = this_type::const_pointer;
|
||||
using reference = this_type::const_reference;
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null (end iterator)
|
||||
inline const_iterator();
|
||||
inline const_iterator() {}
|
||||
|
||||
//- Construct from begin of hash-table
|
||||
inline explicit const_iterator(table_type* hashTbl);
|
||||
//- Copy construct from similar access type
|
||||
inline explicit const_iterator(const Iterator<true>& iter)
|
||||
:
|
||||
Iterator<true>(iter)
|
||||
{}
|
||||
|
||||
//- Construct from hash table, element and hash index.
|
||||
// Used by the hash-table find() method.
|
||||
inline const_iterator
|
||||
(
|
||||
table_type* hashTbl,
|
||||
entry_type* elmt,
|
||||
const label hashIndex
|
||||
);
|
||||
//- Copy construct from dissimilar access type
|
||||
inline explicit const_iterator(const Iterator<false>& iter)
|
||||
:
|
||||
Iterator<true>
|
||||
(
|
||||
static_cast<const Iterator<true>&>(iter)
|
||||
)
|
||||
{}
|
||||
|
||||
//- Implicit conversion from dissimilar access type
|
||||
inline const_iterator(const iterator& iter)
|
||||
:
|
||||
const_iterator(reinterpret_cast<const const_iterator&>(iter))
|
||||
{}
|
||||
|
||||
//- Copy construct from iterator
|
||||
inline const_iterator(const iterator& iter);
|
||||
|
||||
// Member functions/operators
|
||||
|
||||
//- Return const access to referenced object
|
||||
inline reference object() const;
|
||||
//- Const access to referenced object
|
||||
using Iterator<true>::object;
|
||||
|
||||
//- Return const access to referenced object
|
||||
inline reference operator*() const;
|
||||
inline reference operator()() const;
|
||||
//- Const access to referenced object
|
||||
inline reference operator*() const { return this->object(); }
|
||||
inline reference operator()() const { return this->object(); }
|
||||
|
||||
inline const_iterator& operator++();
|
||||
inline const_iterator operator++(int);
|
||||
|
||||
// Assignment
|
||||
|
||||
const_iterator& operator=(const const_iterator&) = default;
|
||||
|
||||
// Allow assign from iterator to const_iterator
|
||||
const_iterator& operator=(const iterator& iter)
|
||||
{
|
||||
return this->operator=
|
||||
(
|
||||
reinterpret_cast<const const_iterator&>(iter)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- Iterating over keys only
|
||||
|
||||
//- An iterator wrapper for returning a reference to the key
|
||||
template<class Iter>
|
||||
class key_iterator_base
|
||||
:
|
||||
public Iter
|
||||
{
|
||||
public:
|
||||
using value_type = this_type::key_type;
|
||||
using pointer = const Key*;
|
||||
using reference = const Key&;
|
||||
|
||||
//- Implicit conversion
|
||||
inline key_iterator_base(const Iter& iter)
|
||||
:
|
||||
Iter(iter)
|
||||
{}
|
||||
|
||||
//- Return the key
|
||||
inline reference operator*() const { return this->key(); }
|
||||
inline reference operator()() const { return this->key(); }
|
||||
|
||||
inline key_iterator_base& operator++()
|
||||
{
|
||||
this->increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline key_iterator_base operator++(int)
|
||||
{
|
||||
key_iterator_base iter(*this);
|
||||
this->increment();
|
||||
return iter;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//- Forward iterator returning the key
|
||||
using key_iterator = key_iterator_base<iterator>;
|
||||
|
||||
@ -793,6 +981,7 @@ inline void Swap
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "HashTableI.H"
|
||||
#include "HashTableIterI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
@ -36,6 +36,8 @@ 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 * * * * * * * * * * * * * * //
|
||||
|
||||
@ -50,7 +52,7 @@ Foam::label Foam::HashTableCore::canonicalSize(const label requested_size)
|
||||
return maxTableSize;
|
||||
}
|
||||
|
||||
// Enforce power of two - makes for a very fast modulus.
|
||||
// Enforce power of two for fast modulus in hash index calculations.
|
||||
// Use unsigned for these calculations.
|
||||
//
|
||||
// - The lower limit (8) is somewhat arbitrary, but if the hash table
|
||||
@ -65,7 +67,8 @@ Foam::label Foam::HashTableCore::canonicalSize(const label requested_size)
|
||||
{
|
||||
return powerOfTwo;
|
||||
}
|
||||
else if (size & (size-1)) // <- Modulus of i^2
|
||||
|
||||
if (size & (size-1)) // <- Modulus of i^2
|
||||
{
|
||||
// Determine power-of-two. Brute-force is fast enough.
|
||||
while (powerOfTwo < size)
|
||||
@ -75,10 +78,8 @@ Foam::label Foam::HashTableCore::canonicalSize(const label requested_size)
|
||||
|
||||
return powerOfTwo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ SourceFiles
|
||||
#include "uLabel.H"
|
||||
#include "className.H"
|
||||
#include "nullObject.H"
|
||||
#include "zero.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -77,20 +78,16 @@ struct HashTableCore
|
||||
template<class IteratorType, class TableType>
|
||||
inline static IteratorType iterator_begin(TableType& table);
|
||||
|
||||
//- Factory method to create a const iterator begin
|
||||
template<class IteratorType, class TableType>
|
||||
inline static IteratorType iterator_begin(const TableType& table);
|
||||
|
||||
//- Factory method to create a const iterator begin
|
||||
template<class IteratorType, class TableType>
|
||||
inline static IteratorType iterator_cbegin(const TableType& table);
|
||||
|
||||
//- Factory method to create a non-const iterator end
|
||||
//- Factory method to return an iterator end
|
||||
// Simply reinterprets a NullObject as a hash-table iterator.
|
||||
template<class IteratorType>
|
||||
inline static const IteratorType& iterator_end();
|
||||
|
||||
//- Factory method to create a const iterator cend
|
||||
//- Factory method to return an iterator cend
|
||||
// Simply reinterprets a NullObject as a hash-table iterator.
|
||||
template<class IteratorType>
|
||||
inline static const IteratorType& iterator_cend();
|
||||
@ -116,6 +113,13 @@ 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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -35,16 +35,6 @@ inline IteratorType Foam::HashTableCore::iterator_begin
|
||||
}
|
||||
|
||||
|
||||
template<class IteratorType, class TableType>
|
||||
inline IteratorType Foam::HashTableCore::iterator_begin
|
||||
(
|
||||
const TableType& table
|
||||
)
|
||||
{
|
||||
return IteratorType(table.begin());
|
||||
}
|
||||
|
||||
|
||||
template<class IteratorType, class TableType>
|
||||
inline IteratorType Foam::HashTableCore::iterator_cbegin
|
||||
(
|
||||
|
||||
@ -25,30 +25,14 @@ License
|
||||
|
||||
#include "error.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::hashedEntry::hashedEntry
|
||||
(
|
||||
const Key& key,
|
||||
const T& obj,
|
||||
hashedEntry* next
|
||||
)
|
||||
:
|
||||
key_(key),
|
||||
obj_(obj),
|
||||
next_(next)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label
|
||||
Foam::HashTable<T, Key, Hash>::hashKeyIndex(const Key& key) const
|
||||
{
|
||||
// size is power of two - this is the modulus
|
||||
return Hash()(key) & (tableSize_ - 1);
|
||||
// capacity is always a power of two - this is the modulus
|
||||
return Hash()(key) & (capacity_ - 1);
|
||||
}
|
||||
|
||||
|
||||
@ -57,21 +41,76 @@ Foam::HashTable<T, Key, Hash>::hashKeyIndex(const Key& key) const
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label Foam::HashTable<T, Key, Hash>::capacity() const
|
||||
{
|
||||
return tableSize_;
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label Foam::HashTable<T, Key, Hash>::size() const
|
||||
{
|
||||
return nElmts_;
|
||||
return size_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::empty() const
|
||||
{
|
||||
return !nElmts_;
|
||||
return !size_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::found(const Key& key) const
|
||||
{
|
||||
if (size_)
|
||||
{
|
||||
return Iterator<true>(this, key).found();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
||||
Foam::HashTable<T, Key, Hash>::find
|
||||
(
|
||||
const Key& key
|
||||
)
|
||||
{
|
||||
if (size_)
|
||||
{
|
||||
return iterator(Iterator<false>(this, key));
|
||||
}
|
||||
|
||||
return iterator();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::find
|
||||
(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
return this->cfind(key);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::cfind
|
||||
(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
if (size_)
|
||||
{
|
||||
return const_iterator(Iterator<true>(this, key));
|
||||
}
|
||||
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +121,7 @@ inline bool Foam::HashTable<T, Key, Hash>::insert
|
||||
const T& obj
|
||||
)
|
||||
{
|
||||
return this->set(key, obj, true);
|
||||
return this->set(key, obj, false); // No overwrite
|
||||
}
|
||||
|
||||
|
||||
@ -93,7 +132,7 @@ inline bool Foam::HashTable<T, Key, Hash>::set
|
||||
const T& obj
|
||||
)
|
||||
{
|
||||
return this->set(key, obj, false);
|
||||
return this->set(key, obj, true); // Overwrite
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +151,7 @@ inline const T& Foam::HashTable<T, Key, Hash>::lookup
|
||||
const T& deflt
|
||||
) const
|
||||
{
|
||||
const_iterator iter = this->find(key);
|
||||
const const_iterator iter(this->cfind(key));
|
||||
return iter.found() ? iter.object() : deflt;
|
||||
}
|
||||
|
||||
@ -122,7 +161,7 @@ inline const T& Foam::HashTable<T, Key, Hash>::lookup
|
||||
template<class T, class Key, class Hash>
|
||||
inline T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key)
|
||||
{
|
||||
iterator iter = this->find(key);
|
||||
const iterator iter(this->find(key));
|
||||
|
||||
if (!iter.found())
|
||||
{
|
||||
@ -139,7 +178,7 @@ inline T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key)
|
||||
template<class T, class Key, class Hash>
|
||||
inline const T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key) const
|
||||
{
|
||||
const_iterator iter = this->find(key);
|
||||
const const_iterator iter(this->cfind(key));
|
||||
|
||||
if (!iter.found())
|
||||
{
|
||||
@ -156,14 +195,14 @@ inline const T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key) const
|
||||
template<class T, class Key, class Hash>
|
||||
inline T& Foam::HashTable<T, Key, Hash>::operator()(const Key& key)
|
||||
{
|
||||
iterator iter = this->find(key);
|
||||
const iterator iter(this->find(key));
|
||||
|
||||
if (iter.found())
|
||||
{
|
||||
return iter.object();
|
||||
}
|
||||
|
||||
this->insert(key, T());
|
||||
this->insert(key, mapped_type());
|
||||
return find(key).object();
|
||||
}
|
||||
|
||||
@ -175,7 +214,7 @@ inline T& Foam::HashTable<T, Key, Hash>::operator()
|
||||
const T& deflt
|
||||
)
|
||||
{
|
||||
iterator iter = this->find(key);
|
||||
const iterator iter(this->find(key));
|
||||
|
||||
if (iter.found())
|
||||
{
|
||||
@ -198,412 +237,6 @@ inline const T& Foam::HashTable<T, Key, Hash>::operator()
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * iterator base * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::iterator_base::iterator_base()
|
||||
:
|
||||
entryPtr_(nullptr),
|
||||
hashTable_(nullptr),
|
||||
hashIndex_(0)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::iterator_base::iterator_base
|
||||
(
|
||||
const table_type* hashTbl,
|
||||
const entry_type* elmt,
|
||||
const label hashIndex
|
||||
)
|
||||
:
|
||||
entryPtr_(const_cast<entry_type*>(elmt)),
|
||||
hashTable_(const_cast<table_type*>(hashTbl)),
|
||||
hashIndex_(hashIndex)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::iterator_base::iterator_base
|
||||
(
|
||||
const table_type* hashTbl
|
||||
)
|
||||
:
|
||||
entryPtr_(nullptr),
|
||||
hashTable_(const_cast<table_type*>(hashTbl)),
|
||||
hashIndex_(0)
|
||||
{
|
||||
if (hashTable_ && hashTable_->nElmts_)
|
||||
{
|
||||
// find first non-nullptr table entry
|
||||
while
|
||||
(
|
||||
!(entryPtr_ = hashTable_->table_[hashIndex_])
|
||||
&& ++hashIndex_ < hashTable_->tableSize_
|
||||
)
|
||||
{}
|
||||
|
||||
if (hashIndex_ >= hashTable_->tableSize_)
|
||||
{
|
||||
// make into an end iterator
|
||||
entryPtr_ = nullptr;
|
||||
hashIndex_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline void
|
||||
Foam::HashTable<T, Key, Hash>::iterator_base::increment()
|
||||
{
|
||||
// A negative index is a special value from erase
|
||||
if (hashIndex_ < 0)
|
||||
{
|
||||
// the markPos='-curPos-1', but we wish to continue at 'curPos-1'
|
||||
// thus use '-(markPos+1) -1'
|
||||
hashIndex_ = -(hashIndex_+1) - 1;
|
||||
}
|
||||
else if (entryPtr_)
|
||||
{
|
||||
if (entryPtr_->next_)
|
||||
{
|
||||
// Move to next element on the SLList
|
||||
entryPtr_ = entryPtr_->next_;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// // if we reach here (entryPtr_ is nullptr) it is already at the end()
|
||||
// // we should probably stop
|
||||
// }
|
||||
|
||||
|
||||
// Step to the next table entry
|
||||
while
|
||||
(
|
||||
++hashIndex_ < hashTable_->tableSize_
|
||||
&& !(entryPtr_ = hashTable_->table_[hashIndex_])
|
||||
)
|
||||
{}
|
||||
|
||||
if (hashIndex_ >= hashTable_->tableSize_)
|
||||
{
|
||||
// make into an end iterator
|
||||
entryPtr_ = nullptr;
|
||||
hashIndex_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline bool
|
||||
Foam::HashTable<T, Key, Hash>::iterator_base::found() const
|
||||
{
|
||||
return entryPtr_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const Key& Foam::HashTable<T, Key, Hash>::iterator_base::key() const
|
||||
{
|
||||
return entryPtr_->key_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline T& Foam::HashTable<T, Key, Hash>::iterator_base::element() const
|
||||
{
|
||||
return entryPtr_->obj_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::iterator_base::operator==
|
||||
(
|
||||
const iterator_base& iter
|
||||
) const
|
||||
{
|
||||
return entryPtr_ == iter.entryPtr_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::iterator_base::operator!=
|
||||
(
|
||||
const iterator_base& iter
|
||||
) const
|
||||
{
|
||||
return entryPtr_ != iter.entryPtr_;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * key iterator base * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class WrappedIterator>
|
||||
inline Foam::HashTable<T, Key, Hash>::key_iterator_base<WrappedIterator>
|
||||
::key_iterator_base
|
||||
(
|
||||
const WrappedIterator& iter
|
||||
)
|
||||
:
|
||||
WrappedIterator(iter)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class WrappedIterator>
|
||||
inline const Key&
|
||||
Foam::HashTable<T, Key, Hash>::key_iterator_base<WrappedIterator>
|
||||
::operator*() const
|
||||
{
|
||||
return this->key();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class WrappedIterator>
|
||||
inline const Key&
|
||||
Foam::HashTable<T, Key, Hash>::key_iterator_base<WrappedIterator>
|
||||
::operator()() const
|
||||
{
|
||||
return this->key();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class WrappedIterator>
|
||||
inline Foam::HashTable<T, Key, Hash>::key_iterator_base<WrappedIterator>&
|
||||
Foam::HashTable<T, Key, Hash>::key_iterator_base<WrappedIterator>
|
||||
::operator++()
|
||||
{
|
||||
this->increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class WrappedIterator>
|
||||
inline Foam::HashTable<T, Key, Hash>::key_iterator_base<WrappedIterator>
|
||||
Foam::HashTable<T, Key, Hash>::key_iterator_base<WrappedIterator>
|
||||
::operator++(int)
|
||||
{
|
||||
key_iterator_base old = *this;
|
||||
this->increment();
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::iterator::iterator()
|
||||
:
|
||||
iterator_base()
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::iterator::iterator
|
||||
(
|
||||
table_type* hashTbl
|
||||
)
|
||||
:
|
||||
iterator_base(hashTbl)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::iterator::iterator
|
||||
(
|
||||
table_type* hashTbl,
|
||||
entry_type* elmt,
|
||||
const label hashIndex
|
||||
)
|
||||
:
|
||||
iterator_base(hashTbl, elmt, hashIndex)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline T&
|
||||
Foam::HashTable<T, Key, Hash>::iterator::object() const
|
||||
{
|
||||
return this->element();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline T&
|
||||
Foam::HashTable<T, Key, Hash>::iterator::operator*() const
|
||||
{
|
||||
return this->object();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline T&
|
||||
Foam::HashTable<T, Key, Hash>::iterator::operator()() const
|
||||
{
|
||||
return this->object();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::iterator&
|
||||
Foam::HashTable<T, Key, Hash>::iterator::operator++()
|
||||
{
|
||||
this->increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
||||
Foam::HashTable<T, Key, Hash>::iterator::operator++(int)
|
||||
{
|
||||
iterator old = *this;
|
||||
this->increment();
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator()
|
||||
:
|
||||
iterator_base()
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
|
||||
(
|
||||
const HashTable<T, Key, Hash>::iterator& iter
|
||||
)
|
||||
:
|
||||
iterator_base(iter)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
|
||||
(
|
||||
table_type* hashTbl
|
||||
)
|
||||
:
|
||||
iterator_base(hashTbl)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
|
||||
(
|
||||
table_type* hashTbl,
|
||||
entry_type* elmt,
|
||||
const label hashIndex
|
||||
)
|
||||
:
|
||||
iterator_base(hashTbl, elmt, hashIndex)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const T&
|
||||
Foam::HashTable<T, Key, Hash>::const_iterator::object() const
|
||||
{
|
||||
return this->element();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const T&
|
||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator*() const
|
||||
{
|
||||
return this->object();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const T&
|
||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator()() const
|
||||
{
|
||||
return this->object();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator++()
|
||||
{
|
||||
this->increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator++(int)
|
||||
{
|
||||
const_iterator old = *this;
|
||||
this->increment();
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
||||
Foam::HashTable<T, Key, Hash>::begin()
|
||||
{
|
||||
return iterator(this);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::begin() const
|
||||
{
|
||||
return const_iterator(this);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::cbegin() const
|
||||
{
|
||||
return const_iterator(this);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::HashTable<T, Key, Hash>::iterator&
|
||||
Foam::HashTable<T, Key, Hash>::end()
|
||||
{
|
||||
return iterator_end<iterator>();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
||||
Foam::HashTable<T, Key, Hash>::end() const
|
||||
{
|
||||
return iterator_end<const_iterator>();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
||||
Foam::HashTable<T, Key, Hash>::cend() const
|
||||
{
|
||||
return iterator_cend<const_iterator>();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
|
||||
@ -33,17 +33,17 @@ template<class T, class Key, class Hash>
|
||||
Foam::HashTable<T, Key, Hash>::HashTable(Istream& is, const label size)
|
||||
:
|
||||
HashTableCore(),
|
||||
nElmts_(0),
|
||||
tableSize_(HashTableCore::canonicalSize(size)),
|
||||
size_(0),
|
||||
capacity_(HashTableCore::canonicalSize(size)),
|
||||
table_(nullptr)
|
||||
{
|
||||
if (tableSize_)
|
||||
if (capacity_)
|
||||
{
|
||||
table_ = new hashedEntry*[tableSize_];
|
||||
table_ = new node_type*[capacity_];
|
||||
|
||||
for (label hashIdx = 0; hashIdx < tableSize_; ++hashIdx)
|
||||
for (label i=0; i < capacity_; ++i)
|
||||
{
|
||||
table_[hashIdx] = nullptr;
|
||||
table_[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,10 +60,10 @@ Foam::Ostream& Foam::HashTable<T, Key, Hash>::printInfo(Ostream& os) const
|
||||
label maxChain = 0;
|
||||
unsigned avgChain = 0;
|
||||
|
||||
for (label hashIdx = 0; hashIdx < tableSize_; ++hashIdx)
|
||||
for (label i=0; i < capacity_; ++i)
|
||||
{
|
||||
label count = 0;
|
||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||
for (node_type* ep = table_[i]; ep; ep = ep->next_)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
@ -81,7 +81,7 @@ Foam::Ostream& Foam::HashTable<T, Key, Hash>::printInfo(Ostream& os) const
|
||||
}
|
||||
|
||||
os << "HashTable<T,Key,Hash>"
|
||||
<< " elements:" << size() << " slots:" << used << "/" << tableSize_
|
||||
<< " elements:" << size() << " slots:" << used << "/" << capacity_
|
||||
<< " chaining(avg/max):" << (used ? (float(avgChain)/used) : 0)
|
||||
<< "/" << maxChain << endl;
|
||||
|
||||
@ -145,7 +145,7 @@ Foam::Istream& Foam::operator>>
|
||||
{
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
// Anull list
|
||||
// Anull existing table
|
||||
L.clear();
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
@ -154,7 +154,7 @@ Foam::Istream& Foam::operator>>
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"operator>>(Istream&, HashTable<T, Key, Hash>&) : "
|
||||
"operator>>(Istream&, HashTable&) : "
|
||||
"reading first token"
|
||||
);
|
||||
|
||||
@ -163,11 +163,11 @@ Foam::Istream& Foam::operator>>
|
||||
const label s = firstToken.labelToken();
|
||||
|
||||
// Read beginning of contents
|
||||
const char delimiter = is.readBeginList("HashTable<T, Key, Hash>");
|
||||
const char delimiter = is.readBeginList("HashTable");
|
||||
|
||||
if (s)
|
||||
{
|
||||
if (2*s > L.tableSize_)
|
||||
if (2*s > L.capacity_)
|
||||
{
|
||||
L.resize(2*s);
|
||||
}
|
||||
@ -182,7 +182,7 @@ Foam::Istream& Foam::operator>>
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"operator>>(Istream&, HashTable<T, Key, Hash>&) : "
|
||||
"operator>>(Istream&, HashTable&) : "
|
||||
"reading entry"
|
||||
);
|
||||
}
|
||||
@ -224,15 +224,11 @@ Foam::Istream& Foam::operator>>
|
||||
|
||||
Key key;
|
||||
is >> key;
|
||||
|
||||
T element;
|
||||
is >> element;
|
||||
|
||||
L.insert(key, element);
|
||||
L.insert(key, pTraits<T>(is));
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"operator>>(Istream&, HashTable<T, Key, Hash>&) : "
|
||||
"operator>>(Istream&, HashTable&) : "
|
||||
"reading entry"
|
||||
);
|
||||
|
||||
@ -262,19 +258,26 @@ Foam::Ostream& Foam::operator<<
|
||||
const HashTable<T, Key, Hash>& tbl
|
||||
)
|
||||
{
|
||||
using const_iterator = typename HashTable<T, Key, Hash>::const_iterator;
|
||||
const label sz = tbl.size();
|
||||
|
||||
// Write size and start delimiter
|
||||
os << nl << tbl.size() << nl << token::BEGIN_LIST << nl;
|
||||
|
||||
// Write contents
|
||||
for (const_iterator iter = tbl.cbegin(); iter != tbl.cend(); ++iter)
|
||||
if (sz)
|
||||
{
|
||||
os << iter.key() << token::SPACE << iter.object() << nl;
|
||||
}
|
||||
// Size and start list delimiter
|
||||
os << nl << sz << nl << token::BEGIN_LIST << nl;
|
||||
|
||||
// Write end delimiter
|
||||
os << token::END_LIST;
|
||||
// Contents
|
||||
for (auto iter = tbl.cbegin(); iter != tbl.cend(); ++iter)
|
||||
{
|
||||
os << iter.key() << token::SPACE << iter.object() << nl;
|
||||
}
|
||||
|
||||
os << token::END_LIST; // End list delimiter
|
||||
}
|
||||
else
|
||||
{
|
||||
// Empty hash table
|
||||
os << sz << token::BEGIN_LIST << token::END_LIST;
|
||||
}
|
||||
|
||||
os.check(FUNCTION_NAME);
|
||||
return os;
|
||||
|
||||
123
src/OpenFOAM/containers/HashTables/HashTable/HashTableIter.C
Normal file
123
src/OpenFOAM/containers/HashTables/HashTable/HashTableIter.C
Normal file
@ -0,0 +1,123 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
Foam::HashTable<T, Key, Hash>::Iterator<Const>::Iterator
|
||||
(
|
||||
table_type* tbl,
|
||||
const Key& key
|
||||
)
|
||||
:
|
||||
entry_(nullptr),
|
||||
container_(tbl),
|
||||
index_(0)
|
||||
{
|
||||
if (tbl->size())
|
||||
{
|
||||
const label index = container_->hashKeyIndex(key);
|
||||
|
||||
for (node_type* ep = container_->table_[index]; ep; ep = ep->next_)
|
||||
{
|
||||
if (key == ep->key())
|
||||
{
|
||||
entry_ = ep;
|
||||
index_ = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
//
|
||||
// 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
|
||||
)
|
||||
{
|
||||
// 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 false;
|
||||
}
|
||||
|
||||
// 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 to there
|
||||
prev->next_ = entry->next_;
|
||||
delete entry;
|
||||
entry = prev;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Was first element on linked list
|
||||
table_[index] = entry->next_;
|
||||
delete entry;
|
||||
|
||||
// Assign any non-nullptr value so it doesn't look like end()
|
||||
entry = reinterpret_cast<node_type*>(this);
|
||||
|
||||
// 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))
|
||||
|
||||
index = (-index - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
263
src/OpenFOAM/containers/HashTables/HashTable/HashTableIterI.H
Normal file
263
src/OpenFOAM/containers/HashTables/HashTable/HashTableIterI.H
Normal file
@ -0,0 +1,263 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * iterator base * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline Foam::HashTable<T, Key, Hash>::Iterator<Const>::Iterator()
|
||||
:
|
||||
entry_(nullptr),
|
||||
container_(nullptr),
|
||||
index_(0)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline Foam::HashTable<T, Key, Hash>::Iterator<Const>::Iterator
|
||||
(
|
||||
bool, // Future use and to avoid implicit construct
|
||||
table_type* tbl
|
||||
)
|
||||
:
|
||||
entry_(nullptr),
|
||||
container_(tbl),
|
||||
index_(0)
|
||||
{
|
||||
if (container_ && container_->size_)
|
||||
{
|
||||
// Locate the first non-nullptr table entry
|
||||
while
|
||||
(
|
||||
!(entry_ = container_->table_[index_])
|
||||
&& ++index_ < container_->capacity_
|
||||
)
|
||||
{}
|
||||
|
||||
if (index_ >= container_->capacity_)
|
||||
{
|
||||
// Nothing found - make it an end iterator
|
||||
entry_ = nullptr;
|
||||
index_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Any changes here may need changes in iterator_erase() method too
|
||||
//
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline void
|
||||
Foam::HashTable<T, Key, Hash>::Iterator<Const>::increment()
|
||||
{
|
||||
if (index_ < 0)
|
||||
{
|
||||
// Negative index is a special value from erase
|
||||
//
|
||||
// Saved as (-index-1), retrieved as (-(index-1)) but to with an
|
||||
// extra (-1) to compensate for the ++ in the following while loop
|
||||
index_ = -(index_+1) - 1;
|
||||
}
|
||||
else if (index_ < container_->capacity_ && entry_ && entry_->next_)
|
||||
{
|
||||
// Move to next element on the linked-list
|
||||
entry_ = entry_->next_;
|
||||
return;
|
||||
}
|
||||
|
||||
// Move to the next non-nullptr table entry
|
||||
while
|
||||
(
|
||||
++index_ < container_->capacity_
|
||||
&& !(entry_ = container_->table_[index_])
|
||||
)
|
||||
{}
|
||||
|
||||
if (index_ >= container_->capacity_)
|
||||
{
|
||||
// Nothing found - make it an end iterator
|
||||
entry_ = nullptr;
|
||||
index_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline bool
|
||||
Foam::HashTable<T, Key, Hash>::Iterator<Const>::found() const
|
||||
{
|
||||
return entry_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline const Key& Foam::HashTable<T, Key, Hash>::Iterator<Const>::key() const
|
||||
{
|
||||
return entry_->key();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::Iterator<Const>::operator==
|
||||
(
|
||||
const Iterator<true>& iter
|
||||
) const
|
||||
{
|
||||
return entry_ == iter.entry_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::Iterator<Const>::operator!=
|
||||
(
|
||||
const Iterator<true>& iter
|
||||
) const
|
||||
{
|
||||
return entry_ != iter.entry_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::Iterator<Const>::operator==
|
||||
(
|
||||
const Iterator<false>& iter
|
||||
) const
|
||||
{
|
||||
return entry_ == iter.entry_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<bool Const>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::Iterator<Const>::operator!=
|
||||
(
|
||||
const Iterator<false>& iter
|
||||
) const
|
||||
{
|
||||
return entry_ != iter.entry_;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::iterator&
|
||||
Foam::HashTable<T, Key, Hash>::iterator::operator++()
|
||||
{
|
||||
this->increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
||||
Foam::HashTable<T, Key, Hash>::iterator::operator++(int)
|
||||
{
|
||||
iterator iter(*this);
|
||||
this->increment();
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator++()
|
||||
{
|
||||
this->increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator++(int)
|
||||
{
|
||||
const_iterator iter(*this);
|
||||
this->increment();
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
||||
Foam::HashTable<T, Key, Hash>::begin()
|
||||
{
|
||||
return iterator(Iterator<false>(true, this));
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::begin() const
|
||||
{
|
||||
return const_iterator(Iterator<true>(true, this));
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||
Foam::HashTable<T, Key, Hash>::cbegin() const
|
||||
{
|
||||
return const_iterator(Iterator<true>(true, this));
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::HashTable<T, Key, Hash>::iterator&
|
||||
Foam::HashTable<T, Key, Hash>::end()
|
||||
{
|
||||
return iterator_end<iterator>();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
||||
Foam::HashTable<T, Key, Hash>::end() const
|
||||
{
|
||||
return iterator_cend<const_iterator>();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
||||
Foam::HashTable<T, Key, Hash>::cend() const
|
||||
{
|
||||
return iterator_cend<const_iterator>();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -27,6 +27,11 @@ Class
|
||||
Description
|
||||
A HashTable to objects of type \<T\> with a label key.
|
||||
|
||||
Note
|
||||
The Map contents are unordered.
|
||||
When the key order is important, use the sortedToc() method to obtain
|
||||
a list of sorted keys and use that for further access.
|
||||
|
||||
See also
|
||||
PtrMap
|
||||
|
||||
@ -65,13 +70,19 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given initial size
|
||||
Map(const label size = 128)
|
||||
//- Construct null with default table size
|
||||
Map()
|
||||
:
|
||||
parent_type()
|
||||
{}
|
||||
|
||||
//- Construct with given table size
|
||||
explicit Map(const label size)
|
||||
:
|
||||
parent_type(size)
|
||||
{}
|
||||
|
||||
//- Construct from Istream
|
||||
//- Construct from Istream with default table size
|
||||
Map(Istream& is)
|
||||
:
|
||||
parent_type(is)
|
||||
@ -96,7 +107,7 @@ public:
|
||||
{}
|
||||
|
||||
//- Construct by transferring the parameter contents
|
||||
Map(const Xfer<HashTable<T, label, Hash<label>>>& map)
|
||||
Map(const Xfer<parent_type>& map)
|
||||
:
|
||||
parent_type(map)
|
||||
{}
|
||||
|
||||
@ -62,8 +62,14 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null with default table size
|
||||
PtrMap()
|
||||
:
|
||||
parent_type()
|
||||
{}
|
||||
|
||||
//- Construct given initial map size
|
||||
PtrMap(const label size = 128)
|
||||
explicit PtrMap(const label size)
|
||||
:
|
||||
parent_type(size)
|
||||
{}
|
||||
|
||||
@ -1,530 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef StaticHashTable_C
|
||||
#define StaticHashTable_C
|
||||
|
||||
#include "StaticHashTable.H"
|
||||
#include "List.H"
|
||||
#include "IOstreams.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable(const label size)
|
||||
:
|
||||
StaticHashTableCore(),
|
||||
keys_(StaticHashTableCore::canonicalSize(size)),
|
||||
objects_(keys_.size()),
|
||||
nElmts_(0),
|
||||
endIter_(*this, keys_.size(), 0),
|
||||
endConstIter_(*this, keys_.size(), 0)
|
||||
{
|
||||
if (size < 1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Illegal size " << size << " for StaticHashTable."
|
||||
<< " Minimum size is 1" << abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
|
||||
(
|
||||
const StaticHashTable<T, Key, Hash>& ht
|
||||
)
|
||||
:
|
||||
StaticHashTableCore(),
|
||||
keys_(ht.keys_),
|
||||
objects_(ht.objects_),
|
||||
nElmts_(ht.nElmts_),
|
||||
endIter_(*this, keys_.size(), 0),
|
||||
endConstIter_(*this, keys_.size(), 0)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
|
||||
(
|
||||
const Xfer<StaticHashTable<T, Key, Hash>>& ht
|
||||
)
|
||||
:
|
||||
StaticHashTableCore(),
|
||||
keys_(0),
|
||||
objects_(0),
|
||||
nElmts_(0),
|
||||
endIter_(*this, 0, 0),
|
||||
endConstIter_(*this, 0, 0)
|
||||
{
|
||||
transfer(ht());
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::StaticHashTable<T, Key, Hash>::~StaticHashTable()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
const List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
forAll(localKeys, elemIdx)
|
||||
{
|
||||
if (key == localKeys[elemIdx])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "Entry " << key << " not found in hash table\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
typename Foam::StaticHashTable<T, Key, Hash>::iterator
|
||||
Foam::StaticHashTable<T, Key, Hash>::find
|
||||
(
|
||||
const Key& key
|
||||
)
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
const List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
forAll(localKeys, elemIdx)
|
||||
{
|
||||
if (key == localKeys[elemIdx])
|
||||
{
|
||||
return iterator(*this, hashIdx, elemIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "Entry " << key << " not found in hash table\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
|
||||
Foam::StaticHashTable<T, Key, Hash>::find
|
||||
(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
return this->cfind(key);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
|
||||
Foam::StaticHashTable<T, Key, Hash>::cfind
|
||||
(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
if (nElmts_)
|
||||
{
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
const List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
forAll(localKeys, elemIdx)
|
||||
{
|
||||
if (key == localKeys[elemIdx])
|
||||
{
|
||||
return const_iterator(*this, hashIdx, elemIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "Entry " << key << " not found in hash table\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return cend();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::List<Key> Foam::StaticHashTable<T, Key, Hash>::toc() const
|
||||
{
|
||||
List<Key> keys(nElmts_);
|
||||
label keyI = 0;
|
||||
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
keys[keyI++] = iter.key();
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::StaticHashTable<T, Key, Hash>::set
|
||||
(
|
||||
const Key& key,
|
||||
const T& obj,
|
||||
const bool protect
|
||||
)
|
||||
{
|
||||
const label hashIdx = hashKeyIndex(key);
|
||||
List<Key>& localKeys = keys_[hashIdx];
|
||||
|
||||
label existing = localKeys.size();
|
||||
forAll(localKeys, elemIdx)
|
||||
{
|
||||
if (key == localKeys[elemIdx])
|
||||
{
|
||||
existing = elemIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (existing == localKeys.size())
|
||||
{
|
||||
// Not found, append
|
||||
List<T>& localObjects = objects_[hashIdx];
|
||||
|
||||
localKeys.setSize(existing+1);
|
||||
localObjects.setSize(existing+1);
|
||||
|
||||
localKeys[existing] = key;
|
||||
localObjects[existing] = obj;
|
||||
|
||||
nElmts_++;
|
||||
}
|
||||
else if (protect)
|
||||
{
|
||||
// Found - but protected from overwriting
|
||||
// this corresponds to the STL 'insert' convention
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Cannot insert " << key << " already in hash table\n";
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found - overwrite existing entry
|
||||
// this corresponds to the Perl convention
|
||||
objects_[hashIdx][existing] = obj;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::StaticHashTable<T, Key, Hash>::erase(const iterator& cit)
|
||||
{
|
||||
if (cit != end())
|
||||
{
|
||||
List<Key>& localKeys = keys_[cit.hashIndex_];
|
||||
List<T>& localObjects = objects_[cit.hashIndex_];
|
||||
|
||||
// Copy down
|
||||
for (label i = cit.elemIndex_+1; i < localKeys.size(); i++)
|
||||
{
|
||||
localKeys[i-1] = localKeys[i];
|
||||
localObjects[i-1] = localObjects[i];
|
||||
}
|
||||
localKeys.setSize(localKeys.size()-1);
|
||||
localObjects.setSize(localObjects.size()-1);
|
||||
|
||||
// Adjust iterator after erase
|
||||
iterator& it = const_cast<iterator&>(cit);
|
||||
|
||||
it.elemIndex_--;
|
||||
if (it.elemIndex_ < 0)
|
||||
{
|
||||
// No previous element in the local list
|
||||
// Mark with as special value (see notes in HashTable)
|
||||
it.hashIndex_ = -it.hashIndex_ - 1;
|
||||
it.elemIndex_ = 0;
|
||||
}
|
||||
|
||||
nElmts_--;
|
||||
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "hashedEntry removed.\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction
|
||||
<< "Cannot remove hashedEntry from hash table\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::StaticHashTable<T, Key, Hash>::erase(const Key& key)
|
||||
{
|
||||
iterator it = find(key);
|
||||
|
||||
if (it != end())
|
||||
{
|
||||
return erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::label Foam::StaticHashTable<T, Key, Hash>::erase
|
||||
(
|
||||
const StaticHashTable<T, Key, Hash>& rhs
|
||||
)
|
||||
{
|
||||
label count = 0;
|
||||
|
||||
// Remove rhs elements from this table
|
||||
// NOTE: could optimize depending on which hash is smaller
|
||||
for (iterator iter = this->begin(); iter != this->end(); ++iter)
|
||||
{
|
||||
if (rhs.found(iter.key()) && erase(iter))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::StaticHashTable<T, Key, Hash>::resize(const label sz)
|
||||
{
|
||||
label newSize = StaticHashTableCore::canonicalSize(sz);
|
||||
|
||||
if (newSize == keys_.size())
|
||||
{
|
||||
#ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
InfoInFunction << "New table size == old table size\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (newSize < 1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Illegal size " << newSize << " for StaticHashTable."
|
||||
<< " Minimum size is 1" << abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
StaticHashTable<T, Key, Hash> newTable(newSize);
|
||||
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
newTable.insert(iter.key(), *iter);
|
||||
}
|
||||
|
||||
transfer(newTable);
|
||||
|
||||
// Adapt end() iterators
|
||||
endIter_.hashIndex_ = keys_.size();
|
||||
endConstIter_.hashIndex_ = keys_.size();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::StaticHashTable<T, Key, Hash>::clear()
|
||||
{
|
||||
forAll(keys_, hashIdx)
|
||||
{
|
||||
keys_[hashIdx].clear();
|
||||
objects_[hashIdx].clear();
|
||||
}
|
||||
|
||||
nElmts_ = 0;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::StaticHashTable<T, Key, Hash>::clearStorage()
|
||||
{
|
||||
clear();
|
||||
resize(1);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::StaticHashTable<T, Key, Hash>::transfer
|
||||
(
|
||||
StaticHashTable<T, Key, Hash>& ht
|
||||
)
|
||||
{
|
||||
// Remove existing elements
|
||||
clear();
|
||||
|
||||
// Copy data from ht
|
||||
keys_.transfer(ht.keys_);
|
||||
objects_.transfer(ht.objects_);
|
||||
|
||||
nElmts_ = ht.nElmts_;
|
||||
ht.nElmts_ = 0;
|
||||
|
||||
// Adapt end() iterators
|
||||
endIter_.hashIndex_ = keys_.size();
|
||||
endConstIter_.hashIndex_ = keys_.size();
|
||||
|
||||
ht.endIter_.hashIndex_ = 0;
|
||||
ht.endConstIter_.hashIndex_ = 0;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::StaticHashTable<T, Key, Hash>::operator=
|
||||
(
|
||||
const StaticHashTable<T, Key, Hash>& rhs
|
||||
)
|
||||
{
|
||||
// Check for assignment to self
|
||||
if (this == &rhs)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "attempted assignment to self"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
// keys could be empty from a previous transfer()
|
||||
if (keys_.empty())
|
||||
{
|
||||
keys_.setSize(rhs.keys_.size());
|
||||
objects_.setSize(keys_.size());
|
||||
|
||||
// Adapt end() iterators
|
||||
endIter_.hashIndex_ = keys_.size();
|
||||
endConstIter_.hashIndex_ = keys_.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
clear();
|
||||
// keys_.size() does not change so neither does end() iterator.
|
||||
}
|
||||
|
||||
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
insert(iter.key(), *iter);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::StaticHashTable<T, Key, Hash>::operator==
|
||||
(
|
||||
const StaticHashTable<T, Key, Hash>& rhs
|
||||
) const
|
||||
{
|
||||
// Sizes (number of keys) must match
|
||||
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
const_iterator fnd = find(iter.key());
|
||||
|
||||
if (fnd == cend() || fnd() != iter())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::StaticHashTable<T, Key, Hash>::operator!=
|
||||
(
|
||||
const StaticHashTable<T, Key, Hash>& rhs
|
||||
) const
|
||||
{
|
||||
return !(operator==(rhs));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
#include "StaticHashTableIO.C"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,415 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::StaticHashTable
|
||||
|
||||
Description
|
||||
STL conforming hash table.
|
||||
|
||||
Note
|
||||
Uses straight lists as underlying type.
|
||||
Is slower to insert than the standard HashTable, but should be more
|
||||
memory efficient and faster to access.
|
||||
|
||||
SourceFiles
|
||||
StaticHashTableI.H
|
||||
StaticHashTable.C
|
||||
StaticHashTableIO.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef StaticHashTable_H
|
||||
#define StaticHashTable_H
|
||||
|
||||
#include "label.H"
|
||||
#include "uLabel.H"
|
||||
#include "word.H"
|
||||
#include "Xfer.H"
|
||||
#include "className.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of friend functions and operators
|
||||
|
||||
template<class T> class List;
|
||||
template<class T, class Key, class Hash> class StaticHashTable;
|
||||
|
||||
template<class T, class Key, class Hash> Istream& operator>>
|
||||
(
|
||||
Istream&,
|
||||
StaticHashTable<T, Key, Hash>&
|
||||
);
|
||||
|
||||
template<class T, class Key, class Hash> Ostream& operator<<
|
||||
(
|
||||
Ostream&,
|
||||
const StaticHashTable<T, Key, Hash>&
|
||||
);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class StaticHashTableCore Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- Template-invariant bits for StaticHashTable
|
||||
struct StaticHashTableCore
|
||||
{
|
||||
//- Return a canonical (power-of-two) of the requested size.
|
||||
static label canonicalSize(const label requested_size);
|
||||
|
||||
//- Construct null
|
||||
StaticHashTableCore()
|
||||
{}
|
||||
|
||||
//- Define template name and debug
|
||||
ClassName("StaticHashTable");
|
||||
|
||||
//- A zero-sized end iterator
|
||||
struct iteratorEnd
|
||||
{
|
||||
//- Construct null
|
||||
iteratorEnd()
|
||||
{}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class StaticHashTable Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class T, class Key=word, class Hash=string::hash>
|
||||
class StaticHashTable
|
||||
:
|
||||
public StaticHashTableCore
|
||||
{
|
||||
// Private data type for table entries
|
||||
|
||||
//- The lookup keys, ordered per hash value
|
||||
List<List<Key>> keys_;
|
||||
|
||||
//- For each key the corresponding object.
|
||||
List<List<T>> objects_;
|
||||
|
||||
//- The current number of elements in table
|
||||
label nElmts_;
|
||||
|
||||
//- 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 hashed entry to a possibly already existing key
|
||||
bool set(const Key& key, const T& obj, bool protect);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// Forward declaration of STL iterators
|
||||
|
||||
template<class TRef, class TableRef>
|
||||
class Iterator;
|
||||
|
||||
typedef Iterator
|
||||
<
|
||||
T&,
|
||||
StaticHashTable<T, Key, Hash>&
|
||||
> iterator;
|
||||
|
||||
typedef Iterator
|
||||
<
|
||||
const T&,
|
||||
const StaticHashTable<T, Key, Hash>&
|
||||
> const_iterator;
|
||||
|
||||
|
||||
// Declare friendship with the iterators
|
||||
|
||||
friend class Iterator
|
||||
<
|
||||
T&,
|
||||
StaticHashTable<T, Key, Hash>&
|
||||
>;
|
||||
|
||||
friend class Iterator
|
||||
<
|
||||
const T&,
|
||||
const StaticHashTable<T, Key, Hash>&
|
||||
>;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given initial table size
|
||||
StaticHashTable(const label size = 128);
|
||||
|
||||
//- Construct from Istream
|
||||
StaticHashTable(Istream&, const label size = 128);
|
||||
|
||||
//- Construct as copy
|
||||
StaticHashTable(const StaticHashTable<T, Key, Hash>&);
|
||||
|
||||
//- Construct by transferring the parameter contents
|
||||
StaticHashTable(const Xfer<StaticHashTable<T, Key, Hash>>&);
|
||||
|
||||
|
||||
//- Destructor
|
||||
~StaticHashTable();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return number of elements in table.
|
||||
inline label size() const;
|
||||
|
||||
//- Return true if the hash table is empty
|
||||
inline bool empty() const;
|
||||
|
||||
//- Return true if hashed entry is found in table
|
||||
bool found(const Key& key) const;
|
||||
|
||||
//- Find and return an iterator set at the hashed entry
|
||||
// If not found iterator = end()
|
||||
iterator find(const Key& key);
|
||||
|
||||
//- Find and return an const_iterator set at the hashed entry
|
||||
// If not found iterator = end()
|
||||
const_iterator find(const Key& key) const;
|
||||
|
||||
//- Find and return an const_iterator set at the hashed entry
|
||||
// If not found iterator = end()
|
||||
const_iterator cfind(const Key& key) const;
|
||||
|
||||
//- Return the table of contents
|
||||
List<Key> toc() const;
|
||||
|
||||
//- Print information
|
||||
Ostream& printInfo(Ostream&) const;
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
//- Insert a new hashed entry
|
||||
bool insert(const Key& key, const T& newElmt);
|
||||
|
||||
//- Assign a new hashed entry, overwriting existing entries
|
||||
inline bool set(const Key&, const T& newElmt);
|
||||
|
||||
//- Erase an hashed entry specified by given iterator
|
||||
bool erase(const iterator& it);
|
||||
|
||||
//- Erase an hashed entry specified by given key if in table
|
||||
bool erase(const Key& key);
|
||||
|
||||
//- Resize the hash table for efficiency
|
||||
void resize(const label newSize);
|
||||
|
||||
//- Remove entries in the given hash table from this hash table
|
||||
// Return the number of elements removed
|
||||
label erase(const StaticHashTable<T, Key, Hash>&);
|
||||
|
||||
//- Clear all entries from table
|
||||
void clear();
|
||||
|
||||
//- Clear the table entries and the table itself.
|
||||
// Equivalent to clear() followed by resize(1)
|
||||
void clearStorage();
|
||||
|
||||
//- Transfer the contents of the argument table into this table
|
||||
// and annul the argument table.
|
||||
void transfer(StaticHashTable<T, Key, Hash>&);
|
||||
|
||||
//- Transfer contents to the Xfer container
|
||||
inline Xfer<StaticHashTable<T, Key, Hash>> xfer();
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Find and return an hashed entry
|
||||
inline T& operator[](const Key&);
|
||||
|
||||
//- Find and return an hashed entry
|
||||
inline const T& operator[](const Key&) const;
|
||||
|
||||
//- Find and return an hashed entry, create it null if not present.
|
||||
inline T& operator()(const Key&);
|
||||
|
||||
//- Assignment
|
||||
void operator=(const StaticHashTable<T, Key, Hash>&);
|
||||
|
||||
//- Equality. Two hash tables are equal if all contents of first are
|
||||
// also in second and vice versa.
|
||||
bool operator==(const StaticHashTable<T, Key, Hash>&) const;
|
||||
|
||||
//- The opposite of the equality operation.
|
||||
bool operator!=(const StaticHashTable<T, Key, Hash>&) const;
|
||||
|
||||
|
||||
// STL type definitions
|
||||
|
||||
//- Type of values the StaticHashTable contains.
|
||||
typedef T value_type;
|
||||
|
||||
//- Type that can be used for storing into StaticHashTable::value_type
|
||||
// objects. This type is usually List::value_type&.
|
||||
typedef T& reference;
|
||||
|
||||
//- Type that can be used for storing into constant
|
||||
// StaticHashTable::value_type objects. This type is usually const
|
||||
// StaticHashTable::value_type&.
|
||||
typedef const T& const_reference;
|
||||
|
||||
//- The type that can represent the size of a StaticHashTable.
|
||||
typedef label size_type;
|
||||
|
||||
|
||||
// STL iterator
|
||||
|
||||
//- An STL iterator
|
||||
template<class TRef, class TableRef>
|
||||
class Iterator
|
||||
{
|
||||
friend class StaticHashTable;
|
||||
|
||||
template<class TRef2, class TableRef2>
|
||||
friend class Iterator;
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to the StaticHashTable this is an iterator for
|
||||
TableRef hashTable_;
|
||||
|
||||
//- Current hash index
|
||||
label hashIndex_;
|
||||
|
||||
//- Index of current element at hashIndex
|
||||
label elemIndex_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from hash table, hash index and element index
|
||||
inline Iterator
|
||||
(
|
||||
TableRef,
|
||||
label hashIndex_,
|
||||
label elemIndex_
|
||||
);
|
||||
|
||||
//- Construct from the non-const iterator
|
||||
inline Iterator(const iterator&);
|
||||
|
||||
|
||||
// Member operators
|
||||
|
||||
inline void operator=(const iterator&);
|
||||
|
||||
inline bool operator==(const iterator&) const;
|
||||
inline bool operator==(const const_iterator&) const;
|
||||
|
||||
inline bool operator!=(const iterator&) const;
|
||||
inline bool operator!=(const const_iterator&) const;
|
||||
|
||||
inline TRef operator*();
|
||||
inline TRef operator()();
|
||||
|
||||
inline Iterator& operator++();
|
||||
inline Iterator operator++(int);
|
||||
|
||||
inline const Key& key() const;
|
||||
};
|
||||
|
||||
|
||||
//- Iterator set to the beginning of the StaticHashTable
|
||||
inline iterator begin();
|
||||
|
||||
//- Iterator set to beyond the end of the StaticHashTable
|
||||
inline const iterator& end();
|
||||
|
||||
//- const_iterator set to the beginning of the StaticHashTable
|
||||
inline const_iterator cbegin() const;
|
||||
|
||||
//- const_iterator set to beyond the end of the StaticHashTable
|
||||
inline const const_iterator& cend() const;
|
||||
|
||||
//- const_iterator set to the beginning of the StaticHashTable
|
||||
inline const_iterator begin() const;
|
||||
|
||||
//- const_iterator set to beyond the end of the StaticHashTable
|
||||
inline const const_iterator& end() const;
|
||||
|
||||
// IOstream Operator
|
||||
|
||||
friend Istream& operator>> <T, Key, Hash>
|
||||
(
|
||||
Istream&,
|
||||
StaticHashTable<T, Key, Hash>&
|
||||
);
|
||||
|
||||
friend Ostream& operator<< <T, Key, Hash>
|
||||
(
|
||||
Ostream&,
|
||||
const StaticHashTable<T, Key, Hash>&
|
||||
);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//- Iterator returned by end()
|
||||
iterator endIter_;
|
||||
|
||||
//- const_iterator returned by end()
|
||||
const_iterator endConstIter_;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "StaticHashTableI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifndef NoStaticHashTableC
|
||||
#ifdef NoRepository
|
||||
#include "StaticHashTable.C"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,86 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "StaticHashTable.H"
|
||||
#include "uLabel.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(StaticHashTableCore, 0);
|
||||
}
|
||||
|
||||
|
||||
// Approximately labelMax/4
|
||||
static const Foam::label maxTableSize(1L << (sizeof(Foam::label)*8-3));
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::label Foam::StaticHashTableCore::canonicalSize(const label requested_size)
|
||||
{
|
||||
if (requested_size < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (requested_size >= maxTableSize)
|
||||
{
|
||||
return maxTableSize;
|
||||
}
|
||||
|
||||
// Enforce power of two - makes for a very fast modulus.
|
||||
// Use unsigned for these calculations.
|
||||
//
|
||||
// - The lower limit (8) is somewhat arbitrary, but if the hash table
|
||||
// is too small, there will be many direct table collisions.
|
||||
// - The upper limit (approx. labelMax/4) must be a power of two,
|
||||
// need not be extremely large for hashing.
|
||||
|
||||
uLabel powerOfTwo = 8u; // lower-limit
|
||||
|
||||
const uLabel size = requested_size;
|
||||
if (size <= powerOfTwo)
|
||||
{
|
||||
return powerOfTwo;
|
||||
}
|
||||
else if (size & (size-1)) // <- Modulus of i^2
|
||||
{
|
||||
// Determine power-of-two. Brute-force is fast enough.
|
||||
while (powerOfTwo < size)
|
||||
{
|
||||
powerOfTwo <<= 1;
|
||||
}
|
||||
|
||||
return powerOfTwo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,399 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "error.H"
|
||||
#include "IOstreams.H"
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label
|
||||
Foam::StaticHashTable<T, Key, Hash>::hashKeyIndex(const Key& key) const
|
||||
{
|
||||
// size is power of two - this is the modulus
|
||||
return Hash()(key) & (keys_.size() - 1);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::label Foam::StaticHashTable<T, Key, Hash>::size() const
|
||||
{
|
||||
return nElmts_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline bool Foam::StaticHashTable<T, Key, Hash>::empty() const
|
||||
{
|
||||
return !nElmts_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline bool Foam::StaticHashTable<T, Key, Hash>::insert
|
||||
(
|
||||
const Key& key,
|
||||
const T& obj
|
||||
)
|
||||
{
|
||||
return set(key, obj, true);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline bool Foam::StaticHashTable<T, Key, Hash>::set
|
||||
(
|
||||
const Key& key,
|
||||
const T& obj
|
||||
)
|
||||
{
|
||||
return set(key, obj, false);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline Foam::Xfer<Foam::StaticHashTable<T, Key, Hash>>
|
||||
Foam::StaticHashTable<T, Key, Hash>::xfer()
|
||||
{
|
||||
return xferMove(*this);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline T& Foam::StaticHashTable<T, Key, Hash>::operator[](const Key& key)
|
||||
{
|
||||
iterator iter = find(key);
|
||||
|
||||
if (iter == end())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< toc()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
return *iter;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const T& Foam::StaticHashTable<T, Key, Hash>::operator[]
|
||||
(
|
||||
const Key& key
|
||||
) const
|
||||
{
|
||||
const_iterator iter = find(key);
|
||||
|
||||
if (iter == cend())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< toc()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
return *iter;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline T& Foam::StaticHashTable<T, Key, Hash>::operator()(const Key& key)
|
||||
{
|
||||
iterator iter = find(key);
|
||||
|
||||
if (iter == end())
|
||||
{
|
||||
insert(key, T());
|
||||
return *find(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::Iterator
|
||||
(
|
||||
TableRef hashTbl,
|
||||
label hashIndex,
|
||||
label elemIndex
|
||||
)
|
||||
:
|
||||
hashTable_(hashTbl),
|
||||
hashIndex_(hashIndex),
|
||||
elemIndex_(elemIndex)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::Iterator
|
||||
(
|
||||
const iterator& iter
|
||||
)
|
||||
:
|
||||
hashTable_(iter.hashTable_),
|
||||
hashIndex_(iter.hashIndex_),
|
||||
elemIndex_(iter.elemIndex_)
|
||||
{}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline void
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator=
|
||||
(
|
||||
const iterator& iter
|
||||
)
|
||||
{
|
||||
this->hashIndex_ = iter.hashIndex_;
|
||||
this->elemIndex_ = iter.elemIndex_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline bool
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator==
|
||||
(
|
||||
const iterator& iter
|
||||
) const
|
||||
{
|
||||
return hashIndex_ == iter.hashIndex_ && elemIndex_ == iter.elemIndex_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline bool
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator==
|
||||
(
|
||||
const const_iterator& iter
|
||||
) const
|
||||
{
|
||||
return hashIndex_ == iter.hashIndex_ && elemIndex_ == iter.elemIndex_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline bool
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator!=
|
||||
(
|
||||
const iterator& iter
|
||||
) const
|
||||
{
|
||||
return !operator==(iter);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline bool
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator!=
|
||||
(
|
||||
const const_iterator& iter
|
||||
) const
|
||||
{
|
||||
return !operator==(iter);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline TRef
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator*()
|
||||
{
|
||||
return hashTable_.objects_[hashIndex_][elemIndex_];
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline TRef
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator()()
|
||||
{
|
||||
return operator*();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline
|
||||
typename Foam::StaticHashTable<T, Key, Hash>::template Iterator
|
||||
<
|
||||
TRef,
|
||||
TableRef
|
||||
>&
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator
|
||||
<
|
||||
TRef,
|
||||
TableRef
|
||||
>::operator++()
|
||||
{
|
||||
// A negative index is a special value from erase
|
||||
// (see notes in HashTable)
|
||||
if (hashIndex_ < 0)
|
||||
{
|
||||
hashIndex_ = -(hashIndex_+1) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try the next element on the local list
|
||||
elemIndex_++;
|
||||
|
||||
if (elemIndex_ < hashTable_.objects_[hashIndex_].size())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
// Step to the next table entry
|
||||
elemIndex_ = 0;
|
||||
|
||||
while
|
||||
(
|
||||
++hashIndex_ < hashTable_.objects_.size()
|
||||
&& !hashTable_.objects_[hashIndex_].size()
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
if (hashIndex_ >= hashTable_.objects_.size())
|
||||
{
|
||||
// make end iterator
|
||||
hashIndex_ = hashTable_.keys_.size();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline
|
||||
typename Foam::StaticHashTable<T, Key, Hash>::template Iterator
|
||||
<
|
||||
TRef,
|
||||
TableRef
|
||||
>
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator
|
||||
<
|
||||
TRef,
|
||||
TableRef
|
||||
>::operator++
|
||||
(
|
||||
int
|
||||
)
|
||||
{
|
||||
iterator tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class TRef, class TableRef>
|
||||
inline const Key&
|
||||
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::key() const
|
||||
{
|
||||
return hashTable_.keys_[hashIndex_][elemIndex_];
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::StaticHashTable<T, Key, Hash>::iterator
|
||||
Foam::StaticHashTable<T, Key, Hash>::begin()
|
||||
{
|
||||
// Find first non-empty entry
|
||||
forAll(keys_, hashIdx)
|
||||
{
|
||||
if (keys_[hashIdx].size())
|
||||
{
|
||||
return iterator(*this, hashIdx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return StaticHashTable<T, Key, Hash>::endIter_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::StaticHashTable<T, Key, Hash>::iterator&
|
||||
Foam::StaticHashTable<T, Key, Hash>::end()
|
||||
{
|
||||
return StaticHashTable<T, Key, Hash>::endIter_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
|
||||
Foam::StaticHashTable<T, Key, Hash>::cbegin() const
|
||||
{
|
||||
// Find first non-empty entry
|
||||
forAll(keys_, hashIdx)
|
||||
{
|
||||
if (keys_[hashIdx].size())
|
||||
{
|
||||
return const_iterator(*this, hashIdx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return StaticHashTable<T, Key, Hash>::endConstIter_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::StaticHashTable<T, Key, Hash>::const_iterator&
|
||||
Foam::StaticHashTable<T, Key, Hash>::cend() const
|
||||
{
|
||||
return StaticHashTable<T, Key, Hash>::endConstIter_;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
|
||||
Foam::StaticHashTable<T, Key, Hash>::begin() const
|
||||
{
|
||||
return this->cbegin();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const typename Foam::StaticHashTable<T, Key, Hash>::const_iterator&
|
||||
Foam::StaticHashTable<T, Key, Hash>::end() const
|
||||
{
|
||||
return StaticHashTable<T, Key, Hash>::endConstIter_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,237 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "StaticHashTable.H"
|
||||
#include "Istream.H"
|
||||
#include "Ostream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
|
||||
(
|
||||
Istream& is,
|
||||
const label size
|
||||
)
|
||||
:
|
||||
StaticHashTableCore(),
|
||||
keys_(StaticHashTableCore::canonicalSize(size)),
|
||||
objects_(StaticHashTableCore::canonicalSize(size)),
|
||||
nElmts_(0),
|
||||
endIter_(*this, keys_.size(), 0),
|
||||
endConstIter_(*this, keys_.size(), 0)
|
||||
{
|
||||
if (size < 1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Illegal size " << size << " for StaticHashTable."
|
||||
<< " Minimum size is 1" << abort(FatalError);
|
||||
}
|
||||
|
||||
operator>>(is, *this);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::Ostream&
|
||||
Foam::StaticHashTable<T, Key, Hash>::printInfo(Ostream& os) const
|
||||
{
|
||||
label used = 0;
|
||||
label maxChain = 0;
|
||||
unsigned avgChain = 0;
|
||||
|
||||
// Find first non-empty entry
|
||||
forAll(keys_, hashIdx)
|
||||
{
|
||||
const label count = keys_[hashIdx].size();
|
||||
if (count)
|
||||
{
|
||||
++used;
|
||||
avgChain += count;
|
||||
|
||||
if (maxChain < count)
|
||||
{
|
||||
maxChain = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os << "StaticHashTable<T,Key,Hash>"
|
||||
<< " elements:" << size() << " slots:" << used << "/" << keys_.size()
|
||||
<< " chaining(avg/max):" << (used ? float(avgChain/used) : 0)
|
||||
<< "/" << maxChain << endl;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::Istream& Foam::operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
|
||||
{
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
// Anull list
|
||||
L.clear();
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
token firstToken(is);
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"operator>>(Istream&, StaticHashTable<T, Key, Hash>&) : "
|
||||
"reading first token"
|
||||
);
|
||||
|
||||
if (firstToken.isLabel())
|
||||
{
|
||||
label s = firstToken.labelToken();
|
||||
|
||||
// Read beginning of contents
|
||||
char delimiter = is.readBeginList("StaticHashTable<T, Key, Hash>");
|
||||
|
||||
if (s)
|
||||
{
|
||||
if (2*s > L.keys_.size())
|
||||
{
|
||||
L.resize(2*s);
|
||||
}
|
||||
|
||||
if (delimiter == token::BEGIN_LIST)
|
||||
{
|
||||
for (label i=0; i<s; i++)
|
||||
{
|
||||
Key key;
|
||||
is >> key;
|
||||
L.insert(key, pTraits<T>(is));
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"operator>>(Istream&, StaticHashTable<T, Key, Hash>&)"
|
||||
" : reading entry"
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "incorrect first token, '(', found " << firstToken.info()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
|
||||
// Read end of contents
|
||||
is.readEndList("StaticHashTable");
|
||||
}
|
||||
else if (firstToken.isPunctuation())
|
||||
{
|
||||
if (firstToken.pToken() != token::BEGIN_LIST)
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "incorrect first token, '(', found " << firstToken.info()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
token lastToken(is);
|
||||
while
|
||||
(
|
||||
!(
|
||||
lastToken.isPunctuation()
|
||||
&& lastToken.pToken() == token::END_LIST
|
||||
)
|
||||
)
|
||||
{
|
||||
is.putBack(lastToken);
|
||||
|
||||
Key key;
|
||||
is >> key;
|
||||
|
||||
T element;
|
||||
is >> element;
|
||||
|
||||
L.insert(key, element);
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"operator>>(Istream&, StaticHashTable<T, Key, Hash>&) : "
|
||||
"reading entry"
|
||||
);
|
||||
|
||||
is >> lastToken;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "incorrect first token, expected <int> or '(', found "
|
||||
<< firstToken.info()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Ostream& os,
|
||||
const StaticHashTable<T, Key, Hash>& L)
|
||||
{
|
||||
// Write size and start delimiter
|
||||
os << nl << L.size() << nl << token::BEGIN_LIST << nl;
|
||||
|
||||
// Write contents
|
||||
for
|
||||
(
|
||||
typename StaticHashTable<T, Key, Hash>::const_iterator iter = L.begin();
|
||||
iter != L.end();
|
||||
++iter
|
||||
)
|
||||
{
|
||||
os << iter.key() << token::SPACE << iter() << nl;
|
||||
}
|
||||
|
||||
// Write end delimiter
|
||||
os << token::END_LIST;
|
||||
|
||||
os.check(FUNCTION_NAME);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,97 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\/ 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::nil
|
||||
|
||||
Description
|
||||
A zero-sized class without any storage. Used, for example, in HashSet.
|
||||
|
||||
Note
|
||||
A zero-sized class actually does still require at least 1 byte storage.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef nil_H
|
||||
#define nil_H
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class Istream;
|
||||
class Ostream;
|
||||
|
||||
// Forward declaration of friend functions and operators
|
||||
|
||||
class nil;
|
||||
|
||||
Istream& operator>>(Istream&, nil&);
|
||||
Ostream& operator<<(Ostream&, const nil&);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class nil Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class nil
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
nil()
|
||||
{}
|
||||
|
||||
//- Construct from Istream
|
||||
nil(Istream&)
|
||||
{}
|
||||
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
friend Istream& operator>>(Istream& is, nil&)
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
friend Ostream& operator<<(Ostream& os, const nil&)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -22,12 +22,13 @@ License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::nullObject
|
||||
Foam::NullObject
|
||||
|
||||
Description
|
||||
Singleton null-object class and instance.
|
||||
It occupies enough space to reinterpret its content as a class with
|
||||
a null pointer for its content.
|
||||
Its contents occupy just enough space to also be reinterpreted
|
||||
as another class with a null pointer or zero long for its first
|
||||
member.
|
||||
|
||||
SourceFiles
|
||||
nullObjectI.H
|
||||
@ -43,8 +44,14 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
class Istream;
|
||||
class Ostream;
|
||||
|
||||
class NullObject;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class nullObject Declaration
|
||||
Class NullObject Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class NullObject
|
||||
@ -55,12 +62,12 @@ class NullObject
|
||||
{
|
||||
void* ptr;
|
||||
unsigned long val;
|
||||
} null;
|
||||
} content;
|
||||
|
||||
//- Private constructor
|
||||
//- Private constructor for singleton only
|
||||
NullObject()
|
||||
:
|
||||
null{nullptr}
|
||||
content{nullptr}
|
||||
{}
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
@ -70,23 +77,44 @@ class NullObject
|
||||
void operator=(const NullObject&) = delete;
|
||||
|
||||
public:
|
||||
//- The unique null object
|
||||
static const NullObject nullObject;
|
||||
|
||||
//- A nullptr pointer content
|
||||
inline const void* pointer() const
|
||||
{
|
||||
return null.ptr;
|
||||
}
|
||||
// Static Data
|
||||
|
||||
//- A zero value content
|
||||
inline unsigned long value() const
|
||||
{
|
||||
return null.val;
|
||||
}
|
||||
//- A unique null object
|
||||
static const NullObject nullObject;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- A nullptr pointer content
|
||||
inline const void* pointer() const
|
||||
{
|
||||
return content.ptr;
|
||||
}
|
||||
|
||||
//- Zero valued integer content
|
||||
inline unsigned long value() const
|
||||
{
|
||||
return content.val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
//- Read from Istream consumes no content.
|
||||
inline Istream& operator>>(Istream& is, NullObject&)
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
//- Write to Ostream emits no content.
|
||||
inline Ostream& operator<<(Ostream& os, const NullObject&)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
//- Pointer to the unique nullObject
|
||||
extern const NullObject* nullObjectPtr;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -25,9 +25,8 @@ Class
|
||||
Foam::one
|
||||
|
||||
Description
|
||||
A class representing the concept of 1 (scalar(1.0)) used to avoid
|
||||
unnecessary manipulations for objects which are known to be one at
|
||||
compile-time.
|
||||
A class representing the concept of 1 (or 1.0) used to avoid unnecessary
|
||||
manipulations for objects that are known to be one at compile-time.
|
||||
|
||||
SourceFiles
|
||||
oneI.H
|
||||
@ -44,6 +43,11 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes, friend functions and operators
|
||||
class Istream;
|
||||
class Ostream;
|
||||
class one;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class one Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -51,15 +55,22 @@ namespace Foam
|
||||
class one
|
||||
{
|
||||
public:
|
||||
|
||||
typedef one value_type;
|
||||
|
||||
// Forward declaration
|
||||
class null;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
//- Null constructible
|
||||
one()
|
||||
{}
|
||||
|
||||
//- Construct null from Istream. Consumes no content.
|
||||
explicit one(Istream&)
|
||||
{}
|
||||
|
||||
|
||||
// Member operators
|
||||
|
||||
@ -83,6 +94,43 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class one::null Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- A one class with a null output adapter.
|
||||
class one::null
|
||||
:
|
||||
public one
|
||||
{
|
||||
public:
|
||||
typedef null value_type;
|
||||
|
||||
//- Null constructible
|
||||
null()
|
||||
{}
|
||||
|
||||
//- Construct null from Istream without consuming any content.
|
||||
explicit null(Istream&)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
//- Read from Istream consumes no content.
|
||||
inline Istream& operator>>(Istream& is, one&)
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
//- Write to Ostream emits no content.
|
||||
inline Ostream& operator<<(Ostream& os, const one::null&)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -39,13 +39,11 @@ Description
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
typedef wordRes wordReListMatcher;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
24
src/OpenFOAM/primitives/zero/nil.H
Normal file
24
src/OpenFOAM/primitives/zero/nil.H
Normal file
@ -0,0 +1,24 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Compatibility include
|
||||
|
||||
Typedef
|
||||
Foam::nil
|
||||
|
||||
Description
|
||||
The older name for Foam::zero::null.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef nil_H
|
||||
#define nil_H
|
||||
|
||||
#include "zero.H"
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
typedef zero::null nil;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -43,6 +43,12 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
class Istream;
|
||||
class Ostream;
|
||||
|
||||
class zero;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class zero Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -50,15 +56,22 @@ namespace Foam
|
||||
class zero
|
||||
{
|
||||
public:
|
||||
|
||||
typedef zero value_type;
|
||||
|
||||
// Forward declaration
|
||||
class null;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
//- Null constructible
|
||||
zero()
|
||||
{}
|
||||
|
||||
//- Construct null from Istream. Consumes no content.
|
||||
explicit zero(Istream&)
|
||||
{}
|
||||
|
||||
|
||||
// Member operators
|
||||
|
||||
@ -85,9 +98,47 @@ public:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class zero::null Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- A zero class with a null output adapter.
|
||||
class zero::null
|
||||
:
|
||||
public zero
|
||||
{
|
||||
public:
|
||||
typedef null value_type;
|
||||
|
||||
//- Null constructible
|
||||
null()
|
||||
{}
|
||||
|
||||
//- Construct null from Istream without consuming any content.
|
||||
explicit null(Istream&)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
//- Read from Istream consumes no content.
|
||||
inline Istream& operator>>(Istream& is, zero&)
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
//- Write to Ostream emits no content.
|
||||
inline Ostream& operator<<(Ostream& os, const zero::null&)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// Global zero
|
||||
static const zero Zero;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user