mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
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:
@ -31,16 +31,11 @@ License
|
||||
#include "List.H"
|
||||
#include "IOstreams.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct given initial table size
|
||||
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(),
|
||||
keys_(size),
|
||||
@ -62,7 +57,7 @@ StaticHashTable<T, Key, Hash>::StaticHashTable(const label size)
|
||||
|
||||
// Construct as copy
|
||||
template<class T, class Key, class Hash>
|
||||
StaticHashTable<T, Key, Hash>::StaticHashTable
|
||||
Foam::StaticHashTable<T, Key, Hash>::StaticHashTable
|
||||
(
|
||||
const StaticHashTable<T, Key, Hash>& ht
|
||||
)
|
||||
@ -78,7 +73,7 @@ StaticHashTable<T, Key, Hash>::StaticHashTable
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
@ -97,22 +92,21 @@ StaticHashTable<T, Key, Hash>::StaticHashTable
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
StaticHashTable<T, Key, Hash>::~StaticHashTable()
|
||||
Foam::StaticHashTable<T, Key, Hash>::~StaticHashTable()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
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, n)
|
||||
forAll(localKeys, elemIdx)
|
||||
{
|
||||
if (localKeys[n] == key)
|
||||
if (key == localKeys[elemIdx])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -121,7 +115,7 @@ bool StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
||||
# ifdef FULLDEBUG
|
||||
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";
|
||||
}
|
||||
# endif
|
||||
@ -131,28 +125,27 @@ bool StaticHashTable<T, Key, Hash>::found(const Key& key) const
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
typename StaticHashTable<T, Key, Hash>::iterator
|
||||
StaticHashTable<T, Key, Hash>::find
|
||||
typename Foam::StaticHashTable<T, Key, Hash>::iterator
|
||||
Foam::StaticHashTable<T, Key, Hash>::find
|
||||
(
|
||||
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, n)
|
||||
forAll(localKeys, elemIdx)
|
||||
{
|
||||
if (localKeys[n] == key)
|
||||
if (key == localKeys[elemIdx])
|
||||
{
|
||||
return iterator(*this, ii, n);
|
||||
return iterator(*this, hashIdx, elemIdx);
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef FULLDEBUG
|
||||
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";
|
||||
}
|
||||
# endif
|
||||
@ -162,28 +155,27 @@ StaticHashTable<T, Key, Hash>::find
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
typename StaticHashTable<T, Key, Hash>::const_iterator
|
||||
StaticHashTable<T, Key, Hash>::find
|
||||
typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
|
||||
Foam::StaticHashTable<T, Key, Hash>::find
|
||||
(
|
||||
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, n)
|
||||
forAll(localKeys, elemIdx)
|
||||
{
|
||||
if (localKeys[n] == key)
|
||||
if (key == localKeys[elemIdx])
|
||||
{
|
||||
return const_iterator(*this, ii, n);
|
||||
return const_iterator(*this, hashIdx, elemIdx);
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef FULLDEBUG
|
||||
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";
|
||||
}
|
||||
# endif
|
||||
@ -194,10 +186,9 @@ StaticHashTable<T, Key, Hash>::find
|
||||
|
||||
// Return the table of contents
|
||||
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_);
|
||||
|
||||
label i = 0;
|
||||
|
||||
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>
|
||||
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];
|
||||
|
||||
forAll(localKeys, n)
|
||||
label existing = localKeys.size();
|
||||
forAll(localKeys, elemIdx)
|
||||
{
|
||||
if (localKeys[n] == key)
|
||||
if (key == localKeys[elemIdx])
|
||||
{
|
||||
# ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "StaticHashTable<T, Key, Hash>::insert"
|
||||
"(const Key& key, T newEntry) : "
|
||||
"Cannot insert " << key << " already in hash table\n";
|
||||
}
|
||||
# endif
|
||||
|
||||
return false;
|
||||
existing = elemIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (existing == localKeys.size())
|
||||
{
|
||||
// not found, append
|
||||
List<T>& localObjects = objects_[hashIdx];
|
||||
|
||||
// Append.
|
||||
List<T>& localObjects = objects_[ii];
|
||||
localKeys.setSize(existing+1);
|
||||
localObjects.setSize(existing+1);
|
||||
|
||||
label sz = localKeys.size();
|
||||
localKeys[existing] = key;
|
||||
localObjects[existing] = newEntry;
|
||||
|
||||
localKeys.setSize(sz+1);
|
||||
localObjects.setSize(sz+1);
|
||||
|
||||
localKeys[sz] = key;
|
||||
localObjects[sz] = newEntry;
|
||||
|
||||
nElmts_++;
|
||||
nElmts_++;
|
||||
}
|
||||
else if (protect)
|
||||
{
|
||||
// found - but protected from overwriting
|
||||
// this corresponds to the STL 'insert' convention
|
||||
# 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;
|
||||
}
|
||||
|
||||
|
||||
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<T>& localObjects = objects_[it.hashIndex_];
|
||||
List<Key>& localKeys = keys_[cit.hashIndex_];
|
||||
List<T>& localObjects = objects_[cit.hashIndex_];
|
||||
|
||||
// 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];
|
||||
localObjects[i-1] = localObjects[i];
|
||||
@ -268,12 +276,39 @@ bool StaticHashTable<T, Key, Hash>::erase(const iterator& it)
|
||||
localKeys.setSize(localKeys.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_--;
|
||||
|
||||
# ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "StaticHashTable<T, Key, Hash>::erase(iterator&) : "
|
||||
Info<< "StaticHashTable<T, Key, Hash>::erase(iterator&) : "
|
||||
<< "hashedEntry removed.\n";
|
||||
}
|
||||
# endif
|
||||
@ -285,7 +320,7 @@ bool StaticHashTable<T, Key, Hash>::erase(const iterator& it)
|
||||
# ifdef FULLDEBUG
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "StaticHashTable<T, Key, Hash>::erase(iterator&) : "
|
||||
Info<< "StaticHashTable<T, Key, Hash>::erase(iterator&) : "
|
||||
<< "cannot remove hashedEntry from hash table\n";
|
||||
}
|
||||
# endif
|
||||
@ -296,7 +331,7 @@ bool StaticHashTable<T, Key, Hash>::erase(const iterator& it)
|
||||
|
||||
|
||||
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);
|
||||
|
||||
@ -312,14 +347,14 @@ bool StaticHashTable<T, Key, Hash>::erase(const Key& key)
|
||||
|
||||
|
||||
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())
|
||||
{
|
||||
# ifdef FULLDEBUG
|
||||
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";
|
||||
}
|
||||
# endif
|
||||
@ -353,46 +388,62 @@ void StaticHashTable<T, Key, Hash>::resize(const label newSize)
|
||||
|
||||
|
||||
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();
|
||||
objects_[ii].clear();
|
||||
keys_[hashIdx].clear();
|
||||
objects_[hashIdx].clear();
|
||||
}
|
||||
|
||||
nElmts_ = 0;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
||||
// 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();
|
||||
|
||||
// Clear ht
|
||||
ht.nElmts_ = 0;
|
||||
ht.endIter_.hashIndex_ = 0;
|
||||
ht.endConstIter_.hashIndex_ = 0;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
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
|
||||
if (this == &ht)
|
||||
if (this == &rhs)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
@ -402,20 +453,70 @@ void StaticHashTable<T, Key, Hash>::operator=
|
||||
<< 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
Reference in New Issue
Block a user