HashTable / StaticHashTable changes

StaticHashTable:
- erase(iterator&) now actually alters the iterator and iterator++() handles
  it properly
- clear() also sets count to zero
- operator=(const StaticHashTable&) doesn't crash after a previous transfer
- operator(), operator==() and operator!=() added

HashTable:
- operator=(const HashTable&) gets tableSize if required, eg, after a
  previous transfer)

HashSet / Map
- add xfer<...> constructor for underlying HashTable
This commit is contained in:
Mark Olesen
2009-01-02 13:24:30 +01:00
parent 973b9ea0ce
commit a010121427
15 changed files with 813 additions and 537 deletions

View File

@ -24,90 +24,122 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include <iostream>
#include "HashTable.H" #include "HashTable.H"
#include "IOstreams.H"
#include "IStringStream.H"
#include "OStringStream.H"
using namespace Foam; using namespace Foam;
// use define so we can easily test other implementations
#define HASHTABLE_CLASS HashTable
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program: // Main program:
int main() int main()
{ {
//for (;;) HASHTABLE_CLASS<double> table1(100);
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;
Info<< "\ntable1 [" << table1.size() << "] " << endl;
forAllIter(HASHTABLE_CLASS<double>, table1, iter)
{ {
HashTable<double> myTable(100); Info<< iter.key() << " => " << iter() << nl;
myTable.insert("aaa", 1.0);
myTable.insert("aba", 2.0);
myTable.insert("aca", 3.0);
myTable.insert("ada", 4.0);
myTable.insert("aeq", 5.0);
myTable.insert("aaw", 6.0);
myTable.insert("abs", 7.0);
myTable.insert("acr", 8.0);
myTable.insert("adx", 9.0);
myTable.insert("aec", 10.0);
myTable.erase("aaw");
myTable.erase("abs");
std::cerr << myTable.find("aaa")() << '\n';
std::cerr << myTable.find("aba")() << '\n';
std::cerr << myTable.find("aca")() << '\n';
std::cerr << myTable.find("ada")() << '\n';
std::cerr << myTable.find("aeq")() << '\n';
//std::cerr << myTable.find("aaw")() << '\n';
//std::cerr << myTable.find("abs")() << '\n';
std::cerr << myTable.find("acr")() << '\n';
std::cerr << myTable.find("adx")() << '\n';
std::cerr << myTable.find("aec")() << '\n';
std::cerr << "\nprint table\n" << std::endl;
for
(
HashTable<double>::iterator iter = myTable.begin();
iter != myTable.end();
++iter
)
{
std::cerr << *iter << '\n';
} }
std::cerr << "\nprint table\n" << std::endl; 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;
forAllIter(HashTable<double>, myTable, iter)
{ {
std::cerr << *iter << '\n'; OStringStream os;
os << table1;
HASHTABLE_CLASS<double> readTable(IStringStream(os.str())(), 100);
Info<< "Istream constructor:" << readTable << endl;
} }
std::cerr << "\ncopy of table\n" << std::endl;
HashTable<double> myTable2; HASHTABLE_CLASS<double> table2(table1);
myTable2 = myTable; HASHTABLE_CLASS<double> table3(table1.transfer());
forAllConstIter(HashTable<double>, myTable2, iter2) Info<< "\ncopy table1 -> table2" << nl
<< "transfer table1 -> table3 via the transfer() method" << nl;
Info<< "\ntable1" << table1 << nl
<< "\ntable2" << table1 << nl
<< "\ntable3" << table3 << nl;
Info<< "\ndelete table2" << nl;
forAllIter(HASHTABLE_CLASS<double>, table2, iter)
{ {
std::cerr << *iter2 << '\n'; Info<< "deleting " << iter.key() << " => " << iter() << " ... ";
table2.erase(iter);
Info<< "deleted" << endl;
} }
std::cerr << "\ndelete entries\n" << std::endl; Info<< "\ntable1" << table1 << nl
<< "\ntable2" << table2 << nl
<< "\ntable3" << table3 << nl;
forAllIter(HashTable<double>, myTable, iter) table3.resize(1);
{ Info<< "\nresize(1) table3" << table3 << nl;
std::cerr << "deleting " << *iter << '\n';
myTable.erase(iter);
std::cerr << "deleted\n";
}
forAllConstIter(HashTable<double>, myTable, iter) table3.resize(10000);
{ Info<< "\nresize(10000) table3" << table3 << nl;
std::cerr << *iter << '\n';
}
}
std::cerr << "\nBye.\n"; 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;
Info<< "\nclearStorage table3 ... ";
table3.clearStorage();
Info<< table3 << nl;
Info<< "\nDone\n";
return 0; return 0;
} }

View File

@ -28,6 +28,7 @@ Description
#include "HashTable.H" #include "HashTable.H"
#include "HashPtrTable.H" #include "HashPtrTable.H"
#include "Map.H"
using namespace Foam; using namespace Foam;
@ -36,38 +37,46 @@ using namespace Foam;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
HashTable<label, Foam::string> testTable(0); HashTable<label, Foam::string> table1(0);
testTable.insert("kjhk", 10); table1.insert("kjhk", 10);
testTable.insert("kjhk2", 12); table1.insert("kjhk2", 12);
Info<< testTable << endl; Info<< "table1: " << table1 << nl
Info<< testTable.toc() << endl; << "toc: " << table1.toc() << endl;
HashTable<label, label, Hash<label> > testTable2(10); HashTable<label, label, Hash<label> > table2(10);
testTable2.insert(3, 10); table2.insert(3, 10);
testTable2.insert(5, 12); table2.insert(5, 12);
testTable2.insert(7, 16); table2.insert(7, 16);
Info<< testTable2 << endl; Info<< "table2: " << table2 << nl
Info<< testTable2.toc() << endl; << "toc: " << table2.toc() << endl;
HashTable<label, label, Hash<label> > testTable3(1); Map<label> table3(1);
testTable3.transfer(testTable2); table3.transfer(table2);
Info<< testTable2 << endl; Info<< "table2: " << table2 << nl
Info<< testTable2.toc() << endl; << "toc: " << table2.toc() << endl;
Info<< testTable3 << endl; Info<< "table3: " << table3 << nl
Info<< testTable3.toc() << endl; << "toc: " << table3.toc() << endl;
Foam::HashPtrTable<label, Foam::string> testPtrTable(0); Map<label> table4(table3.transfer());
testPtrTable.insert("kjhkjh", new label(10));
Info<< testPtrTable.toc() << endl; Info<< "table3: " << table3 << nl
<< "toc: " << table3.toc() << endl;
Info << "End\n" << endl; Info<< "table4: " << table4 << nl
<< "toc: " << table4.toc() << endl;
HashPtrTable<label, Foam::string> ptable1(0);
ptable1.insert("kjhkjh", new label(10));
Info<< "PtrTable toc: " << ptable1.toc() << endl;
Info<< "End\n" << endl;
return 0; return 0;
} }

View File

@ -0,0 +1,3 @@
staticHashTableTest.C
EXE = $(FOAM_APPBIN)/staticHashTableTest

View File

@ -22,12 +22,8 @@ License
along with OpenFOAM; if not, write to the Free Software Foundation, along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include <iostream>
#include "StaticHashTable.H" #include "StaticHashTable.H"
#include "IOstreams.H" #include "IOstreams.H"
#include "IStringStream.H" #include "IStringStream.H"
@ -35,103 +31,115 @@ Description
using namespace Foam; using namespace Foam;
// use define so we can easily test other implementations
#define HASHTABLE_CLASS StaticHashTable
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program: // Main program:
int main() int main()
{ {
//for (;;) HASHTABLE_CLASS<double> table1(100);
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;
Info<< "\ntable1 [" << table1.size() << "] " << endl;
forAllIter(HASHTABLE_CLASS<double>, table1, iter)
{ {
StaticHashTable<double> myTable(10); Info<< iter.key() << " => " << iter() << nl;
}
myTable.insert("aaa", 1.0); table1.set("acr", 108);
myTable.insert("aba", 2.0); table1.set("adx", 109);
myTable.insert("aca", 3.0); table1.set("aec", 100);
myTable.insert("ada", 4.0); table1("aaw") -= 1000;
myTable.insert("aeq", 5.0); table1("aeq") += 1000;
myTable.insert("aaw", 6.0);
myTable.insert("abs", 7.0);
myTable.insert("acr", 8.0);
myTable.insert("adx", 9.0);
myTable.insert("aec", 10.0);
Pout<< "Foam output operator:" << nl << endl; Info<< "\noverwrote some values table1: " << table1 << endl;
Pout<< myTable << endl;
//myTable.erase("aaw"); Info<< "\ntest find:" << endl;
//myTable.erase("abs"); Info<< table1.find("aaa")() << nl
//std::cerr << "Size now:" << myTable.size() << '\n'; << table1.find("aba")() << nl
<< table1.find("aca")() << nl
Pout<< "toc:" << nl << endl; << table1.find("ada")() << nl
Pout<< myTable.toc() << endl; << table1.find("aeq")() << nl
<< table1.find("acr")() << nl
<< table1.find("adx")() << nl
std::cerr << myTable.find("aaa")() << '\n'; << table1.find("aec")() << nl
std::cerr << myTable.find("aba")() << '\n'; << table1["aaa"] << nl;
std::cerr << myTable.find("aca")() << '\n';
std::cerr << myTable.find("ada")() << '\n';
std::cerr << myTable.find("aeq")() << '\n';
std::cerr << myTable.find("aaw")() << '\n';
std::cerr << myTable.find("abs")() << '\n';
std::cerr << myTable.find("acr")() << '\n';
std::cerr << myTable.find("adx")() << '\n';
std::cerr << myTable.find("aec")() << '\n';
std::cerr << myTable["aaa"] << '\n';
{ {
OStringStream os; OStringStream os;
os << table1;
HASHTABLE_CLASS<double> readTable(IStringStream(os.str())(), 100);
os << myTable; Info<< "Istream constructor:" << readTable << endl;
IStringStream is(os.str());
Pout<< "Foam Istream constructor:" << nl << endl;
StaticHashTable<double> readTable(is, 100);
Pout<< readTable << endl;
}
std::cerr << "\ncopy construct of table\n" << std::endl;
StaticHashTable<double> myTable1(myTable);
Pout<< "myTable1:" << myTable1 << endl;
std::cerr << "\nassignment of table\n" << std::endl;
StaticHashTable<double> myTable2(100);
myTable2.transfer(myTable);
//Pout<< "myTable:" << myTable << endl;
forAllConstIter(StaticHashTable<double>, myTable2, iter2)
{
std::cerr << *iter2 << '\n';
}
std::cerr << "\ntable resize 1\n" << std::endl;
myTable2.resize(1);
forAllConstIter(StaticHashTable<double>, myTable2, iter2)
{
std::cerr << *iter2 << '\n';
}
std::cerr << "\ntable size 10000\n" << std::endl;
myTable2.resize(10000);
forAllConstIter(StaticHashTable<double>, myTable2, iter2)
{
std::cerr << *iter2 << '\n';
}
} }
std::cerr << "\nBye.\n"; HASHTABLE_CLASS<double> table2(table1);
HASHTABLE_CLASS<double> table3(table1.transfer());
Info<< "\ncopy table1 -> table2" << nl
<< "transfer table1 -> table3 via the transfer() method" << nl;
Info<< "\ntable1" << table1 << nl
<< "\ntable2" << table1 << nl
<< "\ntable3" << table3 << nl;
Info<< "\ndelete table2" << nl;
forAllIter(HASHTABLE_CLASS<double>, table2, iter)
{
Info<< "deleting " << iter.key() << " => " << iter() << " ... ";
table2.erase(iter);
Info<< "deleted" << endl;
}
Info<< "\ntable1" << table1 << nl
<< "\ntable2" << table2 << nl
<< "\ntable3" << table3 << nl;
table3.resize(1);
Info<< "\nresize(1) table3" << table3 << nl;
table3.resize(10000);
Info<< "\nresize(10000) table3" << 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;
Info<< "\nclearStorage table3 ... ";
table3.clearStorage();
Info<< table3 << nl;
Info<< "\nDone\n";
return 0; return 0;
} }

View File

@ -54,7 +54,7 @@ namespace Foam
{ {
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class HashSet Declaration Class HashSet Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class Key=word, class Hash=string::hash> template<class Key=word, class Hash=string::hash>
@ -106,6 +106,12 @@ public:
HashTable<empty, Key, Hash>(hs) HashTable<empty, Key, Hash>(hs)
{} {}
//- Construct by transferring the parameter contents
HashSet(const xfer<HashTable<empty, Key, Hash> >& hs)
:
HashTable<empty, Key, Hash>(hs)
{}
//- Construct from table of contents of the HashTable //- Construct from table of contents of the HashTable
template<class T> template<class T>
HashSet(const HashTable<T, Key, Hash>& ht); HashSet(const HashTable<T, Key, Hash>& ht);

View File

@ -30,15 +30,10 @@ License
#include "HashTable.H" #include "HashTable.H"
#include "List.H" #include "List.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
HashTable<T, Key, Hash>::HashTable(const label size) Foam::HashTable<T, Key, Hash>::HashTable(const label size)
: :
tableSize_(size), tableSize_(size),
table_(NULL), table_(NULL),
@ -49,16 +44,16 @@ HashTable<T, Key, Hash>::HashTable(const label size)
if (tableSize_) if (tableSize_)
{ {
table_ = new hashedEntry*[tableSize_]; table_ = new hashedEntry*[tableSize_];
for (label i=0; i<tableSize_; i++) for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
{ {
table_[i] = 0; table_[hashIdx] = 0;
} }
} }
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht) Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
: :
HashTableName(), HashTableName(),
tableSize_(ht.tableSize_), tableSize_(ht.tableSize_),
@ -71,9 +66,9 @@ HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
{ {
table_ = new hashedEntry*[tableSize_]; table_ = new hashedEntry*[tableSize_];
for (label i=0; i<tableSize_; i++) for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
{ {
table_[i] = 0; table_[hashIdx] = 0;
} }
for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter) for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter)
@ -84,7 +79,10 @@ HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
HashTable<T, Key, Hash>::HashTable(const xfer<HashTable<T, Key, Hash> >& ht) Foam::HashTable<T, Key, Hash>::HashTable
(
const xfer<HashTable<T, Key, Hash> >& ht
)
: :
HashTableName(), HashTableName(),
tableSize_(0), tableSize_(0),
@ -100,7 +98,7 @@ HashTable<T, Key, Hash>::HashTable(const xfer<HashTable<T, Key, Hash> >& ht)
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
HashTable<T, Key, Hash>::~HashTable() Foam::HashTable<T, Key, Hash>::~HashTable()
{ {
if (table_) if (table_)
{ {
@ -113,15 +111,18 @@ HashTable<T, Key, Hash>::~HashTable()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool HashTable<T, Key, Hash>::found(const Key& key) const bool Foam::HashTable<T, Key, Hash>::found(const Key& key) const
{ {
if (tableSize_) if (tableSize_)
{ {
label ii = Hash()(key, tableSize_); label hashIdx = Hash()(key, tableSize_);
for (hashedEntry* n=table_[ii]; n; n=n->next_) for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
{ {
if (key == n->key_) return true; if (key == ep->key_)
{
return true;
}
} }
} }
@ -138,20 +139,22 @@ bool HashTable<T, Key, Hash>::found(const Key& key) const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
typename HashTable<T, Key, Hash>::iterator HashTable<T, Key, Hash>::find typename Foam::HashTable<T, Key, Hash>::iterator
Foam::HashTable<T, Key, Hash>::find
( (
const Key& key const Key& key
) )
{ {
if (tableSize_) if (tableSize_)
{ {
label ii = Hash()(key, tableSize_); label hashIdx = Hash()(key, tableSize_);
hashedEntry* prev = 0;
for (hashedEntry* n=table_[ii]; n; n=n->next_) for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
{ {
if (key == n->key_) return iterator(*this, n, ii); if (key == ep->key_)
prev = n; {
return iterator(*this, ep, hashIdx);
}
} }
} }
@ -168,20 +171,22 @@ typename HashTable<T, Key, Hash>::iterator HashTable<T, Key, Hash>::find
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
typename HashTable<T, Key, Hash>::const_iterator HashTable<T, Key, Hash>::find typename Foam::HashTable<T, Key, Hash>::const_iterator
Foam::HashTable<T, Key, Hash>::find
( (
const Key& key const Key& key
) const ) const
{ {
if (tableSize_) if (tableSize_)
{ {
label ii = Hash()(key, tableSize_); label hashIdx = Hash()(key, tableSize_);
hashedEntry* prev = 0;
for (hashedEntry* n=table_[ii]; n; n=n->next_) for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
{ {
if (key == n->key_) return const_iterator(*this, n, ii); if (key == ep->key_)
prev = n; {
return const_iterator(*this, ep, hashIdx);
}
} }
} }
@ -199,10 +204,9 @@ typename HashTable<T, Key, Hash>::const_iterator HashTable<T, Key, Hash>::find
// Return the table of contents // Return the table of contents
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
List<Key> HashTable<T, Key, Hash>::toc() const Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
{ {
List<Key> tofc(nElmts_); List<Key> tofc(nElmts_);
label i = 0; label i = 0;
for (const_iterator iter = begin(); iter != end(); ++iter) for (const_iterator iter = begin(); iter != end(); ++iter)
@ -215,7 +219,7 @@ List<Key> HashTable<T, Key, Hash>::toc() const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool HashTable<T, Key, Hash>::set bool Foam::HashTable<T, Key, Hash>::set
( (
const Key& key, const Key& key,
const T& newEntry, const T& newEntry,
@ -227,24 +231,24 @@ bool HashTable<T, Key, Hash>::set
resize(2); resize(2);
} }
label ii = Hash()(key, tableSize_); label hashIdx = Hash()(key, tableSize_);
hashedEntry* existing = 0; hashedEntry* existing = 0;
hashedEntry* prev = 0; hashedEntry* prev = 0;
for (hashedEntry* curr = table_[ii]; curr; curr = curr->next_) for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
{ {
if (key == curr->key_) if (key == ep->key_)
{ {
existing = curr; existing = ep;
break; break;
} }
prev = curr; prev = ep;
} }
// not found, insert it at the head // not found, insert it at the head
if (!existing) if (!existing)
{ {
table_[ii] = new hashedEntry(key, table_[ii], newEntry); table_[hashIdx] = new hashedEntry(key, table_[hashIdx], newEntry);
nElmts_++; nElmts_++;
if (double(nElmts_)/tableSize_ > 0.8) if (double(nElmts_)/tableSize_ > 0.8)
@ -269,7 +273,7 @@ bool HashTable<T, Key, Hash>::set
if (debug) if (debug)
{ {
Info<< "HashTable<T, Key, Hash>::set" Info<< "HashTable<T, Key, Hash>::set"
"(const Key& key, T newEntry, false) : " "(const Key& key, T newEntry, true) : "
"Cannot insert " << key << " already in hash table\n"; "Cannot insert " << key << " already in hash table\n";
} }
# endif # endif
@ -279,16 +283,16 @@ bool HashTable<T, Key, Hash>::set
{ {
// found - overwrite existing entry // found - overwrite existing entry
// this corresponds to the Perl convention // this corresponds to the Perl convention
hashedEntry* elemPtr = new hashedEntry(key, existing->next_, newEntry); hashedEntry* ep = new hashedEntry(key, existing->next_, newEntry);
// replace existing element - within list or insert at the head // replace existing element - within list or insert at the head
if (prev) if (prev)
{ {
prev->next_ = elemPtr; prev->next_ = ep;
} }
else else
{ {
table_[ii] = elemPtr; table_[hashIdx] = ep;
} }
delete existing; delete existing;
@ -299,34 +303,34 @@ bool HashTable<T, Key, Hash>::set
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool HashTable<T, Key, Hash>::erase(const iterator& cit) bool Foam::HashTable<T, Key, Hash>::erase(const iterator& cit)
{ {
if (cit.elmtPtr_) // note: endIter_ also has 0 elmtPtr_ if (cit.elmtPtr_) // note: endIter_ also has 0 elmtPtr_
{ {
iterator& it = const_cast<iterator&>(cit); iterator& it = const_cast<iterator&>(cit);
// Search element before elmtPtr_ // Search element before elmtPtr_
hashedEntry* prevElmtPtr = 0; hashedEntry* prev = 0;
for (hashedEntry* n=table_[it.hashIndex_]; n; n=n->next_) for (hashedEntry* ep = table_[it.hashIndex_]; ep; ep = ep->next_)
{ {
if (n == it.elmtPtr_) if (ep == it.elmtPtr_)
{ {
break; break;
} }
prevElmtPtr = n; prev = ep;
} }
if (prevElmtPtr) if (prev)
{ {
// Have element before elmtPtr // Have element before elmtPtr
prevElmtPtr->next_ = it.elmtPtr_->next_; prev->next_ = it.elmtPtr_->next_;
delete it.elmtPtr_; delete it.elmtPtr_;
it.elmtPtr_ = prevElmtPtr; it.elmtPtr_ = prev;
} }
else else
{ {
// elmtPtr is first element on SLlist // elmtPtr is first element on SLList
table_[it.hashIndex_] = it.elmtPtr_->next_; table_[it.hashIndex_] = it.elmtPtr_->next_;
delete it.elmtPtr_; delete it.elmtPtr_;
@ -382,7 +386,7 @@ bool HashTable<T, Key, Hash>::erase(const iterator& cit)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool HashTable<T, Key, Hash>::erase(const Key& key) bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
{ {
iterator it = find(key); iterator it = find(key);
@ -398,7 +402,7 @@ bool HashTable<T, Key, Hash>::erase(const Key& key)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void HashTable<T, Key, Hash>::resize(const label newSize) void Foam::HashTable<T, Key, Hash>::resize(const label newSize)
{ {
if (newSize == tableSize_) if (newSize == tableSize_)
{ {
@ -433,22 +437,22 @@ void HashTable<T, Key, Hash>::resize(const label newSize)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void HashTable<T, Key, Hash>::clear() void Foam::HashTable<T, Key, Hash>::clear()
{ {
if (nElmts_) if (nElmts_)
{ {
for (label i=0; i<tableSize_; i++) for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
{ {
if (table_[i]) if (table_[hashIdx])
{ {
hashedEntry* n = table_[i]; hashedEntry* ep = table_[hashIdx];
while(hashedEntry* next = n->next_) while (hashedEntry* next = ep->next_)
{ {
delete n; delete ep;
n = next; ep = next;
} }
delete n; delete ep;
table_[i] = 0; table_[hashIdx] = 0;
} }
} }
nElmts_ = 0; nElmts_ = 0;
@ -457,7 +461,7 @@ void HashTable<T, Key, Hash>::clear()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void HashTable<T, Key, Hash>::clearStorage() void Foam::HashTable<T, Key, Hash>::clearStorage()
{ {
clear(); clear();
resize(0); resize(0);
@ -465,10 +469,14 @@ void HashTable<T, Key, Hash>::clearStorage()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void HashTable<T, Key, Hash>::transfer(HashTable<T, Key, Hash>& ht) void Foam::HashTable<T, Key, Hash>::transfer(HashTable<T, Key, Hash>& ht)
{ {
clear(); // as per the Destructor
delete[] table_; if (table_)
{
clear();
delete[] table_;
}
tableSize_ = ht.tableSize_; tableSize_ = ht.tableSize_;
ht.tableSize_ = 0; ht.tableSize_ = 0;
@ -484,10 +492,13 @@ void HashTable<T, Key, Hash>::transfer(HashTable<T, Key, Hash>& ht)
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void HashTable<T, Key, Hash>::operator=(const HashTable<T, Key, Hash>& ht) void Foam::HashTable<T, Key, Hash>::operator=
(
const HashTable<T, Key, Hash>& rhs
)
{ {
// Check for assignment to self // Check for assignment to self
if (this == &ht) if (this == &rhs)
{ {
FatalErrorIn FatalErrorIn
( (
@ -497,9 +508,17 @@ void HashTable<T, Key, Hash>::operator=(const HashTable<T, Key, Hash>& ht)
<< abort(FatalError); << abort(FatalError);
} }
clear(); // could be zero-sized from a previous transfer()
if (tableSize_ == 0)
{
resize(rhs.tableSize_);
}
else
{
clear();
}
for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter) for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
{ {
insert(iter.key(), *iter); insert(iter.key(), *iter);
} }
@ -507,26 +526,28 @@ void HashTable<T, Key, Hash>::operator=(const HashTable<T, Key, Hash>& ht)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool HashTable<T, Key, Hash>::operator==(const HashTable<T, Key, Hash>& ht) bool Foam::HashTable<T, Key, Hash>::operator==
const (
const HashTable<T, Key, Hash>& rhs
) const
{ {
// Are all my elements in ht? // Are all my elements in rhs?
for (const_iterator iter = begin(); iter != end(); ++iter) for (const_iterator iter = begin(); iter != end(); ++iter)
{ {
const_iterator fnd = ht.find(iter.key()); const_iterator fnd = rhs.find(iter.key());
if (fnd == ht.end() || (fnd() != iter())) if (fnd == rhs.end() || fnd() != iter())
{ {
return false; return false;
} }
} }
// Are all ht elements in me? // Are all rhs elements in me?
for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter) for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
{ {
const_iterator fnd = find(iter.key()); const_iterator fnd = find(iter.key());
if (fnd == end() || (fnd() != iter())) if (fnd == end() || fnd() != iter())
{ {
return false; return false;
} }
@ -536,17 +557,15 @@ bool HashTable<T, Key, Hash>::operator==(const HashTable<T, Key, Hash>& ht)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool HashTable<T, Key, Hash>::operator!=(const HashTable<T, Key, Hash>& ht) bool Foam::HashTable<T, Key, Hash>::operator!=
const (
const HashTable<T, Key, Hash>& rhs
) const
{ {
return !(operator==(ht)); return !(operator==(rhs));
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
#include "HashTableIO.C" #include "HashTableIO.C"

View File

@ -50,9 +50,7 @@ namespace Foam
// Forward declaration of friend functions and operators // Forward declaration of friend functions and operators
template<class T> template<class T> class List;
class List;
template<class T, class Key, class Hash> class HashTable; template<class T, class Key, class Hash> class HashTable;
template<class T, class Key, class Hash> class HashPtrTable; template<class T, class Key, class Hash> class HashPtrTable;
@ -216,6 +214,9 @@ public:
// and annull the argument table. // and annull the argument table.
void transfer(HashTable<T, Key, Hash>&); void transfer(HashTable<T, Key, Hash>&);
//- Transfer the contents to the xfer container
inline xfer<HashTable<T, Key, Hash> > transfer();
// Member Operators // Member Operators
@ -225,14 +226,13 @@ public:
//- Find and return an hashedEntry //- Find and return an hashedEntry
inline const T& operator[](const Key&) const; inline const T& operator[](const Key&) const;
//- Find and return an hashedEntry and //- Find and return an hashedEntry, create it null if not present.
// if it is not present create it null.
inline T& operator()(const Key&); inline T& operator()(const Key&);
//- Assignment //- Assignment
void operator=(const HashTable<T, Key, Hash>&); void operator=(const HashTable<T, Key, Hash>&);
//- Equality. Two hashtables are equal if all contents of first are //- Equality. Two hash tables are equal if all contents of first are
// also in second and vice versa. So does not depend on table size or // also in second and vice versa. So does not depend on table size or
// order! // order!
bool operator==(const HashTable<T, Key, Hash>&) const; bool operator==(const HashTable<T, Key, Hash>&) const;

View File

@ -26,15 +26,10 @@ License
#include "error.H" #include "error.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline HashTable<T, Key, Hash>::hashedEntry::hashedEntry inline Foam::HashTable<T, Key, Hash>::hashedEntry::hashedEntry
( (
const Key& key, const Key& key,
hashedEntry* next, hashedEntry* next,
@ -50,36 +45,55 @@ inline HashTable<T, Key, Hash>::hashedEntry::hashedEntry
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline label HashTable<T, Key, Hash>::size() const inline Foam::label Foam::HashTable<T, Key, Hash>::size() const
{ {
return nElmts_; return nElmts_;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::insert(const Key& key, const T& newEntry) inline bool Foam::HashTable<T, Key, Hash>::insert
(
const Key& key,
const T& newEntry
)
{ {
return set(key, newEntry, true); return set(key, newEntry, true);
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::set(const Key& key, const T& newEntry) inline bool Foam::HashTable<T, Key, Hash>::set
(
const Key& key,
const T& newEntry
)
{ {
return set(key, newEntry, false); return set(key, newEntry, false);
} }
template<class T, class Key, class Hash>
inline Foam::xfer<Foam::HashTable<T, Key, Hash> >
Foam::HashTable<T, Key, Hash>::transfer()
{
Foam::xfer<HashTable<T, Key, Hash> > xf;
xf().transfer(*this);
return xf;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline T& HashTable<T, Key, Hash>::operator[](const Key& key) inline T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key)
{ {
iterator iter = find(key); iterator iter = find(key);
if (iter == end()) if (iter == end())
{ {
FatalErrorIn("HashTable<T, Key, Hash>::operator[](const Key&)") FatalErrorIn("HashTable<T, Key, Hash>::operator[](const Key&)")
<< key << " not found in table. Valid entries are " << key << " not found in table. Valid entries: "
<< toc() << toc()
<< exit(FatalError); << exit(FatalError);
} }
@ -87,15 +101,16 @@ inline T& HashTable<T, Key, Hash>::operator[](const Key& key)
return *iter; return *iter;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const T& HashTable<T, Key, Hash>::operator[](const Key& key) const inline const T& Foam::HashTable<T, Key, Hash>::operator[](const Key& key) const
{ {
const_iterator iter = find(key); const_iterator iter = find(key);
if (iter == end()) if (iter == end())
{ {
FatalErrorIn("HashTable<T, Key, Hash>::operator[](const Key&) const") FatalErrorIn("HashTable<T, Key, Hash>::operator[](const Key&) const")
<< key << " not found in table. Valid entries are " << key << " not found in table. Valid entries: "
<< toc() << toc()
<< exit(FatalError); << exit(FatalError);
} }
@ -105,7 +120,7 @@ inline const T& HashTable<T, Key, Hash>::operator[](const Key& key) const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline T& HashTable<T, Key, Hash>::operator()(const Key& key) inline T& Foam::HashTable<T, Key, Hash>::operator()(const Key& key)
{ {
iterator iter = find(key); iterator iter = find(key);
@ -124,7 +139,7 @@ inline T& HashTable<T, Key, Hash>::operator()(const Key& key)
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline HashTable<T, Key, Hash>::iterator::iterator inline Foam::HashTable<T, Key, Hash>::iterator::iterator
( (
HashTable<T, Key, Hash>& curHashTable, HashTable<T, Key, Hash>& curHashTable,
hashedEntry* elmt, hashedEntry* elmt,
@ -138,7 +153,10 @@ inline HashTable<T, Key, Hash>::iterator::iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline void HashTable<T, Key, Hash>::iterator::operator=(const iterator& iter) inline void Foam::HashTable<T, Key, Hash>::iterator::operator=
(
const iterator& iter
)
{ {
elmtPtr_ = iter.elmtPtr_; elmtPtr_ = iter.elmtPtr_;
hashIndex_ = iter.hashIndex_; hashIndex_ = iter.hashIndex_;
@ -146,7 +164,7 @@ inline void HashTable<T, Key, Hash>::iterator::operator=(const iterator& iter)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::iterator::operator== inline bool Foam::HashTable<T, Key, Hash>::iterator::operator==
( (
const iterator& iter const iterator& iter
) const ) const
@ -156,7 +174,7 @@ inline bool HashTable<T, Key, Hash>::iterator::operator==
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::iterator::operator!= inline bool Foam::HashTable<T, Key, Hash>::iterator::operator!=
( (
const iterator& iter const iterator& iter
) const ) const
@ -166,7 +184,7 @@ inline bool HashTable<T, Key, Hash>::iterator::operator!=
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::iterator::operator== inline bool Foam::HashTable<T, Key, Hash>::iterator::operator==
( (
const const_iterator& iter const const_iterator& iter
) const ) const
@ -176,7 +194,7 @@ inline bool HashTable<T, Key, Hash>::iterator::operator==
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::iterator::operator!= inline bool Foam::HashTable<T, Key, Hash>::iterator::operator!=
( (
const const_iterator& iter const const_iterator& iter
) const ) const
@ -186,14 +204,14 @@ inline bool HashTable<T, Key, Hash>::iterator::operator!=
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline T& HashTable<T, Key, Hash>::iterator::operator*() inline T& Foam::HashTable<T, Key, Hash>::iterator::operator*()
{ {
return elmtPtr_->obj_; return elmtPtr_->obj_;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline T& HashTable<T, Key, Hash>::iterator::operator()() inline T& Foam::HashTable<T, Key, Hash>::iterator::operator()()
{ {
return operator*(); return operator*();
} }
@ -201,13 +219,13 @@ inline T& HashTable<T, Key, Hash>::iterator::operator()()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline inline
typename HashTable<T, Key, Hash>::iterator& typename Foam::HashTable<T, Key, Hash>::iterator&
HashTable<T, Key, Hash>::iterator::operator++() Foam::HashTable<T, Key, Hash>::iterator::operator++()
{ {
// Check for special value from erase. (sets hashIndex to -1) // Check for special value from erase. (sets hashIndex to -1)
if (hashIndex_ >= 0) if (hashIndex_ >= 0)
{ {
// Do we have additional elements on the singly linked list? // Do we have additional elements on the SLList?
if (elmtPtr_ && elmtPtr_->next_) if (elmtPtr_ && elmtPtr_->next_)
{ {
elmtPtr_ = elmtPtr_->next_; elmtPtr_ = elmtPtr_->next_;
@ -226,16 +244,16 @@ HashTable<T, Key, Hash>::iterator::operator++()
if (hashIndex_ == curHashTable_.tableSize_) if (hashIndex_ == curHashTable_.tableSize_)
{ {
// make end iterator // make end iterator
hashIndex_ = 0;
elmtPtr_ = 0; elmtPtr_ = 0;
hashIndex_ = 0;
} }
return *this; return *this;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline typename HashTable<T, Key, Hash>::iterator inline typename Foam::HashTable<T, Key, Hash>::iterator
HashTable<T, Key, Hash>::iterator::operator++ Foam::HashTable<T, Key, Hash>::iterator::operator++
( (
int int
) )
@ -248,15 +266,15 @@ HashTable<T, Key, Hash>::iterator::operator++
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline inline
const Key& HashTable<T, Key, Hash>::iterator::key() const Key& Foam::HashTable<T, Key, Hash>::iterator::key()
{ {
return elmtPtr_->key_; return elmtPtr_->key_;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline typename HashTable<T, Key, Hash>::iterator inline typename Foam::HashTable<T, Key, Hash>::iterator
HashTable<T, Key, Hash>::begin() Foam::HashTable<T, Key, Hash>::begin()
{ {
label i = 0; label i = 0;
@ -282,8 +300,8 @@ HashTable<T, Key, Hash>::begin()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const typename HashTable<T, Key, Hash>::iterator& inline const typename Foam::HashTable<T, Key, Hash>::iterator&
HashTable<T, Key, Hash>::end() Foam::HashTable<T, Key, Hash>::end()
{ {
return HashTable<T, Key, Hash>::endIter_; return HashTable<T, Key, Hash>::endIter_;
} }
@ -292,7 +310,7 @@ HashTable<T, Key, Hash>::end()
// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline HashTable<T, Key, Hash>::const_iterator::const_iterator inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
( (
const HashTable<T, Key, Hash>& curHashTable, const HashTable<T, Key, Hash>& curHashTable,
const hashedEntry* elmt, const hashedEntry* elmt,
@ -306,7 +324,7 @@ inline HashTable<T, Key, Hash>::const_iterator::const_iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline HashTable<T, Key, Hash>::const_iterator::const_iterator inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
( (
const iterator& iter const iterator& iter
) )
@ -318,7 +336,7 @@ inline HashTable<T, Key, Hash>::const_iterator::const_iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline void HashTable<T, Key, Hash>::const_iterator::operator= inline void Foam::HashTable<T, Key, Hash>::const_iterator::operator=
( (
const const_iterator& iter const const_iterator& iter
) )
@ -329,7 +347,7 @@ inline void HashTable<T, Key, Hash>::const_iterator::operator=
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::const_iterator::operator== inline bool Foam::HashTable<T, Key, Hash>::const_iterator::operator==
( (
const const_iterator& iter const const_iterator& iter
) const ) const
@ -339,7 +357,7 @@ inline bool HashTable<T, Key, Hash>::const_iterator::operator==
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::const_iterator::operator!= inline bool Foam::HashTable<T, Key, Hash>::const_iterator::operator!=
( (
const const_iterator& iter const const_iterator& iter
) const ) const
@ -349,7 +367,7 @@ inline bool HashTable<T, Key, Hash>::const_iterator::operator!=
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::const_iterator::operator== inline bool Foam::HashTable<T, Key, Hash>::const_iterator::operator==
( (
const iterator& iter const iterator& iter
) const ) const
@ -359,7 +377,7 @@ inline bool HashTable<T, Key, Hash>::const_iterator::operator==
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline bool HashTable<T, Key, Hash>::const_iterator::operator!= inline bool Foam::HashTable<T, Key, Hash>::const_iterator::operator!=
( (
const iterator& iter const iterator& iter
) const ) const
@ -369,14 +387,14 @@ inline bool HashTable<T, Key, Hash>::const_iterator::operator!=
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const T& HashTable<T, Key, Hash>::const_iterator::operator*() inline const T& Foam::HashTable<T, Key, Hash>::const_iterator::operator*()
{ {
return elmtPtr_->obj_; return elmtPtr_->obj_;
} }
#ifndef __CINT__ #ifndef __CINT__
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const T& HashTable<T, Key, Hash>::const_iterator::operator()() inline const T& Foam::HashTable<T, Key, Hash>::const_iterator::operator()()
{ {
return operator*(); return operator*();
} }
@ -384,8 +402,8 @@ inline const T& HashTable<T, Key, Hash>::const_iterator::operator()()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline inline
typename HashTable<T, Key, Hash>::const_iterator& typename Foam::HashTable<T, Key, Hash>::const_iterator&
HashTable<T, Key, Hash>::const_iterator::operator++() Foam::HashTable<T, Key, Hash>::const_iterator::operator++()
{ {
if if
( (
@ -407,8 +425,8 @@ HashTable<T, Key, Hash>::const_iterator::operator++()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline typename HashTable<T, Key, Hash>::const_iterator inline typename Foam::HashTable<T, Key, Hash>::const_iterator
HashTable<T, Key, Hash>::const_iterator::operator++ Foam::HashTable<T, Key, Hash>::const_iterator::operator++
( (
int int
) )
@ -421,15 +439,15 @@ HashTable<T, Key, Hash>::const_iterator::operator++
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline inline
const Key& HashTable<T, Key, Hash>::const_iterator::key() const Key& Foam::HashTable<T, Key, Hash>::const_iterator::key()
{ {
return elmtPtr_->key_; return elmtPtr_->key_;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline typename HashTable<T, Key, Hash>::const_iterator inline typename Foam::HashTable<T, Key, Hash>::const_iterator
HashTable<T, Key, Hash>::begin() const Foam::HashTable<T, Key, Hash>::begin() const
{ {
label i = 0; label i = 0;
@ -455,15 +473,11 @@ HashTable<T, Key, Hash>::begin() const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const typename HashTable<T, Key, Hash>::const_iterator& inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
HashTable<T, Key, Hash>::end() const Foam::HashTable<T, Key, Hash>::end() const
{ {
return HashTable<T, Key, Hash>::endConstIter_; return HashTable<T, Key, Hash>::endConstIter_;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* // // ************************************************************************* //

View File

@ -58,13 +58,13 @@ Foam::Istream& Foam::operator>>(Istream& is, HashTable<T, Key, Hash>& L)
// Anull list // Anull list
L.clear(); L.clear();
is.fatalCheck("operator>>(Istream& is, HashTable<T, Key, Hash>& L)"); is.fatalCheck("operator>>(Istream&, HashTable<T, Key, Hash>&)");
token firstToken(is); token firstToken(is);
is.fatalCheck is.fatalCheck
( (
"operator>>(Istream& is, HashTable<T, Key, Hash>& L) : " "operator>>(Istream&, HashTable<T, Key, Hash>&) : "
"reading first token" "reading first token"
); );
@ -101,7 +101,7 @@ Foam::Istream& Foam::operator>>(Istream& is, HashTable<T, Key, Hash>& L)
{ {
FatalIOErrorIn FatalIOErrorIn
( (
"operator>>(Istream& is, HashTable<T, Key, Hash>& L)", "operator>>(Istream&, HashTable<T, Key, Hash>&)",
is is
) << "incorrect first token, '(', found " << firstToken.info() ) << "incorrect first token, '(', found " << firstToken.info()
<< exit(FatalIOError); << exit(FatalIOError);
@ -117,7 +117,7 @@ Foam::Istream& Foam::operator>>(Istream& is, HashTable<T, Key, Hash>& L)
{ {
FatalIOErrorIn FatalIOErrorIn
( (
"operator>>(Istream& is, HashTable<T, Key, Hash>& L)", "operator>>(Istream&, HashTable<T, Key, Hash>&)",
is is
) << "incorrect first token, '(', found " << firstToken.info() ) << "incorrect first token, '(', found " << firstToken.info()
<< exit(FatalIOError); << exit(FatalIOError);
@ -152,7 +152,7 @@ Foam::Istream& Foam::operator>>(Istream& is, HashTable<T, Key, Hash>& L)
{ {
FatalIOErrorIn FatalIOErrorIn
( (
"operator>>(Istream& is, HashTable<T, Key, Hash>& L)", "operator>>(Istream&, HashTable<T, Key, Hash>&)",
is is
) << "incorrect first token, expected <int> or '(', found " ) << "incorrect first token, expected <int> or '(', found "
<< firstToken.info() << firstToken.info()
@ -168,13 +168,10 @@ Foam::Istream& Foam::operator>>(Istream& is, HashTable<T, Key, Hash>& L)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
Foam::Ostream& Foam::operator<<(Ostream& os, const HashTable<T, Key, Hash>& L) Foam::Ostream& Foam::operator<<(Ostream& os, const HashTable<T, Key, Hash>& L)
{ {
// Write size of HashTable // Write size of HashTable and start contents delimiter
os << nl << L.size(); os << nl << L.size() << nl << token::BEGIN_LIST << nl;
// Write beginning of contents // Write contents
os << nl << token::BEGIN_LIST << nl;
// Write HashTable contents
for for
( (
typename HashTable<T, Key, Hash>::const_iterator iter = L.begin(); typename HashTable<T, Key, Hash>::const_iterator iter = L.begin();
@ -185,7 +182,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const HashTable<T, Key, Hash>& L)
os << iter.key() << token::SPACE << iter() << nl; os << iter.key() << token::SPACE << iter() << nl;
} }
// Write end of contents // Write end of contents delimiter
os << token::END_LIST; os << token::END_LIST;
// Check state of IOstream // Check state of IOstream

View File

@ -86,6 +86,12 @@ public:
HashTable<T, label, Hash<label> >(map) HashTable<T, label, Hash<label> >(map)
{} {}
//- Construct by transferring the parameter contents
Map(const xfer<HashTable<T, label, Hash<label> > >& map)
:
HashTable<T, label, Hash<label> >(map)
{}
//- Return a null Map //- Return a null Map
static const Map<T>& null() static const Map<T>& null()

View File

@ -31,16 +31,11 @@ License
#include "List.H" #include "List.H"
#include "IOstreams.H" #include "IOstreams.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct given initial table size // Construct given initial table size
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
StaticHashTable<T, Key, Hash>::StaticHashTable(const label size) Foam::StaticHashTable<T, Key, Hash>::StaticHashTable(const label size)
: :
StaticHashTableName(), StaticHashTableName(),
keys_(size), keys_(size),
@ -62,7 +57,7 @@ StaticHashTable<T, Key, Hash>::StaticHashTable(const label size)
// Construct as copy // Construct as copy
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
StaticHashTable<T, Key, Hash>::StaticHashTable Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
( (
const StaticHashTable<T, Key, Hash>& ht const StaticHashTable<T, Key, Hash>& ht
) )
@ -78,7 +73,7 @@ StaticHashTable<T, Key, Hash>::StaticHashTable
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
StaticHashTable<T, Key, Hash>::StaticHashTable Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
( (
const xfer<StaticHashTable<T, Key, Hash> >& ht const xfer<StaticHashTable<T, Key, Hash> >& ht
) )
@ -97,22 +92,21 @@ StaticHashTable<T, Key, Hash>::StaticHashTable
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
StaticHashTable<T, Key, Hash>::~StaticHashTable() Foam::StaticHashTable<T, Key, Hash>::~StaticHashTable()
{} {}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool StaticHashTable<T, Key, Hash>::found(const Key& key) const bool Foam::StaticHashTable<T, Key, Hash>::found(const Key& key) const
{ {
label ii = Hash()(key, keys_.size()); label hashIdx = Hash()(key, keys_.size());
const List<Key>& localKeys = keys_[hashIdx];
const List<Key>& localKeys = keys_[ii]; forAll(localKeys, elemIdx)
forAll(localKeys, n)
{ {
if (localKeys[n] == key) if (key == localKeys[elemIdx])
{ {
return true; return true;
} }
@ -121,7 +115,7 @@ bool StaticHashTable<T, Key, Hash>::found(const Key& key) const
# ifdef FULLDEBUG # ifdef FULLDEBUG
if (debug) if (debug)
{ {
Pout<< "StaticHashTable<T, Key, Hash>::found(const Key& key) : " Info<< "StaticHashTable<T, Key, Hash>::found(const Key&) : "
<< "Entry " << key << " not found in hash table\n"; << "Entry " << key << " not found in hash table\n";
} }
# endif # endif
@ -131,28 +125,27 @@ bool StaticHashTable<T, Key, Hash>::found(const Key& key) const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
typename StaticHashTable<T, Key, Hash>::iterator typename Foam::StaticHashTable<T, Key, Hash>::iterator
StaticHashTable<T, Key, Hash>::find Foam::StaticHashTable<T, Key, Hash>::find
( (
const Key& key const Key& key
) )
{ {
label ii = Hash()(key, keys_.size()); label hashIdx = Hash()(key, keys_.size());
const List<Key>& localKeys = keys_[hashIdx];
const List<Key>& localKeys = keys_[ii]; forAll(localKeys, elemIdx)
forAll(localKeys, n)
{ {
if (localKeys[n] == key) if (key == localKeys[elemIdx])
{ {
return iterator(*this, ii, n); return iterator(*this, hashIdx, elemIdx);
} }
} }
# ifdef FULLDEBUG # ifdef FULLDEBUG
if (debug) if (debug)
{ {
Pout<< "StaticHashTable<T, Key, Hash>::find(const Key& key) : " Info<< "StaticHashTable<T, Key, Hash>::find(const Key&) : "
<< "Entry " << key << " not found in hash table\n"; << "Entry " << key << " not found in hash table\n";
} }
# endif # endif
@ -162,28 +155,27 @@ StaticHashTable<T, Key, Hash>::find
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
typename StaticHashTable<T, Key, Hash>::const_iterator typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
StaticHashTable<T, Key, Hash>::find Foam::StaticHashTable<T, Key, Hash>::find
( (
const Key& key const Key& key
) const ) const
{ {
label ii = Hash()(key, keys_.size()); label hashIdx = Hash()(key, keys_.size());
const List<Key>& localKeys = keys_[hashIdx];
const List<Key>& localKeys = keys_[ii]; forAll(localKeys, elemIdx)
forAll(localKeys, n)
{ {
if (localKeys[n] == key) if (key == localKeys[elemIdx])
{ {
return const_iterator(*this, ii, n); return const_iterator(*this, hashIdx, elemIdx);
} }
} }
# ifdef FULLDEBUG # ifdef FULLDEBUG
if (debug) if (debug)
{ {
Pout<< "StaticHashTable<T, Key, Hash>::find(const Key& key) const : " Info<< "StaticHashTable<T, Key, Hash>::find(const Key&) const : "
<< "Entry " << key << " not found in hash table\n"; << "Entry " << key << " not found in hash table\n";
} }
# endif # endif
@ -194,10 +186,9 @@ StaticHashTable<T, Key, Hash>::find
// Return the table of contents // Return the table of contents
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
List<Key> StaticHashTable<T, Key, Hash>::toc() const Foam::List<Key> Foam::StaticHashTable<T, Key, Hash>::toc() const
{ {
List<Key> tofc(nElmts_); List<Key> tofc(nElmts_);
label i = 0; label i = 0;
for (const_iterator iter = begin(); iter != end(); ++iter) for (const_iterator iter = begin(); iter != end(); ++iter)
@ -210,57 +201,74 @@ List<Key> StaticHashTable<T, Key, Hash>::toc() const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool StaticHashTable<T, Key, Hash>::insert(const Key& key, const T& newEntry) bool Foam::StaticHashTable<T, Key, Hash>::set
(
const Key& key,
const T& newEntry,
const bool protect
)
{ {
label ii = Hash()(key, keys_.size()); label hashIdx = Hash()(key, keys_.size());
List<Key>& localKeys = keys_[hashIdx];
List<Key>& localKeys = keys_[ii]; label existing = localKeys.size();
forAll(localKeys, elemIdx)
forAll(localKeys, n)
{ {
if (localKeys[n] == key) if (key == localKeys[elemIdx])
{ {
# ifdef FULLDEBUG existing = elemIdx;
if (debug) break;
{
Pout<< "StaticHashTable<T, Key, Hash>::insert"
"(const Key& key, T newEntry) : "
"Cannot insert " << key << " already in hash table\n";
}
# endif
return false;
} }
} }
if (existing == localKeys.size())
{
// not found, append
List<T>& localObjects = objects_[hashIdx];
// Append. localKeys.setSize(existing+1);
List<T>& localObjects = objects_[ii]; localObjects.setSize(existing+1);
label sz = localKeys.size(); localKeys[existing] = key;
localObjects[existing] = newEntry;
localKeys.setSize(sz+1); nElmts_++;
localObjects.setSize(sz+1); }
else if (protect)
localKeys[sz] = key; {
localObjects[sz] = newEntry; // found - but protected from overwriting
// this corresponds to the STL 'insert' convention
nElmts_++; # ifdef FULLDEBUG
if (debug)
{
Info<< "StaticHashTable<T, Key, Hash>::set"
"(const Key& key, T newEntry, true) : "
"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] = newEntry;
}
return true; return true;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool StaticHashTable<T, Key, Hash>::erase(const iterator& it) bool Foam::StaticHashTable<T, Key, Hash>::erase(const iterator& cit)
{ {
if (it != end()) if (cit != end())
{ {
List<Key>& localKeys = keys_[it.hashIndex_]; List<Key>& localKeys = keys_[cit.hashIndex_];
List<T>& localObjects = objects_[it.hashIndex_]; List<T>& localObjects = objects_[cit.hashIndex_];
// Copy down // Copy down
for (label i = it.elementIndex_+1; i < localKeys.size(); i++) for (label i = cit.elementIndex_+1; i < localKeys.size(); i++)
{ {
localKeys[i-1] = localKeys[i]; localKeys[i-1] = localKeys[i];
localObjects[i-1] = localObjects[i]; localObjects[i-1] = localObjects[i];
@ -268,12 +276,39 @@ bool StaticHashTable<T, Key, Hash>::erase(const iterator& it)
localKeys.setSize(localKeys.size()-1); localKeys.setSize(localKeys.size()-1);
localObjects.setSize(localObjects.size()-1); localObjects.setSize(localObjects.size()-1);
// adjust iterator after erase
iterator& it = const_cast<iterator&>(cit);
it.elementIndex_--;
if (it.elementIndex_ < 0)
{
// No previous element in the local list
// Search back for previous non-zero table entry
while (--it.hashIndex_ >= 0 && !objects_[it.hashIndex_].size())
{}
if (it.hashIndex_ >= 0)
{
// The last element in the local list
it.elementIndex_ = objects_[it.hashIndex_].size() - 1;
}
else
{
// No previous found. Mark with special value which is
// - not end()
// - handled by operator++
it.hashIndex_ = -1;
it.elementIndex_ = 0;
}
}
nElmts_--; nElmts_--;
# ifdef FULLDEBUG # ifdef FULLDEBUG
if (debug) if (debug)
{ {
Pout<< "StaticHashTable<T, Key, Hash>::erase(iterator&) : " Info<< "StaticHashTable<T, Key, Hash>::erase(iterator&) : "
<< "hashedEntry removed.\n"; << "hashedEntry removed.\n";
} }
# endif # endif
@ -285,7 +320,7 @@ bool StaticHashTable<T, Key, Hash>::erase(const iterator& it)
# ifdef FULLDEBUG # ifdef FULLDEBUG
if (debug) if (debug)
{ {
Pout<< "StaticHashTable<T, Key, Hash>::erase(iterator&) : " Info<< "StaticHashTable<T, Key, Hash>::erase(iterator&) : "
<< "cannot remove hashedEntry from hash table\n"; << "cannot remove hashedEntry from hash table\n";
} }
# endif # endif
@ -296,7 +331,7 @@ bool StaticHashTable<T, Key, Hash>::erase(const iterator& it)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
bool StaticHashTable<T, Key, Hash>::erase(const Key& key) bool Foam::StaticHashTable<T, Key, Hash>::erase(const Key& key)
{ {
iterator it = find(key); iterator it = find(key);
@ -312,14 +347,14 @@ bool StaticHashTable<T, Key, Hash>::erase(const Key& key)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void StaticHashTable<T, Key, Hash>::resize(const label newSize) void Foam::StaticHashTable<T, Key, Hash>::resize(const label newSize)
{ {
if (newSize == keys_.size()) if (newSize == keys_.size())
{ {
# ifdef FULLDEBUG # ifdef FULLDEBUG
if (debug) if (debug)
{ {
Pout<< "StaticHashTable<T, Key, Hash>::resize(const label) : " Info<< "StaticHashTable<T, Key, Hash>::resize(const label) : "
<< "new table size == old table size\n"; << "new table size == old table size\n";
} }
# endif # endif
@ -353,46 +388,62 @@ void StaticHashTable<T, Key, Hash>::resize(const label newSize)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void StaticHashTable<T, Key, Hash>::clear() void Foam::StaticHashTable<T, Key, Hash>::clear()
{ {
forAll(keys_, ii) forAll(keys_, hashIdx)
{ {
keys_[ii].clear(); keys_[hashIdx].clear();
objects_[ii].clear(); objects_[hashIdx].clear();
} }
nElmts_ = 0;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void StaticHashTable<T, Key, Hash>::transfer(StaticHashTable<T, Key, Hash>& ht) void Foam::StaticHashTable<T, Key, Hash>::clearStorage()
{ {
// Remove my existing elements 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(); clear();
// Copy data from ht // Copy data from ht
keys_.transfer(ht.keys_); keys_.transfer(ht.keys_);
objects_.transfer(ht.objects_); objects_.transfer(ht.objects_);
nElmts_ = ht.nElmts_; nElmts_ = ht.nElmts_;
ht.nElmts_ = 0;
// Adapt end() iterators // Adapt end() iterators
endIter_.hashIndex_ = keys_.size(); endIter_.hashIndex_ = keys_.size();
endConstIter_.hashIndex_ = keys_.size(); endConstIter_.hashIndex_ = keys_.size();
// Clear ht ht.endIter_.hashIndex_ = 0;
ht.nElmts_ = 0; ht.endConstIter_.hashIndex_ = 0;
} }
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
void StaticHashTable<T, Key, Hash>::operator= void Foam::StaticHashTable<T, Key, Hash>::operator=
( (
const StaticHashTable<T, Key, Hash>& ht const StaticHashTable<T, Key, Hash>& rhs
) )
{ {
// Check for assignment to self // Check for assignment to self
if (this == &ht) if (this == &rhs)
{ {
FatalErrorIn FatalErrorIn
( (
@ -402,20 +453,70 @@ void StaticHashTable<T, Key, Hash>::operator=
<< abort(FatalError); << abort(FatalError);
} }
clear();
for (const_iterator iter = ht.begin(); iter != ht.end(); ++iter) // could be zero-sized from a previous transfer()
if (keys_.size() == 0)
{
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.begin(); iter != rhs.end(); ++iter)
{ {
insert(iter.key(), *iter); insert(iter.key(), *iter);
} }
}
// keys_.size() does not change so neither does end() iterator. template<class T, class Key, class Hash>
bool Foam::StaticHashTable<T, Key, Hash>::operator==
(
const StaticHashTable<T, Key, Hash>& rhs
) const
{
// Are all my elements in rhs?
for (const_iterator iter = begin(); iter != end(); ++iter)
{
const_iterator fnd = rhs.find(iter.key());
if (fnd == rhs.end() || fnd() != iter())
{
return false;
}
}
// Are all rhs elements in me?
for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)
{
const_iterator fnd = find(iter.key());
if (fnd == end() || 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));
}
} // End namespace Foam
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //

View File

@ -28,6 +28,7 @@ Class
Description Description
STL conforming hash table. STL conforming hash table.
Note
Uses straight lists as underlying type. Uses straight lists as underlying type.
Is slower to insert than the standard HashTable, but should be more Is slower to insert than the standard HashTable, but should be more
memory efficient and faster to access. memory efficient and faster to access.
@ -55,9 +56,7 @@ namespace Foam
// Forward declaration of friend functions and operators // Forward declaration of friend functions and operators
template<class T> template<class T> class List;
class List;
template<class T, class Key, class Hash> class StaticHashTable; template<class T, class Key, class Hash> class StaticHashTable;
template<class T, class Key, class Hash> Istream& operator>> template<class T, class Key, class Hash> Istream& operator>>
@ -74,14 +73,14 @@ template<class T, class Key, class Hash> Ostream& operator<<
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class StaticHashTableName Declaration Class StaticHashTableName Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
TemplateName(StaticHashTable); TemplateName(StaticHashTable);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class StaticHashTable Declaration Class StaticHashTable Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class T, class Key=word, class Hash=string::hash> template<class T, class Key=word, class Hash=string::hash>
@ -100,6 +99,9 @@ class StaticHashTable
//- The current number of elements in table //- The current number of elements in table
label nElmts_; label nElmts_;
//- Assign a new hashed entry to a possibly already existing key
bool set(const Key&, const T& newElmt, bool protect);
public: public:
@ -147,7 +149,7 @@ public:
//- Construct as copy //- Construct as copy
StaticHashTable(const StaticHashTable<T, Key, Hash>&); StaticHashTable(const StaticHashTable<T, Key, Hash>&);
//- Construct as copy //- Construct by transferring the parameter contents
StaticHashTable(const xfer<StaticHashTable<T, Key, Hash> >&); StaticHashTable(const xfer<StaticHashTable<T, Key, Hash> >&);
// Destructor // Destructor
@ -162,14 +164,14 @@ public:
//- Return number of elements in table. //- Return number of elements in table.
inline label size() const; inline label size() const;
//- Return true if hashedEntry is found in table //- Return true if hashed entry is found in table
bool found(const Key& key) const; bool found(const Key& key) const;
//- Find and return an iterator set at the hashedEntry //- Find and return an iterator set at the hashed entry
// If not found iterator = end() // If not found iterator = end()
iterator find(const Key& key); iterator find(const Key& key);
//- Find and return an const_iterator set at the hashedEntry //- Find and return an const_iterator set at the hashed entry
// If not found iterator = end() // If not found iterator = end()
const_iterator find(const Key& key) const; const_iterator find(const Key& key) const;
@ -179,13 +181,16 @@ public:
// Edit // Edit
//- Insert a new hashedEntry //- Insert a new hashed entry
bool insert(const Key& key, const T& newElmt); bool insert(const Key& key, const T& newElmt);
//- Erase an hashedEntry specified by given iterator //- 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); bool erase(const iterator& it);
//- Erase an hashedEntry specified by given key if in table //- Erase an hashed entry specified by given key if in table
bool erase(const Key& key); bool erase(const Key& key);
//- Resize the hash table for efficiency //- Resize the hash table for efficiency
@ -194,22 +199,38 @@ public:
//- Clear all entries from table //- Clear all entries from table
void clear(); 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 //- Transfer the contents of the argument table into this table
// and annull the argument table. // and annull the argument table.
void transfer(StaticHashTable<T, Key, Hash>&); void transfer(StaticHashTable<T, Key, Hash>&);
//- Transfer the contents to the xfer container
inline xfer<StaticHashTable<T, Key, Hash> > transfer();
// Member Operators // Member Operators
//- Find and return an hashedEntry //- Find and return an hashed entry
inline T& operator[](const Key& key); inline T& operator[](const Key&);
//- Find and return an hashedEntry //- Find and return an hashed entry
inline const T& operator[](const Key& key) const; 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 //- Assignment
void operator=(const StaticHashTable<T, Key, Hash>&); 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 // STL type definitions
@ -245,7 +266,7 @@ public:
// Private data // Private data
//- Reference to the StaticHashTable this is an iterator for //- Reference to the StaticHashTable this is an iterator for
TableRef curStaticHashTable_; TableRef curHashTable_;
//- Current hash index //- Current hash index
label hashIndex_; label hashIndex_;
@ -257,10 +278,10 @@ public:
// Constructors // Constructors
//- Construct from hash table, element and hash index //- Construct from hash table, hash index and element index
inline Iterator inline Iterator
( (
TableRef curStaticHashTable, TableRef curHashTable,
label hashIndex_, label hashIndex_,
label elementIndex_ label elementIndex_
); );

View File

@ -27,34 +27,60 @@ License
#include "error.H" #include "error.H"
#include "IOstreams.H" #include "IOstreams.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline label StaticHashTable<T, Key, Hash>::size() const inline Foam::label Foam::StaticHashTable<T, Key, Hash>::size() const
{ {
return nElmts_; return nElmts_;
} }
template<class T, class Key, class Hash>
inline bool Foam::StaticHashTable<T, Key, Hash>::insert
(
const Key& key,
const T& newEntry
)
{
return set(key, newEntry, true);
}
template<class T, class Key, class Hash>
inline bool Foam::StaticHashTable<T, Key, Hash>::set
(
const Key& key,
const T& newEntry
)
{
return set(key, newEntry, false);
}
template<class T, class Key, class Hash>
inline Foam::xfer<Foam::StaticHashTable<T, Key, Hash> >
Foam::StaticHashTable<T, Key, Hash>::transfer()
{
Foam::xfer<StaticHashTable<T, Key, Hash> > xf;
xf().transfer(*this);
return xf;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline T& StaticHashTable<T, Key, Hash>::operator[](const Key& key) inline T& Foam::StaticHashTable<T, Key, Hash>::operator[](const Key& key)
{ {
iterator iter = find(key); iterator iter = find(key);
if (iter == end()) if (iter == end())
{ {
FatalErrorIn("StaticHashTable<T, Key, Hash>::operator[](const Key&)") FatalErrorIn("StaticHashTable<T, Key, Hash>::operator[](const Key&)")
<< key << " not found in table. Valid entries are " << key << " not found in table. Valid entries: "
<< toc() << toc()
<< exit(FatalError); << exit(FatalError);
} }
@ -62,8 +88,12 @@ inline T& StaticHashTable<T, Key, Hash>::operator[](const Key& key)
return *iter; return *iter;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const T& StaticHashTable<T, Key, Hash>::operator[](const Key& key) const inline const T& Foam::StaticHashTable<T, Key, Hash>::operator[]
(
const Key& key
) const
{ {
const_iterator iter = find(key); const_iterator iter = find(key);
@ -72,7 +102,7 @@ inline const T& StaticHashTable<T, Key, Hash>::operator[](const Key& key) const
FatalErrorIn FatalErrorIn
( (
"StaticHashTable<T, Key, Hash>::operator[](const Key&) const" "StaticHashTable<T, Key, Hash>::operator[](const Key&) const"
) << key << " not found in table. Valid entries are " ) << key << " not found in table. Valid entries: "
<< toc() << toc()
<< exit(FatalError); << exit(FatalError);
} }
@ -81,19 +111,35 @@ inline const T& StaticHashTable<T, Key, Hash>::operator[](const Key& key) const
} }
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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: inline Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::Iterator
Iterator
( (
TableRef curStaticHashTable, TableRef curHashTable,
label hashIndex, label hashIndex,
label elementIndex label elementIndex
) )
: :
curStaticHashTable_(curStaticHashTable), curHashTable_(curHashTable),
hashIndex_(hashIndex), hashIndex_(hashIndex),
elementIndex_(elementIndex) elementIndex_(elementIndex)
{} {}
@ -101,10 +147,12 @@ Iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: inline Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::Iterator
Iterator(const iterator& iter) (
const iterator& iter
)
: :
curStaticHashTable_(iter.curStaticHashTable_), curHashTable_(iter.curHashTable_),
hashIndex_(iter.hashIndex_), hashIndex_(iter.hashIndex_),
elementIndex_(iter.elementIndex_) elementIndex_(iter.elementIndex_)
{} {}
@ -112,8 +160,11 @@ Iterator(const iterator& iter)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline void StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: inline void
operator=(const iterator& iter) Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator=
(
const iterator& iter
)
{ {
this->hashIndex_ = iter.hashIndex_; this->hashIndex_ = iter.hashIndex_;
this->elementIndex_ = iter.elementIndex_; this->elementIndex_ = iter.elementIndex_;
@ -122,16 +173,11 @@ operator=(const iterator& iter)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline bool StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: inline bool
operator==(const iterator& iter) const Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator==
{ (
return hashIndex_ == iter.hashIndex_ && elementIndex_ == iter.elementIndex_; const iterator& iter
} ) const
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::
operator==(const const_iterator& iter) const
{ {
return hashIndex_ == iter.hashIndex_ && elementIndex_ == iter.elementIndex_; return hashIndex_ == iter.hashIndex_ && elementIndex_ == iter.elementIndex_;
} }
@ -139,16 +185,23 @@ operator==(const const_iterator& iter) const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline bool StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: inline bool
operator!=(const iterator& iter) const Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator==
(
const const_iterator& iter
) const
{ {
return !operator==(iter); return hashIndex_ == iter.hashIndex_ && elementIndex_ == iter.elementIndex_;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline bool StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: inline bool
operator!=(const const_iterator& iter) const Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator!=
(
const iterator& iter
) const
{ {
return !operator==(iter); return !operator==(iter);
} }
@ -156,17 +209,29 @@ operator!=(const const_iterator& iter) const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline TRef StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: inline bool
operator*() Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator!=
(
const const_iterator& iter
) const
{ {
return curStaticHashTable_.objects_[hashIndex_][elementIndex_]; return !operator==(iter);
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline TRef StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: inline TRef
operator()() Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator*()
{
return curHashTable_.objects_[hashIndex_][elementIndex_];
}
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*(); return operator*();
} }
@ -175,40 +240,44 @@ operator()()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline inline
typename StaticHashTable<T, Key, Hash>::template Iterator typename Foam::StaticHashTable<T, Key, Hash>::template Iterator
< <
TRef, TRef,
TableRef TableRef
>& >&
StaticHashTable<T, Key, Hash>::Iterator Foam::StaticHashTable<T, Key, Hash>::Iterator
< <
TRef, TRef,
TableRef TableRef
>::operator++() >::operator++()
{ {
const List<T>& localObjects = curStaticHashTable_.objects_[hashIndex_]; // Check for special value from erase. (sets hashIndex to -1)
if (hashIndex_ >= 0)
if (elementIndex_ == localObjects.size()-1)
{ {
elementIndex_ = 0; // Try the next element on the local list
elementIndex_++;
// Find first non-zero entry if (elementIndex_ < curHashTable_.objects_[hashIndex_].size())
for
(
hashIndex_++;
hashIndex_ < curStaticHashTable_.objects_.size();
hashIndex_++
)
{ {
if (curStaticHashTable_.objects_[hashIndex_].size() > 0) return *this;
{
break;
}
} }
} }
else
// Step to the next table entry
elementIndex_ = 0;
while
(
++hashIndex_ < curHashTable_.objects_.size()
&& !curHashTable_.objects_[hashIndex_].size()
)
{}
if (hashIndex_ >= curHashTable_.objects_.size())
{ {
elementIndex_++; // make end iterator
hashIndex_ = curHashTable_.keys_.size();
} }
return *this; return *this;
@ -218,12 +287,12 @@ StaticHashTable<T, Key, Hash>::Iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline inline
typename StaticHashTable<T, Key, Hash>::template Iterator typename Foam::StaticHashTable<T, Key, Hash>::template Iterator
< <
TRef, TRef,
TableRef TableRef
> >
StaticHashTable<T, Key, Hash>::Iterator Foam::StaticHashTable<T, Key, Hash>::Iterator
< <
TRef, TRef,
TableRef TableRef
@ -240,24 +309,23 @@ StaticHashTable<T, Key, Hash>::Iterator
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
template<class TRef, class TableRef> template<class TRef, class TableRef>
inline inline const Key&
const Key& StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>:: Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::key()
key()
{ {
return curStaticHashTable_.keys_[hashIndex_][elementIndex_]; return curHashTable_.keys_[hashIndex_][elementIndex_];
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline typename StaticHashTable<T, Key, Hash>::iterator inline typename Foam::StaticHashTable<T, Key, Hash>::iterator
StaticHashTable<T, Key, Hash>::begin() Foam::StaticHashTable<T, Key, Hash>::begin()
{ {
// Find first non-empty entry // Find first non-empty entry
forAll(keys_, i) forAll(keys_, hashIdx)
{ {
if (keys_[i].size() > 0) if (keys_[hashIdx].size() > 0)
{ {
return iterator(*this, i, 0); return iterator(*this, hashIdx, 0);
} }
} }
@ -273,23 +341,23 @@ StaticHashTable<T, Key, Hash>::begin()
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const typename StaticHashTable<T, Key, Hash>::iterator& inline const typename Foam::StaticHashTable<T, Key, Hash>::iterator&
StaticHashTable<T, Key, Hash>::end() Foam::StaticHashTable<T, Key, Hash>::end()
{ {
return StaticHashTable<T, Key, Hash>::endIter_; return StaticHashTable<T, Key, Hash>::endIter_;
} }
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline typename StaticHashTable<T, Key, Hash>::const_iterator inline typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
StaticHashTable<T, Key, Hash>::begin() const Foam::StaticHashTable<T, Key, Hash>::begin() const
{ {
// Find first non-empty entry // Find first non-empty entry
forAll(keys_, i) forAll(keys_, hashIdx)
{ {
if (keys_[i].size() > 0) if (keys_[hashIdx].size() > 0)
{ {
return const_iterator(*this, i, 0); return const_iterator(*this, hashIdx, 0);
} }
} }
@ -305,8 +373,8 @@ StaticHashTable<T, Key, Hash>::begin() const
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
inline const typename StaticHashTable<T, Key, Hash>::const_iterator& inline const typename Foam::StaticHashTable<T, Key, Hash>::const_iterator&
StaticHashTable<T, Key, Hash>::end() const Foam::StaticHashTable<T, Key, Hash>::end() const
{ {
return StaticHashTable<T, Key, Hash>::endConstIter_; return StaticHashTable<T, Key, Hash>::endConstIter_;
} }
@ -314,6 +382,4 @@ StaticHashTable<T, Key, Hash>::end() const
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* // // ************************************************************************* //

View File

@ -28,16 +28,14 @@ License
#include "Istream.H" #include "Istream.H"
#include "Ostream.H" #include "Ostream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from Istream
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
StaticHashTable<T, Key, Hash>::StaticHashTable(Istream& is, const label size) Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
(
Istream& is,
const label size
)
: :
StaticHashTableName(), StaticHashTableName(),
keys_(size), keys_(size),
@ -62,20 +60,20 @@ StaticHashTable<T, Key, Hash>::StaticHashTable(Istream& is, const label size)
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
Istream& operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L) Foam::Istream& Foam::operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
{ {
is.fatalCheck("operator>>(Istream&, StaticHashTable<T, Key, Hash>&)"); is.fatalCheck("operator>>(Istream&, StaticHashTable<T, Key, Hash>&)");
// Anull list // Anull list
L.clear(); L.clear();
is.fatalCheck("operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)"); is.fatalCheck("operator>>(Istream&, StaticHashTable<T, Key, Hash>&)");
token firstToken(is); token firstToken(is);
is.fatalCheck is.fatalCheck
( (
"operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L) : " "operator>>(Istream&, StaticHashTable<T, Key, Hash>&) : "
"reading first token" "reading first token"
); );
@ -112,7 +110,7 @@ Istream& operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
{ {
FatalIOErrorIn FatalIOErrorIn
( (
"operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)", "operator>>(Istream&, StaticHashTable<T, Key, Hash>&)",
is is
) << "incorrect first token, '(', found " << firstToken.info() ) << "incorrect first token, '(', found " << firstToken.info()
<< exit(FatalIOError); << exit(FatalIOError);
@ -128,7 +126,7 @@ Istream& operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
{ {
FatalIOErrorIn FatalIOErrorIn
( (
"operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)", "operator>>(Istream&, StaticHashTable<T, Key, Hash>&)",
is is
) << "incorrect first token, '(', found " << firstToken.info() ) << "incorrect first token, '(', found " << firstToken.info()
<< exit(FatalIOError); << exit(FatalIOError);
@ -163,7 +161,7 @@ Istream& operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
{ {
FatalIOErrorIn FatalIOErrorIn
( (
"operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)", "operator>>(Istream&, StaticHashTable<T, Key, Hash>&)",
is is
) << "incorrect first token, expected <int> or '(', found " ) << "incorrect first token, expected <int> or '(', found "
<< firstToken.info() << firstToken.info()
@ -177,15 +175,15 @@ Istream& operator>>(Istream& is, StaticHashTable<T, Key, Hash>& L)
template<class T, class Key, class Hash> template<class T, class Key, class Hash>
Ostream& operator<<(Ostream& os, const StaticHashTable<T, Key, Hash>& L) Foam::Ostream& Foam::operator<<
(
Ostream& os,
const StaticHashTable<T, Key, Hash>& L)
{ {
// Write size of StaticHashTable // Write size of HashTable and start contents delimiter
os << nl << L.size(); os << nl << L.size() << nl << token::BEGIN_LIST << nl;
// Write beginning of contents // Write contents
os << nl << token::BEGIN_LIST << nl;
// Write StaticHashTable contents
for for
( (
typename StaticHashTable<T, Key, Hash>::const_iterator iter = L.begin(); typename StaticHashTable<T, Key, Hash>::const_iterator iter = L.begin();
@ -196,7 +194,7 @@ Ostream& operator<<(Ostream& os, const StaticHashTable<T, Key, Hash>& L)
os << iter.key() << token::SPACE << iter() << nl; os << iter.key() << token::SPACE << iter() << nl;
} }
// Write end of contents // Write end of contents delimiter
os << token::END_LIST; os << token::END_LIST;
// Check state of IOstream // Check state of IOstream
@ -206,8 +204,4 @@ Ostream& operator<<(Ostream& os, const StaticHashTable<T, Key, Hash>& L)
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* // // ************************************************************************* //