mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Activate the reworked HashTable
- previous draft version was HashTbl - accidentally still had canonicalSize in templated code
This commit is contained in:
@ -61,8 +61,7 @@ $(sha1)/SHA1Digest.C
|
|||||||
|
|
||||||
primitives/random/Random.C
|
primitives/random/Random.C
|
||||||
|
|
||||||
containers/HashTables/HashTbl/HashTblCore.C
|
containers/HashTables/HashTable/HashTableCore.C
|
||||||
containers/HashTables/HashTable/HashTableName.C
|
|
||||||
containers/HashTables/StaticHashTable/StaticHashTableCore.C
|
containers/HashTables/StaticHashTable/StaticHashTableCore.C
|
||||||
containers/Lists/SortableList/ParSortableListName.C
|
containers/Lists/SortableList/ParSortableListName.C
|
||||||
containers/Lists/PackedList/PackedListName.C
|
containers/Lists/PackedList/PackedListName.C
|
||||||
|
|||||||
@ -30,44 +30,15 @@ License
|
|||||||
#include "HashTable.H"
|
#include "HashTable.H"
|
||||||
#include "List.H"
|
#include "List.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::label Foam::HashTable<T, Key, Hash>::canonicalSize(const label size)
|
|
||||||
{
|
|
||||||
if (size < 1)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// enforce power of two
|
|
||||||
unsigned int goodSize = size;
|
|
||||||
|
|
||||||
if (goodSize & (goodSize - 1))
|
|
||||||
{
|
|
||||||
// brute-force is fast enough
|
|
||||||
goodSize = 1;
|
|
||||||
while (goodSize < unsigned(size))
|
|
||||||
{
|
|
||||||
goodSize <<= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return goodSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
Foam::HashTable<T, Key, Hash>::HashTable(const label size)
|
Foam::HashTable<T, Key, Hash>::HashTable(const label size)
|
||||||
:
|
:
|
||||||
HashTableName(),
|
HashTableCore(),
|
||||||
nElmts_(0),
|
nElmts_(0),
|
||||||
tableSize_(canonicalSize(size)),
|
tableSize_(HashTableCore::canonicalSize(size)),
|
||||||
table_(NULL),
|
table_(NULL)
|
||||||
endIter_(*this, NULL, 0),
|
|
||||||
endConstIter_(*this, NULL, 0)
|
|
||||||
{
|
{
|
||||||
if (tableSize_)
|
if (tableSize_)
|
||||||
{
|
{
|
||||||
@ -84,12 +55,10 @@ Foam::HashTable<T, Key, Hash>::HashTable(const label size)
|
|||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
|
Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
|
||||||
:
|
:
|
||||||
HashTableName(),
|
HashTableCore(),
|
||||||
nElmts_(0),
|
nElmts_(0),
|
||||||
tableSize_(ht.tableSize_),
|
tableSize_(ht.tableSize_),
|
||||||
table_(NULL),
|
table_(NULL)
|
||||||
endIter_(*this, NULL, 0),
|
|
||||||
endConstIter_(*this, NULL, 0)
|
|
||||||
{
|
{
|
||||||
if (tableSize_)
|
if (tableSize_)
|
||||||
{
|
{
|
||||||
@ -113,12 +82,10 @@ Foam::HashTable<T, Key, Hash>::HashTable
|
|||||||
const Xfer<HashTable<T, Key, Hash> >& ht
|
const Xfer<HashTable<T, Key, Hash> >& ht
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
HashTableName(),
|
HashTableCore(),
|
||||||
nElmts_(0),
|
nElmts_(0),
|
||||||
tableSize_(0),
|
tableSize_(0),
|
||||||
table_(NULL),
|
table_(NULL)
|
||||||
endIter_(*this, NULL, 0),
|
|
||||||
endConstIter_(*this, NULL, 0)
|
|
||||||
{
|
{
|
||||||
transfer(ht());
|
transfer(ht());
|
||||||
}
|
}
|
||||||
@ -182,7 +149,7 @@ Foam::HashTable<T, Key, Hash>::find
|
|||||||
{
|
{
|
||||||
if (key == ep->key_)
|
if (key == ep->key_)
|
||||||
{
|
{
|
||||||
return iterator(*this, ep, hashIdx);
|
return iterator(this, ep, hashIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,7 +162,7 @@ Foam::HashTable<T, Key, Hash>::find
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
return end();
|
return iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -214,7 +181,7 @@ Foam::HashTable<T, Key, Hash>::find
|
|||||||
{
|
{
|
||||||
if (key == ep->key_)
|
if (key == ep->key_)
|
||||||
{
|
{
|
||||||
return const_iterator(*this, ep, hashIdx);
|
return const_iterator(this, ep, hashIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,32 +194,32 @@ Foam::HashTable<T, Key, Hash>::find
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
return cend();
|
return const_iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
|
Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
|
||||||
{
|
{
|
||||||
List<Key> tofc(nElmts_);
|
List<Key> keys(nElmts_);
|
||||||
label i = 0;
|
label keyI = 0;
|
||||||
|
|
||||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||||
{
|
{
|
||||||
tofc[i++] = iter.key();
|
keys[keyI++] = iter.key();
|
||||||
}
|
}
|
||||||
|
|
||||||
return tofc;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
Foam::List<Key> Foam::HashTable<T, Key, Hash>::sortedToc() const
|
Foam::List<Key> Foam::HashTable<T, Key, Hash>::sortedToc() const
|
||||||
{
|
{
|
||||||
List<Key> sortedList = this->toc();
|
List<Key> sortedLst = this->toc();
|
||||||
sort(sortedList);
|
sort(sortedLst);
|
||||||
|
|
||||||
return sortedList;
|
return sortedLst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -290,7 +257,7 @@ bool Foam::HashTable<T, Key, Hash>::set
|
|||||||
table_[hashIdx] = new hashedEntry(key, table_[hashIdx], newEntry);
|
table_[hashIdx] = new hashedEntry(key, table_[hashIdx], newEntry);
|
||||||
nElmts_++;
|
nElmts_++;
|
||||||
|
|
||||||
if (double(nElmts_)/tableSize_ > 0.8)
|
if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize)
|
||||||
{
|
{
|
||||||
# ifdef FULLDEBUG
|
# ifdef FULLDEBUG
|
||||||
if (debug)
|
if (debug)
|
||||||
@ -342,18 +309,22 @@ bool Foam::HashTable<T, Key, Hash>::set
|
|||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
bool Foam::HashTable<T, Key, Hash>::erase(const iterator& cit)
|
bool Foam::HashTable<T, Key, Hash>::iteratorBase::erase()
|
||||||
{
|
{
|
||||||
if (cit.elmtPtr_) // note: endIter_ also has 0 elmtPtr_
|
// note: entryPtr_ is NULL for end(), so this catches that too
|
||||||
|
if (entryPtr_)
|
||||||
{
|
{
|
||||||
iterator& it = const_cast<iterator&>(cit);
|
// Search element before entryPtr_
|
||||||
|
|
||||||
// Search element before elmtPtr_
|
|
||||||
hashedEntry* prev = 0;
|
hashedEntry* prev = 0;
|
||||||
|
|
||||||
for (hashedEntry* ep = table_[it.hashIndex_]; ep; ep = ep->next_)
|
for
|
||||||
|
(
|
||||||
|
hashedEntry* ep = hashTable_->table_[hashIndex_];
|
||||||
|
ep;
|
||||||
|
ep = ep->next_
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (ep == it.elmtPtr_)
|
if (ep == entryPtr_)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -362,98 +333,76 @@ bool Foam::HashTable<T, Key, Hash>::erase(const iterator& cit)
|
|||||||
|
|
||||||
if (prev)
|
if (prev)
|
||||||
{
|
{
|
||||||
// Have element before elmtPtr
|
// has an element before entryPtr - reposition to there
|
||||||
prev->next_ = it.elmtPtr_->next_;
|
prev->next_ = entryPtr_->next_;
|
||||||
delete it.elmtPtr_;
|
delete entryPtr_;
|
||||||
it.elmtPtr_ = prev;
|
entryPtr_ = prev;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// elmtPtr is first element on SLList
|
// entryPtr was first element on SLList
|
||||||
table_[it.hashIndex_] = it.elmtPtr_->next_;
|
hashTable_->table_[hashIndex_] = entryPtr_->next_;
|
||||||
delete it.elmtPtr_;
|
delete entryPtr_;
|
||||||
|
|
||||||
// Search back for previous non-zero table entry
|
// assign any non-NULL pointer value so it doesn't look
|
||||||
while (--it.hashIndex_ >= 0 && !table_[it.hashIndex_])
|
// like end()/cend()
|
||||||
{}
|
entryPtr_ = reinterpret_cast<hashedEntry*>(this);
|
||||||
|
|
||||||
if (it.hashIndex_ >= 0)
|
// Mark with special hashIndex value to signal it has been rewound.
|
||||||
{
|
// The next increment will bring it back to the present location.
|
||||||
// In table entry search for last element
|
//
|
||||||
it.elmtPtr_ = table_[it.hashIndex_];
|
// From the current position 'curPos', we wish to continue at
|
||||||
|
// prevPos='curPos-1', which we mark as markPos='-curPos-1'.
|
||||||
while (it.elmtPtr_ && it.elmtPtr_->next_)
|
// The negative lets us notice it is special, the extra '-1'
|
||||||
{
|
// is needed to avoid ambiguity for position '0'.
|
||||||
it.elmtPtr_ = it.elmtPtr_->next_;
|
// To retrieve prevPos, we would later use '-(markPos+1) - 1'
|
||||||
}
|
hashIndex_ = -hashIndex_ - 1;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No previous found. Mark with special value which is
|
|
||||||
// - not end()/cend()
|
|
||||||
// - handled by operator++
|
|
||||||
it.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
|
||||||
it.hashIndex_ = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nElmts_--;
|
hashTable_->nElmts_--;
|
||||||
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTable<T, Key, Hash>::erase(iterator&) : "
|
|
||||||
<< "hashedEntry " << it.elmtPtr_->key_ << " removed.\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTable<T, Key, Hash>::erase(iterator&) : "
|
|
||||||
<< "cannot remove hashedEntry from hash table\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE:
|
||||||
|
// We use (const iterator&) here, but manipulate its contents anyhow.
|
||||||
|
// The parameter should be (iterator&), but then the compiler doesn't find
|
||||||
|
// it correctly and tries to call as (iterator) instead.
|
||||||
|
//
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
bool Foam::HashTable<T, Key, Hash>::erase(const iterator& iter)
|
||||||
|
{
|
||||||
|
// adjust iterator after erase
|
||||||
|
return const_cast<iterator&>(iter).erase();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
|
bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
|
||||||
{
|
{
|
||||||
iterator fnd = find(key);
|
return erase(find(key));
|
||||||
|
|
||||||
if (fnd != end())
|
|
||||||
{
|
|
||||||
return erase(fnd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
Foam::label Foam::HashTable<T, Key, Hash>::erase(const UList<Key>& keys)
|
Foam::label Foam::HashTable<T, Key, Hash>::erase(const UList<Key>& keys)
|
||||||
{
|
{
|
||||||
|
const label nTotal = nElmts_;
|
||||||
label count = 0;
|
label count = 0;
|
||||||
|
|
||||||
// Remove listed keys from this table
|
// Remove listed keys from this table - terminates early if possible
|
||||||
if (this->size())
|
for (label keyI = 0; count < nTotal && keyI < keys.size(); ++keyI)
|
||||||
{
|
{
|
||||||
forAll(keys, keyI)
|
if (erase(keys[keyI]))
|
||||||
{
|
{
|
||||||
if (erase(keys[keyI]))
|
count++;
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,24 +411,21 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase(const UList<Key>& keys)
|
|||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
template<class AnyType>
|
template<class AnyType, class AnyHash>
|
||||||
Foam::label Foam::HashTable<T, Key, Hash>::erase
|
Foam::label Foam::HashTable<T, Key, Hash>::erase
|
||||||
(
|
(
|
||||||
const HashTable<AnyType, Key, Hash>& rhs
|
const HashTable<AnyType, Key, AnyHash>& rhs
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
label count = 0;
|
label count = 0;
|
||||||
|
|
||||||
// Remove rhs elements from this table
|
// Remove rhs keys from this table - terminates early if possible
|
||||||
if (this->size())
|
// Could optimize depending on which hash is smaller ...
|
||||||
|
for (iterator iter = begin(); iter != end(); ++iter)
|
||||||
{
|
{
|
||||||
// NOTE: could further optimize depending on which hash is smaller
|
if (rhs.found(iter.key()) && erase(iter))
|
||||||
for (iterator iter = begin(); iter != end(); ++iter)
|
|
||||||
{
|
{
|
||||||
if (rhs.found(iter.key()) && erase(iter))
|
count++;
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +436,7 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase
|
|||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||||
{
|
{
|
||||||
label newSize = canonicalSize(sz);
|
label newSize = HashTableCore::canonicalSize(sz);
|
||||||
|
|
||||||
if (newSize == tableSize_)
|
if (newSize == tableSize_)
|
||||||
{
|
{
|
||||||
@ -505,22 +451,22 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HashTable<T, Key, Hash>* newTable = new HashTable<T, Key, Hash>(newSize);
|
HashTable<T, Key, Hash>* tmpTable = new HashTable<T, Key, Hash>(newSize);
|
||||||
|
|
||||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||||
{
|
{
|
||||||
newTable->insert(iter.key(), *iter);
|
tmpTable->insert(iter.key(), *iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
label oldTableSize = tableSize_;
|
label oldSize = tableSize_;
|
||||||
tableSize_ = newTable->tableSize_;
|
tableSize_ = tmpTable->tableSize_;
|
||||||
newTable->tableSize_ = oldTableSize;
|
tmpTable->tableSize_ = oldSize;
|
||||||
|
|
||||||
hashedEntry** oldTable = table_;
|
hashedEntry** oldTable = table_;
|
||||||
table_ = newTable->table_;
|
table_ = tmpTable->table_;
|
||||||
newTable->table_ = oldTable;
|
tmpTable->table_ = oldTable;
|
||||||
|
|
||||||
delete newTable;
|
delete tmpTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -556,6 +502,19 @@ void Foam::HashTable<T, Key, Hash>::clearStorage()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
void Foam::HashTable<T, Key, Hash>::shrink()
|
||||||
|
{
|
||||||
|
const label newSize = HashTableCore::canonicalSize(nElmts_);
|
||||||
|
|
||||||
|
if (newSize < tableSize_)
|
||||||
|
{
|
||||||
|
// avoid having the table disappear on us
|
||||||
|
resize(newSize ? newSize : 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
void Foam::HashTable<T, Key, Hash>::transfer(HashTable<T, Key, Hash>& ht)
|
void Foam::HashTable<T, Key, Hash>::transfer(HashTable<T, Key, Hash>& ht)
|
||||||
{
|
{
|
||||||
@ -619,18 +578,12 @@ bool Foam::HashTable<T, Key, Hash>::operator==
|
|||||||
const HashTable<T, Key, Hash>& rhs
|
const HashTable<T, Key, Hash>& rhs
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Are all my elements in rhs?
|
// sizes (number of keys) must match
|
||||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
if (size() != rhs.size())
|
||||||
{
|
{
|
||||||
const_iterator fnd = rhs.find(iter.key());
|
return false;
|
||||||
|
|
||||||
if (fnd == rhs.cend() || fnd() != iter())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are all rhs elements in me?
|
|
||||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||||
{
|
{
|
||||||
const_iterator fnd = find(iter.key());
|
const_iterator fnd = find(iter.key());
|
||||||
@ -640,6 +593,7 @@ bool Foam::HashTable<T, Key, Hash>::operator==
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -71,23 +71,60 @@ Ostream& operator<<(Ostream&, const HashTable<T, Key, Hash>&);
|
|||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class HashTableName Declaration
|
Class HashTableCore Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TemplateName(HashTable);
|
//- Template-invariant bits for HashTable
|
||||||
|
struct HashTableCore
|
||||||
|
{
|
||||||
|
//- Return a canonical (power-of-two) size
|
||||||
|
static label canonicalSize(const label);
|
||||||
|
|
||||||
|
//- Maximum allowable table size
|
||||||
|
static const label maxTableSize;
|
||||||
|
|
||||||
|
//- Construct null
|
||||||
|
HashTableCore()
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Define template name and debug
|
||||||
|
ClassName("HashTable");
|
||||||
|
|
||||||
|
//- A zero-sized end iterator
|
||||||
|
struct iteratorEnd
|
||||||
|
{
|
||||||
|
//- Construct null
|
||||||
|
iteratorEnd()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
//- iteratorEnd set to beyond the end of any HashTable
|
||||||
|
inline static iteratorEnd cend()
|
||||||
|
{
|
||||||
|
return iteratorEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- iteratorEnd set to beyond the end of any HashTable
|
||||||
|
inline static iteratorEnd end()
|
||||||
|
{
|
||||||
|
return iteratorEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class HashTable Declaration
|
Class HashTable Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
template<class T, class Key=word, class Hash=string::hash>
|
template<class T, class Key=word, class Hash=string::hash>
|
||||||
class HashTable
|
class HashTable
|
||||||
:
|
:
|
||||||
public HashTableName
|
public HashTableCore
|
||||||
{
|
{
|
||||||
// Private data type for table entries
|
// Private data type for table entries
|
||||||
|
|
||||||
|
//- Structure to hold a hashed entry with SLList for collisions
|
||||||
struct hashedEntry
|
struct hashedEntry
|
||||||
{
|
{
|
||||||
//- The lookup key
|
//- The lookup key
|
||||||
@ -99,18 +136,15 @@ class HashTable
|
|||||||
//- The data object
|
//- The data object
|
||||||
T obj_;
|
T obj_;
|
||||||
|
|
||||||
//- Constructors
|
//- Construct from key, next pointer and object
|
||||||
|
inline hashedEntry(const Key&, hashedEntry* next, const T&);
|
||||||
|
|
||||||
//- Construct given key, next pointer and object
|
private:
|
||||||
inline hashedEntry
|
//- Disallow default bitwise copy construct
|
||||||
(
|
hashedEntry(const hashedEntry&);
|
||||||
const Key&,
|
|
||||||
hashedEntry* next,
|
|
||||||
const T& newEntry
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Dissallow construction as copy
|
//- Disallow default bitwise assignment
|
||||||
hashedEntry(const hashedEntry&);
|
void operator=(const hashedEntry&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -119,7 +153,7 @@ class HashTable
|
|||||||
//- The current number of elements in table
|
//- The current number of elements in table
|
||||||
label nElmts_;
|
label nElmts_;
|
||||||
|
|
||||||
//- Number of primary entries allocated in table (not necessarily used)
|
//- Number of primary entries allocated in table
|
||||||
label tableSize_;
|
label tableSize_;
|
||||||
|
|
||||||
//- The table of primary entries
|
//- The table of primary entries
|
||||||
@ -140,17 +174,23 @@ class HashTable
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Forward declaration of iterators
|
||||||
|
|
||||||
|
class iteratorBase;
|
||||||
|
class iterator;
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
//- Declare friendship with the HashPtrTable class
|
//- Declare friendship with the HashPtrTable class
|
||||||
template<class T2, class Key2, class Hash2>
|
template<class T2, class Key2, class Hash2>
|
||||||
friend class HashPtrTable;
|
friend class HashPtrTable;
|
||||||
|
|
||||||
|
//- Declare friendship with the iteratorBase
|
||||||
|
friend class iteratorBase;
|
||||||
|
|
||||||
// Forward declaration of STL iterators
|
//- Declare friendship with the iterator
|
||||||
|
|
||||||
class iterator;
|
|
||||||
friend class iterator;
|
friend class iterator;
|
||||||
|
|
||||||
class const_iterator;
|
//- Declare friendship with the const_iterator
|
||||||
friend class const_iterator;
|
friend class const_iterator;
|
||||||
|
|
||||||
|
|
||||||
@ -178,7 +218,10 @@ public:
|
|||||||
|
|
||||||
// Access
|
// Access
|
||||||
|
|
||||||
//- Return number of elements in table.
|
//- The size of the underlying table
|
||||||
|
inline label capacity() const;
|
||||||
|
|
||||||
|
//- Return number of elements in table
|
||||||
inline label size() const;
|
inline label size() const;
|
||||||
|
|
||||||
//- Return true if the hash table is empty
|
//- Return true if the hash table is empty
|
||||||
@ -212,10 +255,11 @@ public:
|
|||||||
//- Assign a new hashedEntry, overwriting existing entries
|
//- Assign a new hashedEntry, overwriting existing entries
|
||||||
inline bool set(const Key&, const T& newElmt);
|
inline bool set(const Key&, const T& newElmt);
|
||||||
|
|
||||||
//- Erase an hashedEntry specified by given iterator
|
//- Erase a hashedEntry specified by given iterator
|
||||||
|
// This invalidates the iterator until the next operator++
|
||||||
bool erase(const iterator&);
|
bool erase(const iterator&);
|
||||||
|
|
||||||
//- Erase an hashedEntry specified by given key if in table
|
//- Erase a hashedEntry specified by the given key
|
||||||
bool erase(const Key&);
|
bool erase(const Key&);
|
||||||
|
|
||||||
//- Remove entries given by the listed keys from this HashTable
|
//- Remove entries given by the listed keys from this HashTable
|
||||||
@ -224,10 +268,10 @@ public:
|
|||||||
|
|
||||||
//- Remove entries given by the given keys from this HashTable
|
//- Remove entries given by the given keys from this HashTable
|
||||||
// Return the number of elements removed.
|
// Return the number of elements removed.
|
||||||
// The parameter HashTable needs the same type of keys, but
|
// The parameter HashTable needs the same type of key, but the
|
||||||
// but the type of values held is arbitrary.
|
// type of values held and the hashing function are arbitrary.
|
||||||
template<class AnyType>
|
template<class AnyType, class AnyHash>
|
||||||
label erase(const HashTable<AnyType, Key, Hash>&);
|
label erase(const HashTable<AnyType, Key, AnyHash>&);
|
||||||
|
|
||||||
//- Resize the hash table for efficiency
|
//- Resize the hash table for efficiency
|
||||||
void resize(const label newSize);
|
void resize(const label newSize);
|
||||||
@ -239,31 +283,33 @@ public:
|
|||||||
// Equivalent to clear() followed by resize(0)
|
// Equivalent to clear() followed by resize(0)
|
||||||
void clearStorage();
|
void clearStorage();
|
||||||
|
|
||||||
|
//- Shrink the allocated table to approx. twice number of elements
|
||||||
|
void shrink();
|
||||||
|
|
||||||
//- 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(HashTable<T, Key, Hash>&);
|
void transfer(HashTable<T, Key, Hash>&);
|
||||||
|
|
||||||
//- Transfer contents to the Xfer container
|
//- Transfer contents to the Xfer container
|
||||||
inline Xfer<HashTable<T, Key, Hash> > xfer();
|
inline Xfer< HashTable<T, Key, Hash> > xfer();
|
||||||
|
|
||||||
|
|
||||||
// Member Operators
|
// Member Operators
|
||||||
|
|
||||||
//- Find and return an hashedEntry
|
//- Find and return a hashedEntry
|
||||||
inline T& operator[](const Key&);
|
inline T& operator[](const Key&);
|
||||||
|
|
||||||
//- Find and return an hashedEntry
|
//- Find and return a hashedEntry
|
||||||
inline const T& operator[](const Key&) const;
|
inline const T& operator[](const Key&) const;
|
||||||
|
|
||||||
//- Find and return an hashedEntry, create it null if not present.
|
//- Find and return a hashedEntry, create it null if not present
|
||||||
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 hash tables are equal if all contents of first are
|
//- Equality. Hash tables are equal if the keys and values are equal.
|
||||||
// also in second and vice versa. So does not depend on table size or
|
// Independent of table storage size and table order.
|
||||||
// order!
|
|
||||||
bool operator==(const HashTable<T, Key, Hash>&) const;
|
bool operator==(const HashTable<T, Key, Hash>&) const;
|
||||||
|
|
||||||
//- The opposite of the equality operation. Takes linear time.
|
//- The opposite of the equality operation. Takes linear time.
|
||||||
@ -289,134 +335,193 @@ public:
|
|||||||
typedef label size_type;
|
typedef label size_type;
|
||||||
|
|
||||||
|
|
||||||
// STL iterator
|
// Iterators and helpers
|
||||||
|
|
||||||
//- An STL-conforming iterator
|
//- The iterator base for HashTable
|
||||||
class iterator
|
// Note: data and functions are protected, to allow reuse by iterator
|
||||||
|
// and prevent most external usage.
|
||||||
|
// iterator and const_iterator have the same size, allowing
|
||||||
|
// us to reinterpret_cast between them (if desired)
|
||||||
|
class iteratorBase
|
||||||
{
|
{
|
||||||
friend class HashTable;
|
// Private Data
|
||||||
friend class const_iterator;
|
|
||||||
|
|
||||||
// Private data
|
//- Pointer to the HashTable for which this is an iterator
|
||||||
|
// This also lets us use the default bitwise copy/assignment
|
||||||
//- Reference to the HashTable this is an iterator for
|
HashTable<T, Key, Hash>* hashTable_;
|
||||||
HashTable<T, Key, Hash>& hashTable_;
|
|
||||||
|
|
||||||
//- Current element
|
//- Current element
|
||||||
hashedEntry* elmtPtr_;
|
hashedEntry* entryPtr_;
|
||||||
|
|
||||||
//- Current hash index
|
//- Current hash index
|
||||||
label hashIndex_;
|
label hashIndex_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct null - equivalent to an 'end' position
|
||||||
|
inline iteratorBase();
|
||||||
|
|
||||||
|
//- Construct from hash table, moving to its 'begin' position
|
||||||
|
inline explicit iteratorBase
|
||||||
|
(
|
||||||
|
const HashTable<T, Key, Hash>* curHashTable
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from hash table, element and hash index
|
||||||
|
inline explicit iteratorBase
|
||||||
|
(
|
||||||
|
const HashTable<T, Key, Hash>* curHashTable,
|
||||||
|
const hashedEntry* elmt,
|
||||||
|
const label hashIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Increment to the next position
|
||||||
|
inline void increment();
|
||||||
|
|
||||||
|
//- Erase the HashTable element at the current position
|
||||||
|
bool erase();
|
||||||
|
|
||||||
|
//- Return non-const access to referenced object
|
||||||
|
inline T& object();
|
||||||
|
|
||||||
|
//- Return const access to referenced object
|
||||||
|
inline const T& cobject() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Member operators
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- Return the Key corresponding to the iterator
|
||||||
|
inline const Key& key() const;
|
||||||
|
|
||||||
|
//- Compare hashedEntry element pointers
|
||||||
|
inline bool operator==(const iteratorBase&) const;
|
||||||
|
inline bool operator!=(const iteratorBase&) const;
|
||||||
|
|
||||||
|
//- Compare hashedEntry to iteratorEnd pointers
|
||||||
|
inline bool operator==(const iteratorEnd& unused) const;
|
||||||
|
inline bool operator!=(const iteratorEnd& unused) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//- An STL-conforming iterator
|
||||||
|
class iterator
|
||||||
|
:
|
||||||
|
public iteratorBase
|
||||||
|
{
|
||||||
|
friend class HashTable;
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Construct from hash table, moving to its 'begin' position
|
||||||
|
inline explicit iterator
|
||||||
|
(
|
||||||
|
HashTable<T, Key, Hash>* curHashTable
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from hash table, element and hash index
|
||||||
|
inline explicit iterator
|
||||||
|
(
|
||||||
|
HashTable<T, Key, Hash>* curHashTable,
|
||||||
|
hashedEntry* elmt,
|
||||||
|
const label hashIndex
|
||||||
|
);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from hash table, element and hash index
|
//- Construct null (end iterator)
|
||||||
inline iterator
|
inline iterator();
|
||||||
(
|
|
||||||
HashTable<T, Key, Hash>& curHashTable,
|
//- Construct end iterator
|
||||||
hashedEntry* elmt,
|
inline iterator(const iteratorEnd& unused);
|
||||||
label hashIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
// Member operators
|
// Member operators
|
||||||
|
|
||||||
inline void operator=(const iterator&);
|
//- Conversion to a const_iterator
|
||||||
|
inline operator const_iterator() const;
|
||||||
|
|
||||||
inline bool operator==(const iterator&) const;
|
// Access
|
||||||
inline bool operator!=(const iterator&) const;
|
|
||||||
|
|
||||||
inline bool operator==(const const_iterator&) const;
|
|
||||||
inline bool operator!=(const const_iterator&) const;
|
|
||||||
|
|
||||||
|
//- Return referenced hash value
|
||||||
inline T& operator*();
|
inline T& operator*();
|
||||||
inline T& operator()();
|
inline T& operator()();
|
||||||
|
|
||||||
|
//- Return referenced hash value
|
||||||
inline const T& operator*() const;
|
inline const T& operator*() const;
|
||||||
inline const T& operator()() const;
|
inline const T& operator()() const;
|
||||||
|
|
||||||
inline iterator& operator++();
|
inline iterator& operator++();
|
||||||
inline iterator operator++(int);
|
inline iterator operator++(int);
|
||||||
|
|
||||||
inline const Key& key() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//- iterator set to the begining of the HashTable
|
//- iterator set to the begining of the HashTable
|
||||||
inline iterator begin();
|
inline iterator begin();
|
||||||
|
|
||||||
//- iterator set to beyond the end of the HashTable
|
|
||||||
inline const iterator& end();
|
|
||||||
|
|
||||||
|
|
||||||
// STL const_iterator
|
// STL const_iterator
|
||||||
|
|
||||||
//- An STL-conforming const_iterator
|
//- An STL-conforming const_iterator
|
||||||
class const_iterator
|
class const_iterator
|
||||||
|
:
|
||||||
|
public iteratorBase
|
||||||
{
|
{
|
||||||
friend class iterator;
|
friend class HashTable;
|
||||||
|
|
||||||
// Private data
|
// Private Member Functions
|
||||||
|
|
||||||
//- Reference to the HashTable this is an iterator for
|
//- Construct from hash table, moving to its 'begin' position
|
||||||
const HashTable<T, Key, Hash>& hashTable_;
|
inline explicit const_iterator
|
||||||
|
(
|
||||||
//- Current element
|
const HashTable<T, Key, Hash>* curHashTable
|
||||||
const hashedEntry* elmtPtr_;
|
);
|
||||||
|
|
||||||
//- Current hash index
|
|
||||||
label hashIndex_;
|
|
||||||
|
|
||||||
|
//- Construct from hash table, element and hash index
|
||||||
|
inline explicit const_iterator
|
||||||
|
(
|
||||||
|
const HashTable<T, Key, Hash>* curHashTable,
|
||||||
|
const hashedEntry* elmt,
|
||||||
|
const label hashIndex
|
||||||
|
);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from hash table, element and hash index
|
//- Construct null (end iterator)
|
||||||
inline const_iterator
|
inline const_iterator();
|
||||||
(
|
|
||||||
const HashTable<T, Key, Hash>& curHashTable,
|
|
||||||
const hashedEntry* elmt,
|
|
||||||
label hashIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Construct from the non-const iterator
|
|
||||||
inline const_iterator(const iterator&);
|
|
||||||
|
|
||||||
|
//- Construct end iterator
|
||||||
|
inline const_iterator(const iteratorEnd& unused);
|
||||||
|
|
||||||
// Member operators
|
// Member operators
|
||||||
|
|
||||||
inline void operator=(const const_iterator&);
|
// Access
|
||||||
|
|
||||||
inline bool operator==(const const_iterator&) const;
|
|
||||||
inline bool operator!=(const const_iterator&) const;
|
|
||||||
|
|
||||||
inline bool operator==(const iterator&) const;
|
|
||||||
inline bool operator!=(const iterator&) const;
|
|
||||||
|
|
||||||
|
//- Return referenced hash value
|
||||||
inline const T& operator*() const;
|
inline const T& operator*() const;
|
||||||
inline const T& operator()() const;
|
inline const T& operator()() const;
|
||||||
|
|
||||||
inline const_iterator& operator++();
|
inline const_iterator& operator++();
|
||||||
inline const_iterator operator++(int);
|
inline const_iterator operator++(int);
|
||||||
|
|
||||||
inline const Key& key() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//- const_iterator set to the beginning of the HashTable
|
//- const_iterator set to the beginning of the HashTable
|
||||||
inline const_iterator cbegin() const;
|
inline const_iterator cbegin() const;
|
||||||
|
|
||||||
//- const_iterator set to beyond the end of the HashTable
|
|
||||||
inline const const_iterator& cend() const;
|
|
||||||
|
|
||||||
//- const_iterator set to the beginning of the HashTable
|
//- const_iterator set to the beginning of the HashTable
|
||||||
inline const_iterator begin() const;
|
inline const_iterator begin() const;
|
||||||
|
|
||||||
//- const_iterator set to beyond the end of the HashTable
|
|
||||||
inline const const_iterator& end() const;
|
|
||||||
|
|
||||||
|
|
||||||
// IOstream Operator
|
// IOstream Operator
|
||||||
|
|
||||||
@ -432,14 +537,6 @@ public:
|
|||||||
const HashTable<T, Key, Hash>&
|
const HashTable<T, Key, Hash>&
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
//- iterator returned by end()
|
|
||||||
iterator endIter_;
|
|
||||||
|
|
||||||
//- const_iterator returned by end()
|
|
||||||
const_iterator endConstIter_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -24,18 +24,44 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "HashTbl.H"
|
#include "HashTable.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
defineTypeNameAndDebug(Foam::HashTblCore, 0);
|
defineTypeNameAndDebug(Foam::HashTableCore, 0);
|
||||||
|
|
||||||
const Foam::label Foam::HashTblCore::maxTableSize
|
const Foam::label Foam::HashTableCore::maxTableSize
|
||||||
(
|
(
|
||||||
Foam::HashTblCore::canonicalSize
|
Foam::HashTableCore::canonicalSize
|
||||||
(
|
(
|
||||||
Foam::labelMax/2
|
Foam::labelMax/2
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::label Foam::HashTableCore::canonicalSize(const label size)
|
||||||
|
{
|
||||||
|
if (size < 1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enforce power of two
|
||||||
|
unsigned int goodSize = size;
|
||||||
|
|
||||||
|
if (goodSize & (goodSize - 1))
|
||||||
|
{
|
||||||
|
// brute-force is fast enough
|
||||||
|
goodSize = 1;
|
||||||
|
while (goodSize < unsigned(size))
|
||||||
|
{
|
||||||
|
goodSize <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return goodSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -33,12 +33,12 @@ inline Foam::HashTable<T, Key, Hash>::hashedEntry::hashedEntry
|
|||||||
(
|
(
|
||||||
const Key& key,
|
const Key& key,
|
||||||
hashedEntry* next,
|
hashedEntry* next,
|
||||||
const T& newEntry
|
const T& obj
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
key_(key),
|
key_(key),
|
||||||
next_(next),
|
next_(next),
|
||||||
obj_(newEntry)
|
obj_(obj)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -55,6 +55,13 @@ Foam::HashTable<T, Key, Hash>::hashKeyIndex(const Key& key) const
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline Foam::label Foam::HashTable<T, Key, Hash>::capacity() const
|
||||||
|
{
|
||||||
|
return tableSize_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline Foam::label Foam::HashTable<T, Key, Hash>::size() const
|
inline Foam::label Foam::HashTable<T, Key, Hash>::size() const
|
||||||
{
|
{
|
||||||
@ -152,70 +159,218 @@ inline T& Foam::HashTable<T, Key, Hash>::operator()(const Key& key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * iterator base * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline Foam::HashTable<T, Key, Hash>::iterator::iterator
|
inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase()
|
||||||
|
:
|
||||||
|
hashTable_(0),
|
||||||
|
entryPtr_(0),
|
||||||
|
hashIndex_(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase
|
||||||
(
|
(
|
||||||
HashTable<T, Key, Hash>& hashTbl,
|
const HashTable<T, Key, Hash>* hashTbl
|
||||||
hashedEntry* elmt,
|
|
||||||
label hashIndex
|
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
hashTable_(hashTbl),
|
hashTable_(const_cast<HashTable<T, Key, Hash>*>(hashTbl)),
|
||||||
elmtPtr_(elmt),
|
entryPtr_(0),
|
||||||
|
hashIndex_(0)
|
||||||
|
{
|
||||||
|
if (hashTable_->nElmts_ && hashTable_->table_)
|
||||||
|
{
|
||||||
|
// find first non-NULL table entry
|
||||||
|
while
|
||||||
|
(
|
||||||
|
!(entryPtr_ = hashTable_->table_[hashIndex_])
|
||||||
|
&& ++hashIndex_ < hashTable_->tableSize_
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
|
if (hashIndex_ >= hashTable_->tableSize_)
|
||||||
|
{
|
||||||
|
// make into an end iterator
|
||||||
|
entryPtr_ = 0;
|
||||||
|
hashIndex_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline Foam::HashTable<T, Key, Hash>::iteratorBase::iteratorBase
|
||||||
|
(
|
||||||
|
const HashTable<T, Key, Hash>* hashTbl,
|
||||||
|
const hashedEntry* elmt,
|
||||||
|
const label hashIndex
|
||||||
|
)
|
||||||
|
:
|
||||||
|
hashTable_(const_cast<HashTable<T, Key, Hash>*>(hashTbl)),
|
||||||
|
entryPtr_(const_cast<hashedEntry*>(elmt)),
|
||||||
hashIndex_(hashIndex)
|
hashIndex_(hashIndex)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline void Foam::HashTable<T, Key, Hash>::iterator::operator=
|
inline void
|
||||||
|
Foam::HashTable<T, Key, Hash>::iteratorBase::increment()
|
||||||
|
{
|
||||||
|
// A negative index is a special value from erase
|
||||||
|
if (hashIndex_ < 0)
|
||||||
|
{
|
||||||
|
// the markPos='-curPos-1', but we wish to continue at 'curPos-1'
|
||||||
|
// thus use '-(markPos+1) -1'
|
||||||
|
hashIndex_ = -(hashIndex_+1) - 1;
|
||||||
|
}
|
||||||
|
else if (entryPtr_)
|
||||||
|
{
|
||||||
|
if (entryPtr_->next_)
|
||||||
|
{
|
||||||
|
// Move to next element on the SLList
|
||||||
|
entryPtr_ = entryPtr_->next_;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // if we reach here (entryPtr_ is NULL) it is already at the end()
|
||||||
|
// // we should probably stop
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// Step to the next table entry
|
||||||
|
while
|
||||||
|
(
|
||||||
|
++hashIndex_ < hashTable_->tableSize_
|
||||||
|
&& !(entryPtr_ = hashTable_->table_[hashIndex_])
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
|
if (hashIndex_ >= hashTable_->tableSize_)
|
||||||
|
{
|
||||||
|
// make into an end iterator
|
||||||
|
entryPtr_ = 0;
|
||||||
|
hashIndex_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline
|
||||||
|
const Key& Foam::HashTable<T, Key, Hash>::iteratorBase::key() const
|
||||||
|
{
|
||||||
|
return entryPtr_->key_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline T&
|
||||||
|
Foam::HashTable<T, Key, Hash>::iteratorBase::object()
|
||||||
|
{
|
||||||
|
return entryPtr_->obj_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline const T&
|
||||||
|
Foam::HashTable<T, Key, Hash>::iteratorBase::cobject() const
|
||||||
|
{
|
||||||
|
return entryPtr_->obj_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline bool Foam::HashTable<T, Key, Hash>::iteratorBase::operator==
|
||||||
(
|
(
|
||||||
const iterator& iter
|
const iteratorBase& iter
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return entryPtr_ == iter.entryPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline bool Foam::HashTable<T, Key, Hash>::iteratorBase::operator!=
|
||||||
|
(
|
||||||
|
const iteratorBase& iter
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return entryPtr_ != iter.entryPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline bool Foam::HashTable<T, Key, Hash>::iteratorBase::operator==
|
||||||
|
(
|
||||||
|
const iteratorEnd&
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return !entryPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline bool Foam::HashTable<T, Key, Hash>::iteratorBase::operator!=
|
||||||
|
(
|
||||||
|
const iteratorEnd&
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return entryPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline Foam::HashTable<T, Key, Hash>::iterator::iterator()
|
||||||
|
:
|
||||||
|
iteratorBase()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline Foam::HashTable<T, Key, Hash>::iterator::iterator
|
||||||
|
(
|
||||||
|
const iteratorEnd&
|
||||||
)
|
)
|
||||||
{
|
:
|
||||||
elmtPtr_ = iter.elmtPtr_;
|
iteratorBase()
|
||||||
hashIndex_ = iter.hashIndex_;
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline bool Foam::HashTable<T, Key, Hash>::iterator::operator==
|
inline Foam::HashTable<T, Key, Hash>::iterator::iterator
|
||||||
(
|
(
|
||||||
const iterator& iter
|
HashTable<T, Key, Hash>* hashTbl
|
||||||
) const
|
)
|
||||||
{
|
:
|
||||||
return elmtPtr_ == iter.elmtPtr_;
|
iteratorBase(hashTbl)
|
||||||
}
|
{}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline bool Foam::HashTable<T, Key, Hash>::iterator::operator!=
|
inline Foam::HashTable<T, Key, Hash>::iterator::iterator
|
||||||
(
|
(
|
||||||
const iterator& iter
|
HashTable<T, Key, Hash>* hashTbl,
|
||||||
) const
|
hashedEntry* elmt,
|
||||||
{
|
const label hashIndex
|
||||||
return elmtPtr_ != iter.elmtPtr_;
|
)
|
||||||
}
|
:
|
||||||
|
iteratorBase(hashTbl, elmt, hashIndex)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline bool Foam::HashTable<T, Key, Hash>::iterator::operator==
|
inline Foam::HashTable<T, Key, Hash>::iterator::operator
|
||||||
(
|
typename Foam::HashTable<T, Key, Hash>::const_iterator() const
|
||||||
const const_iterator& iter
|
|
||||||
) const
|
|
||||||
{
|
{
|
||||||
return elmtPtr_ == iter.elmtPtr_;
|
return *reinterpret_cast
|
||||||
}
|
<
|
||||||
|
const typename Foam::HashTable<T, Key, Hash>::const_iterator*
|
||||||
|
>(this);
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTable<T, Key, Hash>::iterator::operator!=
|
|
||||||
(
|
|
||||||
const const_iterator& iter
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return elmtPtr_ != iter.elmtPtr_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -223,7 +378,7 @@ template<class T, class Key, class Hash>
|
|||||||
inline T&
|
inline T&
|
||||||
Foam::HashTable<T, Key, Hash>::iterator::operator*()
|
Foam::HashTable<T, Key, Hash>::iterator::operator*()
|
||||||
{
|
{
|
||||||
return elmtPtr_->obj_;
|
return this->object();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -231,7 +386,7 @@ template<class T, class Key, class Hash>
|
|||||||
inline T&
|
inline T&
|
||||||
Foam::HashTable<T, Key, Hash>::iterator::operator()()
|
Foam::HashTable<T, Key, Hash>::iterator::operator()()
|
||||||
{
|
{
|
||||||
return elmtPtr_->obj_;
|
return this->object();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -239,7 +394,7 @@ template<class T, class Key, class Hash>
|
|||||||
inline const T&
|
inline const T&
|
||||||
Foam::HashTable<T, Key, Hash>::iterator::operator*() const
|
Foam::HashTable<T, Key, Hash>::iterator::operator*() const
|
||||||
{
|
{
|
||||||
return elmtPtr_->obj_;
|
return this->cobject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -247,7 +402,7 @@ template<class T, class Key, class Hash>
|
|||||||
inline const T&
|
inline const T&
|
||||||
Foam::HashTable<T, Key, Hash>::iterator::operator()() const
|
Foam::HashTable<T, Key, Hash>::iterator::operator()() const
|
||||||
{
|
{
|
||||||
return elmtPtr_->obj_;
|
return this->cobject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -256,53 +411,18 @@ inline
|
|||||||
typename Foam::HashTable<T, Key, Hash>::iterator&
|
typename Foam::HashTable<T, Key, Hash>::iterator&
|
||||||
Foam::HashTable<T, Key, Hash>::iterator::operator++()
|
Foam::HashTable<T, Key, Hash>::iterator::operator++()
|
||||||
{
|
{
|
||||||
// Check for special value from erase. (sets hashIndex to -1)
|
this->increment();
|
||||||
if (hashIndex_ >= 0)
|
|
||||||
{
|
|
||||||
// Do we have additional elements on the SLList?
|
|
||||||
if (elmtPtr_ && elmtPtr_->next_)
|
|
||||||
{
|
|
||||||
elmtPtr_ = elmtPtr_->next_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step to the next table entry
|
|
||||||
while
|
|
||||||
(
|
|
||||||
++hashIndex_ < hashTable_.tableSize_
|
|
||||||
&& !(elmtPtr_ = hashTable_.table_[hashIndex_])
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
if (hashIndex_ == hashTable_.tableSize_)
|
|
||||||
{
|
|
||||||
// make end iterator
|
|
||||||
elmtPtr_ = 0;
|
|
||||||
hashIndex_ = 0;
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
||||||
Foam::HashTable<T, Key, Hash>::iterator::operator++
|
Foam::HashTable<T, Key, Hash>::iterator::operator++(int)
|
||||||
(
|
|
||||||
int
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
iterator tmp = *this;
|
iterator old = *this;
|
||||||
++*this;
|
this->increment();
|
||||||
return tmp;
|
return old;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline
|
|
||||||
const Key& Foam::HashTable<T, Key, Hash>::iterator::key() const
|
|
||||||
{
|
|
||||||
return elmtPtr_->key_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -310,135 +430,64 @@ template<class T, class Key, class Hash>
|
|||||||
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
inline typename Foam::HashTable<T, Key, Hash>::iterator
|
||||||
Foam::HashTable<T, Key, Hash>::begin()
|
Foam::HashTable<T, Key, Hash>::begin()
|
||||||
{
|
{
|
||||||
label i = 0;
|
return iterator(this);
|
||||||
|
|
||||||
if (nElmts_)
|
|
||||||
{
|
|
||||||
while (table_ && !table_[i] && ++i < tableSize_)
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = tableSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == tableSize_)
|
|
||||||
{
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTable is empty\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return HashTable<T, Key, Hash>::endIter_;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return iterator(*this, table_[i], i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const typename Foam::HashTable<T, Key, Hash>::iterator&
|
|
||||||
Foam::HashTable<T, Key, Hash>::end()
|
|
||||||
{
|
|
||||||
return HashTable<T, Key, Hash>::endIter_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator()
|
||||||
|
:
|
||||||
|
iteratorBase()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
|
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
|
||||||
(
|
(
|
||||||
const HashTable<T, Key, Hash>& hashTbl,
|
const iteratorEnd&
|
||||||
|
)
|
||||||
|
:
|
||||||
|
iteratorBase()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
|
||||||
|
(
|
||||||
|
const HashTable<T, Key, Hash>* hashTbl
|
||||||
|
)
|
||||||
|
:
|
||||||
|
iteratorBase(hashTbl)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class Key, class Hash>
|
||||||
|
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
|
||||||
|
(
|
||||||
|
const HashTable<T, Key, Hash>* hashTbl,
|
||||||
const hashedEntry* elmt,
|
const hashedEntry* elmt,
|
||||||
label hashIndex
|
const label hashIndex
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
hashTable_(hashTbl),
|
iteratorBase(hashTbl, elmt, hashIndex)
|
||||||
elmtPtr_(elmt),
|
|
||||||
hashIndex_(hashIndex)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTable<T, Key, Hash>::const_iterator::const_iterator
|
|
||||||
(
|
|
||||||
const iterator& iter
|
|
||||||
)
|
|
||||||
:
|
|
||||||
hashTable_(iter.hashTable_),
|
|
||||||
elmtPtr_(iter.elmtPtr_),
|
|
||||||
hashIndex_(iter.hashIndex_)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline void Foam::HashTable<T, Key, Hash>::const_iterator::operator=
|
|
||||||
(
|
|
||||||
const const_iterator& iter
|
|
||||||
)
|
|
||||||
{
|
|
||||||
elmtPtr_ = iter.elmtPtr_;
|
|
||||||
hashIndex_ = iter.hashIndex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTable<T, Key, Hash>::const_iterator::operator==
|
|
||||||
(
|
|
||||||
const const_iterator& iter
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return elmtPtr_ == iter.elmtPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTable<T, Key, Hash>::const_iterator::operator!=
|
|
||||||
(
|
|
||||||
const const_iterator& iter
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return elmtPtr_ != iter.elmtPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTable<T, Key, Hash>::const_iterator::operator==
|
|
||||||
(
|
|
||||||
const iterator& iter
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return elmtPtr_ == iter.elmtPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTable<T, Key, Hash>::const_iterator::operator!=
|
|
||||||
(
|
|
||||||
const iterator& iter
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return elmtPtr_ != iter.elmtPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline const T&
|
inline const T&
|
||||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator*() const
|
Foam::HashTable<T, Key, Hash>::const_iterator::operator*() const
|
||||||
{
|
{
|
||||||
return elmtPtr_->obj_;
|
return this->cobject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline const T&
|
inline const T&
|
||||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator()() const
|
Foam::HashTable<T, Key, Hash>::const_iterator::operator()() const
|
||||||
{
|
{
|
||||||
return elmtPtr_->obj_;
|
return this->cobject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -447,43 +496,18 @@ inline
|
|||||||
typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
||||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator++()
|
Foam::HashTable<T, Key, Hash>::const_iterator::operator++()
|
||||||
{
|
{
|
||||||
if
|
this->increment();
|
||||||
(
|
|
||||||
!(elmtPtr_ = elmtPtr_->next_)
|
|
||||||
&& ++hashIndex_ < hashTable_.tableSize_
|
|
||||||
&& !(elmtPtr_ = hashTable_.table_[hashIndex_])
|
|
||||||
)
|
|
||||||
{
|
|
||||||
while
|
|
||||||
(
|
|
||||||
++hashIndex_ < hashTable_.tableSize_
|
|
||||||
&& !(elmtPtr_ = hashTable_.table_[hashIndex_])
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||||
Foam::HashTable<T, Key, Hash>::const_iterator::operator++
|
Foam::HashTable<T, Key, Hash>::const_iterator::operator++(int)
|
||||||
(
|
|
||||||
int
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const_iterator tmp = *this;
|
const_iterator old = *this;
|
||||||
++*this;
|
this->increment();
|
||||||
return tmp;
|
return old;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline
|
|
||||||
const Key& Foam::HashTable<T, Key, Hash>::const_iterator::key() const
|
|
||||||
{
|
|
||||||
return elmtPtr_->key_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -491,41 +515,7 @@ template<class T, class Key, class Hash>
|
|||||||
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
|
||||||
Foam::HashTable<T, Key, Hash>::cbegin() const
|
Foam::HashTable<T, Key, Hash>::cbegin() const
|
||||||
{
|
{
|
||||||
label i = 0;
|
return const_iterator(this);
|
||||||
|
|
||||||
if (nElmts_)
|
|
||||||
{
|
|
||||||
while (table_ && !table_[i] && ++i < tableSize_)
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = tableSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == tableSize_)
|
|
||||||
{
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTable is empty\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return HashTable<T, Key, Hash>::endConstIter_;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return const_iterator(*this, table_[i], i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
|
||||||
Foam::HashTable<T, Key, Hash>::cend() const
|
|
||||||
{
|
|
||||||
return HashTable<T, Key, Hash>::endConstIter_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -537,12 +527,4 @@ Foam::HashTable<T, Key, Hash>::begin() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const typename Foam::HashTable<T, Key, Hash>::const_iterator&
|
|
||||||
Foam::HashTable<T, Key, Hash>::end() const
|
|
||||||
{
|
|
||||||
return HashTable<T, Key, Hash>::endConstIter_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -33,16 +33,19 @@ License
|
|||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
Foam::HashTable<T, Key, Hash>::HashTable(Istream& is, const label size)
|
Foam::HashTable<T, Key, Hash>::HashTable(Istream& is, const label size)
|
||||||
:
|
:
|
||||||
HashTableName(),
|
HashTableCore(),
|
||||||
nElmts_(0),
|
nElmts_(0),
|
||||||
tableSize_(canonicalSize(size)),
|
tableSize_(HashTableCore::canonicalSize(size)),
|
||||||
table_(new hashedEntry*[tableSize_]),
|
table_(NULL)
|
||||||
endIter_(*this, NULL, 0),
|
|
||||||
endConstIter_(*this, NULL, 0)
|
|
||||||
{
|
{
|
||||||
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
if (tableSize_)
|
||||||
{
|
{
|
||||||
table_[hashIdx] = 0;
|
table_ = new hashedEntry*[tableSize_];
|
||||||
|
|
||||||
|
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
||||||
|
{
|
||||||
|
table_[hashIdx] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operator>>(is, *this);
|
operator>>(is, *this);
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by the
|
|
||||||
Free Software Foundation; either version 2 of the License, or (at your
|
|
||||||
option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "HashTable.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(Foam::HashTableName, 0);
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,645 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by the
|
|
||||||
Free Software Foundation; either version 2 of the License, or (at your
|
|
||||||
option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef HashTbl_C
|
|
||||||
#define HashTbl_C
|
|
||||||
|
|
||||||
#include "HashTbl.H"
|
|
||||||
#include "List.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::label Foam::HashTblCore::canonicalSize(const label size)
|
|
||||||
{
|
|
||||||
if (size < 1)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// enforce power of two
|
|
||||||
unsigned int goodSize = size;
|
|
||||||
|
|
||||||
if (goodSize & (goodSize - 1))
|
|
||||||
{
|
|
||||||
// brute-force is fast enough
|
|
||||||
goodSize = 1;
|
|
||||||
while (goodSize < unsigned(size))
|
|
||||||
{
|
|
||||||
goodSize <<= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return goodSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::HashTbl<T, Key, Hash>::HashTbl(const label size)
|
|
||||||
:
|
|
||||||
HashTblCore(),
|
|
||||||
nElmts_(0),
|
|
||||||
tableSize_(HashTblCore::canonicalSize(size)),
|
|
||||||
table_(NULL)
|
|
||||||
{
|
|
||||||
if (tableSize_)
|
|
||||||
{
|
|
||||||
table_ = new hashedEntry*[tableSize_];
|
|
||||||
|
|
||||||
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
|
||||||
{
|
|
||||||
table_[hashIdx] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::HashTbl<T, Key, Hash>::HashTbl(const HashTbl<T, Key, Hash>& ht)
|
|
||||||
:
|
|
||||||
HashTblCore(),
|
|
||||||
nElmts_(0),
|
|
||||||
tableSize_(ht.tableSize_),
|
|
||||||
table_(NULL)
|
|
||||||
{
|
|
||||||
if (tableSize_)
|
|
||||||
{
|
|
||||||
table_ = new hashedEntry*[tableSize_];
|
|
||||||
|
|
||||||
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
|
||||||
{
|
|
||||||
table_[hashIdx] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const_iterator iter = ht.cbegin(); iter != ht.cend(); ++iter)
|
|
||||||
{
|
|
||||||
insert(iter.key(), *iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::HashTbl<T, Key, Hash>::HashTbl
|
|
||||||
(
|
|
||||||
const Xfer<HashTbl<T, Key, Hash> >& ht
|
|
||||||
)
|
|
||||||
:
|
|
||||||
HashTblCore(),
|
|
||||||
nElmts_(0),
|
|
||||||
tableSize_(0),
|
|
||||||
table_(NULL)
|
|
||||||
{
|
|
||||||
transfer(ht());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::HashTbl<T, Key, Hash>::~HashTbl()
|
|
||||||
{
|
|
||||||
if (table_)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
delete[] table_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
bool Foam::HashTbl<T, Key, Hash>::found(const Key& key) const
|
|
||||||
{
|
|
||||||
if (nElmts_)
|
|
||||||
{
|
|
||||||
const label hashIdx = hashKeyIndex(key);
|
|
||||||
|
|
||||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
|
||||||
{
|
|
||||||
if (key == ep->key_)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTbl<T, Key, Hash>::found(const Key& key) : "
|
|
||||||
<< "Entry " << key << " not found in hash table\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
typename Foam::HashTbl<T, Key, Hash>::iterator
|
|
||||||
Foam::HashTbl<T, Key, Hash>::find
|
|
||||||
(
|
|
||||||
const Key& key
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (nElmts_)
|
|
||||||
{
|
|
||||||
const label hashIdx = hashKeyIndex(key);
|
|
||||||
|
|
||||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
|
||||||
{
|
|
||||||
if (key == ep->key_)
|
|
||||||
{
|
|
||||||
return iterator(this, ep, hashIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTbl<T, Key, Hash>::find(const Key& key) : "
|
|
||||||
<< "Entry " << key << " not found in hash table\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
typename Foam::HashTbl<T, Key, Hash>::const_iterator
|
|
||||||
Foam::HashTbl<T, Key, Hash>::find
|
|
||||||
(
|
|
||||||
const Key& key
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
if (nElmts_)
|
|
||||||
{
|
|
||||||
const label hashIdx = hashKeyIndex(key);
|
|
||||||
|
|
||||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
|
||||||
{
|
|
||||||
if (key == ep->key_)
|
|
||||||
{
|
|
||||||
return const_iterator(this, ep, hashIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTbl<T, Key, Hash>::find(const Key& key) const : "
|
|
||||||
<< "Entry " << key << " not found in hash table\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return const_iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::List<Key> Foam::HashTbl<T, Key, Hash>::toc() const
|
|
||||||
{
|
|
||||||
List<Key> keys(nElmts_);
|
|
||||||
label keyI = 0;
|
|
||||||
|
|
||||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
|
||||||
{
|
|
||||||
keys[keyI++] = iter.key();
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::List<Key> Foam::HashTbl<T, Key, Hash>::sortedToc() const
|
|
||||||
{
|
|
||||||
List<Key> sortedLst = this->toc();
|
|
||||||
sort(sortedLst);
|
|
||||||
|
|
||||||
return sortedLst;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
bool Foam::HashTbl<T, Key, Hash>::set
|
|
||||||
(
|
|
||||||
const Key& key,
|
|
||||||
const T& newEntry,
|
|
||||||
const bool protect
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!tableSize_)
|
|
||||||
{
|
|
||||||
resize(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
const label hashIdx = hashKeyIndex(key);
|
|
||||||
|
|
||||||
hashedEntry* existing = 0;
|
|
||||||
hashedEntry* prev = 0;
|
|
||||||
|
|
||||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
|
||||||
{
|
|
||||||
if (key == ep->key_)
|
|
||||||
{
|
|
||||||
existing = ep;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev = ep;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not found, insert it at the head
|
|
||||||
if (!existing)
|
|
||||||
{
|
|
||||||
table_[hashIdx] = new hashedEntry(key, table_[hashIdx], newEntry);
|
|
||||||
nElmts_++;
|
|
||||||
|
|
||||||
if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize)
|
|
||||||
{
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTbl<T, Key, Hash>::set"
|
|
||||||
"(const Key& key, T newEntry) : "
|
|
||||||
"Doubling table size\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
resize(2*tableSize_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (protect)
|
|
||||||
{
|
|
||||||
// found - but protected from overwriting
|
|
||||||
// this corresponds to the STL 'insert' convention
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTbl<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
|
|
||||||
hashedEntry* ep = new hashedEntry(key, existing->next_, newEntry);
|
|
||||||
|
|
||||||
// replace existing element - within list or insert at the head
|
|
||||||
if (prev)
|
|
||||||
{
|
|
||||||
prev->next_ = ep;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
table_[hashIdx] = ep;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete existing;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
bool Foam::HashTbl<T, Key, Hash>::iteratorBase::erase()
|
|
||||||
{
|
|
||||||
// note: entryPtr_ is NULL for end(), so this catches that too
|
|
||||||
if (entryPtr_)
|
|
||||||
{
|
|
||||||
// Search element before entryPtr_
|
|
||||||
hashedEntry* prev = 0;
|
|
||||||
|
|
||||||
for
|
|
||||||
(
|
|
||||||
hashedEntry* ep = hashTable_->table_[hashIndex_];
|
|
||||||
ep;
|
|
||||||
ep = ep->next_
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (ep == entryPtr_)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev = ep;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev)
|
|
||||||
{
|
|
||||||
// has an element before entryPtr - reposition to there
|
|
||||||
prev->next_ = entryPtr_->next_;
|
|
||||||
delete entryPtr_;
|
|
||||||
entryPtr_ = prev;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// entryPtr was first element on SLList
|
|
||||||
hashTable_->table_[hashIndex_] = entryPtr_->next_;
|
|
||||||
delete entryPtr_;
|
|
||||||
|
|
||||||
// assign any non-NULL pointer value so it doesn't look
|
|
||||||
// like end()/cend()
|
|
||||||
entryPtr_ = reinterpret_cast<hashedEntry*>(this);
|
|
||||||
|
|
||||||
// Mark with special hashIndex value to signal it has been rewound.
|
|
||||||
// The next increment will bring it back to the present location.
|
|
||||||
//
|
|
||||||
// From the current position 'curPos', we wish to continue at
|
|
||||||
// prevPos='curPos-1', which we mark as markPos='-curPos-1'.
|
|
||||||
// The negative lets us notice it is special, the extra '-1'
|
|
||||||
// is needed to avoid ambiguity for position '0'.
|
|
||||||
// To retrieve prevPos, we would later use '-(markPos+1) - 1'
|
|
||||||
hashIndex_ = -hashIndex_ - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
hashTable_->nElmts_--;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE:
|
|
||||||
// We use (const iterator&) here, but manipulate its contents anyhow.
|
|
||||||
// The parameter should be (iterator&), but then the compiler doesn't find
|
|
||||||
// it correctly and tries to call as (iterator) instead.
|
|
||||||
//
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
bool Foam::HashTbl<T, Key, Hash>::erase(const iterator& cit)
|
|
||||||
{
|
|
||||||
// adjust iterator after erase
|
|
||||||
return const_cast<iterator&>(cit).erase();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
bool Foam::HashTbl<T, Key, Hash>::erase(const Key& key)
|
|
||||||
{
|
|
||||||
return erase(find(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::label Foam::HashTbl<T, Key, Hash>::erase(const UList<Key>& keys)
|
|
||||||
{
|
|
||||||
const label nTotal = nElmts_;
|
|
||||||
label count = 0;
|
|
||||||
|
|
||||||
// Remove listed keys from this table - terminates early if possible
|
|
||||||
for (label keyI = 0; count < nTotal && keyI < keys.size(); ++keyI)
|
|
||||||
{
|
|
||||||
if (erase(keys[keyI]))
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
template<class AnyType, class AnyHash>
|
|
||||||
Foam::label Foam::HashTbl<T, Key, Hash>::erase
|
|
||||||
(
|
|
||||||
const HashTbl<AnyType, Key, AnyHash>& rhs
|
|
||||||
)
|
|
||||||
{
|
|
||||||
label count = 0;
|
|
||||||
|
|
||||||
// Remove rhs keys from this table - terminates early if possible
|
|
||||||
// Could optimize depending on which hash is smaller ...
|
|
||||||
for (iterator iter = begin(); iter != end(); ++iter)
|
|
||||||
{
|
|
||||||
if (rhs.found(iter.key()) && erase(iter))
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
void Foam::HashTbl<T, Key, Hash>::resize(const label sz)
|
|
||||||
{
|
|
||||||
label newSize = HashTblCore::canonicalSize(sz);
|
|
||||||
|
|
||||||
if (newSize == tableSize_)
|
|
||||||
{
|
|
||||||
# ifdef FULLDEBUG
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "HashTbl<T, Key, Hash>::resize(const label) : "
|
|
||||||
<< "new table size == old table size\n";
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashTbl<T, Key, Hash>* tmpTable = new HashTbl<T, Key, Hash>(newSize);
|
|
||||||
|
|
||||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
|
||||||
{
|
|
||||||
tmpTable->insert(iter.key(), *iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
label oldSize = tableSize_;
|
|
||||||
tableSize_ = tmpTable->tableSize_;
|
|
||||||
tmpTable->tableSize_ = oldSize;
|
|
||||||
|
|
||||||
hashedEntry** oldTable = table_;
|
|
||||||
table_ = tmpTable->table_;
|
|
||||||
tmpTable->table_ = oldTable;
|
|
||||||
|
|
||||||
delete tmpTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
void Foam::HashTbl<T, Key, Hash>::clear()
|
|
||||||
{
|
|
||||||
if (nElmts_)
|
|
||||||
{
|
|
||||||
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
|
||||||
{
|
|
||||||
if (table_[hashIdx])
|
|
||||||
{
|
|
||||||
hashedEntry* ep = table_[hashIdx];
|
|
||||||
while (hashedEntry* next = ep->next_)
|
|
||||||
{
|
|
||||||
delete ep;
|
|
||||||
ep = next;
|
|
||||||
}
|
|
||||||
delete ep;
|
|
||||||
table_[hashIdx] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nElmts_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
void Foam::HashTbl<T, Key, Hash>::clearStorage()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
resize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
void Foam::HashTbl<T, Key, Hash>::shrink()
|
|
||||||
{
|
|
||||||
const label newSize = HashTblCore::canonicalSize(nElmts_);
|
|
||||||
|
|
||||||
if (newSize < tableSize_)
|
|
||||||
{
|
|
||||||
// avoid having the table disappear on us
|
|
||||||
resize(newSize ? newSize : 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
void Foam::HashTbl<T, Key, Hash>::transfer(HashTbl<T, Key, Hash>& ht)
|
|
||||||
{
|
|
||||||
// as per the Destructor
|
|
||||||
if (table_)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
delete[] table_;
|
|
||||||
}
|
|
||||||
|
|
||||||
tableSize_ = ht.tableSize_;
|
|
||||||
ht.tableSize_ = 0;
|
|
||||||
|
|
||||||
table_ = ht.table_;
|
|
||||||
ht.table_ = NULL;
|
|
||||||
|
|
||||||
nElmts_ = ht.nElmts_;
|
|
||||||
ht.nElmts_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
void Foam::HashTbl<T, Key, Hash>::operator=
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>& rhs
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Check for assignment to self
|
|
||||||
if (this == &rhs)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"HashTbl<T, Key, Hash>::operator="
|
|
||||||
"(const HashTbl<T, Key, Hash>&)"
|
|
||||||
) << "attempted assignment to self"
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// could be zero-sized from a previous transfer()
|
|
||||||
if (!tableSize_)
|
|
||||||
{
|
|
||||||
resize(rhs.tableSize_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
|
||||||
{
|
|
||||||
insert(iter.key(), *iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
bool Foam::HashTbl<T, Key, Hash>::operator==
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>& rhs
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
// sizes (number of keys) must match
|
|
||||||
if (size() != rhs.size())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
|
||||||
{
|
|
||||||
const_iterator fnd = find(iter.key());
|
|
||||||
|
|
||||||
if (fnd == cend() || fnd() != iter())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
bool Foam::HashTbl<T, Key, Hash>::operator!=
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>& rhs
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return !(operator==(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#include "HashTblIO.C"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,563 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by the
|
|
||||||
Free Software Foundation; either version 2 of the License, or (at your
|
|
||||||
option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::HashTbl
|
|
||||||
|
|
||||||
Description
|
|
||||||
An STL-conforming hash table.
|
|
||||||
|
|
||||||
Note
|
|
||||||
Hashing index collisions are handled via chaining using a singly-linked
|
|
||||||
list with the colliding entry being added to the head of the linked
|
|
||||||
list. Thus copying the hash table (or indeed even resizing it) will
|
|
||||||
often result in a different hash order. Use a sorted table-of-contents
|
|
||||||
when the hash order is important.
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
HashTblI.H
|
|
||||||
HashTbl.C
|
|
||||||
HashTblIO.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef HashTbl_H
|
|
||||||
#define HashTbl_H
|
|
||||||
|
|
||||||
#include "label.H"
|
|
||||||
#include "uLabel.H"
|
|
||||||
#include "word.H"
|
|
||||||
#include "Xfer.H"
|
|
||||||
#include "className.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
// Forward declaration of friend functions and operators
|
|
||||||
|
|
||||||
template<class T> class List;
|
|
||||||
template<class T> class UList;
|
|
||||||
template<class T, class Key, class Hash> class HashTbl;
|
|
||||||
template<class T, class Key, class Hash> class HashPtrTable;
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Istream& operator>>(Istream&, HashTbl<T, Key, Hash>&);
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Ostream& operator<<(Ostream&, const HashTbl<T, Key, Hash>&);
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class HashTblCore Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
//- Template-invariant bits for HashTbl
|
|
||||||
struct HashTblCore
|
|
||||||
{
|
|
||||||
//- Return a canonical (power-of-two) size
|
|
||||||
static label canonicalSize(const label);
|
|
||||||
|
|
||||||
//- Maximum allowable table size
|
|
||||||
static const label maxTableSize;
|
|
||||||
|
|
||||||
//- Construct null
|
|
||||||
HashTblCore()
|
|
||||||
{}
|
|
||||||
|
|
||||||
//- Define template name and debug
|
|
||||||
ClassName("HashTbl");
|
|
||||||
|
|
||||||
//- A zero-sized end iterator
|
|
||||||
struct iteratorEnd
|
|
||||||
{
|
|
||||||
//- Construct null
|
|
||||||
iteratorEnd()
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
//- iteratorEnd set to beyond the end of any HashTbl
|
|
||||||
static iteratorEnd cend()
|
|
||||||
{
|
|
||||||
return iteratorEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
//- iteratorEnd set to beyond the end of any HashTbl
|
|
||||||
static iteratorEnd end()
|
|
||||||
{
|
|
||||||
return iteratorEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class HashTbl Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
template<class T, class Key=word, class Hash=string::hash>
|
|
||||||
class HashTbl
|
|
||||||
:
|
|
||||||
public HashTblCore
|
|
||||||
{
|
|
||||||
// Private data type for table entries
|
|
||||||
|
|
||||||
//- Structure to hold a hashed entry with SLList for collisions
|
|
||||||
struct hashedEntry
|
|
||||||
{
|
|
||||||
//- The lookup key
|
|
||||||
Key key_;
|
|
||||||
|
|
||||||
//- Pointer to next hashedEntry in sub-list
|
|
||||||
hashedEntry* next_;
|
|
||||||
|
|
||||||
//- The data object
|
|
||||||
T obj_;
|
|
||||||
|
|
||||||
//- Construct from key, next pointer and object
|
|
||||||
inline hashedEntry(const Key&, hashedEntry* next, const T&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//- Disallow default bitwise copy construct
|
|
||||||
hashedEntry(const hashedEntry&);
|
|
||||||
|
|
||||||
//- Disallow default bitwise assignment
|
|
||||||
void operator=(const hashedEntry&);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Private data: size of table, the table and current number of elements
|
|
||||||
|
|
||||||
//- The current number of elements in table
|
|
||||||
label nElmts_;
|
|
||||||
|
|
||||||
//- Number of primary entries allocated in table
|
|
||||||
label tableSize_;
|
|
||||||
|
|
||||||
//- The table of primary entries
|
|
||||||
hashedEntry** table_;
|
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- Return a canonical (power-of-two) size
|
|
||||||
static label canonicalSize(const label);
|
|
||||||
|
|
||||||
//- Return the hash index of the Key within the current table size.
|
|
||||||
// No checks for zero-sized tables.
|
|
||||||
inline label hashKeyIndex(const Key&) const;
|
|
||||||
|
|
||||||
//- Assign a new hashedEntry to a possibly already existing key
|
|
||||||
bool set(const Key&, const T& newElmt, bool protect);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Forward declaration of iterators
|
|
||||||
|
|
||||||
class iteratorBase;
|
|
||||||
class iterator;
|
|
||||||
class const_iterator;
|
|
||||||
|
|
||||||
//- Declare friendship with the HashPtrTable class
|
|
||||||
template<class T2, class Key2, class Hash2>
|
|
||||||
friend class HashPtrTable;
|
|
||||||
|
|
||||||
//- Declare friendship with the iteratorBase
|
|
||||||
friend class iteratorBase;
|
|
||||||
|
|
||||||
//- Declare friendship with the iterator
|
|
||||||
friend class iterator;
|
|
||||||
|
|
||||||
//- Declare friendship with the const_iterator
|
|
||||||
friend class const_iterator;
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct given initial table size
|
|
||||||
HashTbl(const label size = 128);
|
|
||||||
|
|
||||||
//- Construct from Istream
|
|
||||||
HashTbl(Istream&, const label size = 128);
|
|
||||||
|
|
||||||
//- Construct as copy
|
|
||||||
HashTbl(const HashTbl<T, Key, Hash>&);
|
|
||||||
|
|
||||||
//- Construct by transferring the parameter contents
|
|
||||||
HashTbl(const Xfer<HashTbl<T, Key, Hash> >&);
|
|
||||||
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
|
|
||||||
~HashTbl();
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
// Access
|
|
||||||
|
|
||||||
//- The size of the underlying table
|
|
||||||
inline label capacity() const;
|
|
||||||
|
|
||||||
//- Return number of elements in table
|
|
||||||
inline label size() const;
|
|
||||||
|
|
||||||
//- Return true if the hash table is empty
|
|
||||||
inline bool empty() const;
|
|
||||||
|
|
||||||
//- Return true if hashedEntry is found in table
|
|
||||||
bool found(const Key&) const;
|
|
||||||
|
|
||||||
//- Find and return an iterator set at the hashedEntry
|
|
||||||
// If not found iterator = end()
|
|
||||||
iterator find(const Key&);
|
|
||||||
|
|
||||||
//- Find and return an const_iterator set at the hashedEntry
|
|
||||||
// If not found iterator = end()
|
|
||||||
const_iterator find(const Key&) const;
|
|
||||||
|
|
||||||
//- Return the table of contents
|
|
||||||
List<Key> toc() const;
|
|
||||||
|
|
||||||
//- Return the table of contents as a sorted list
|
|
||||||
List<Key> sortedToc() const;
|
|
||||||
|
|
||||||
//- Print information
|
|
||||||
Ostream& printInfo(Ostream&) const;
|
|
||||||
|
|
||||||
// Edit
|
|
||||||
|
|
||||||
//- Insert a new hashedEntry
|
|
||||||
inline bool insert(const Key&, const T& newElmt);
|
|
||||||
|
|
||||||
//- Assign a new hashedEntry, overwriting existing entries
|
|
||||||
inline bool set(const Key&, const T& newElmt);
|
|
||||||
|
|
||||||
//- Erase a hashedEntry specified by given iterator
|
|
||||||
// This invalidates the iterator until the next operator++
|
|
||||||
bool erase(const iterator&);
|
|
||||||
|
|
||||||
//- Erase a hashedEntry specified by the given key
|
|
||||||
bool erase(const Key&);
|
|
||||||
|
|
||||||
//- Remove entries given by the listed keys from this HashTbl
|
|
||||||
// Return the number of elements removed
|
|
||||||
label erase(const UList<Key>&);
|
|
||||||
|
|
||||||
//- Remove entries given by the given keys from this HashTbl
|
|
||||||
// Return the number of elements removed.
|
|
||||||
// The parameter HashTbl needs the same type of key, but the
|
|
||||||
// type of values held and the hashing function are arbitrary.
|
|
||||||
template<class AnyType, class AnyHash>
|
|
||||||
label erase(const HashTbl<AnyType, Key, AnyHash>&);
|
|
||||||
|
|
||||||
//- Resize the hash table for efficiency
|
|
||||||
void resize(const label newSize);
|
|
||||||
|
|
||||||
//- Clear all entries from table
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
//- Clear the table entries and the table itself.
|
|
||||||
// Equivalent to clear() followed by resize(0)
|
|
||||||
void clearStorage();
|
|
||||||
|
|
||||||
//- Shrink the allocated table to approx. twice number of elements
|
|
||||||
void shrink();
|
|
||||||
|
|
||||||
//- Transfer the contents of the argument table into this table
|
|
||||||
// and annull the argument table.
|
|
||||||
void transfer(HashTbl<T, Key, Hash>&);
|
|
||||||
|
|
||||||
//- Transfer contents to the Xfer container
|
|
||||||
inline Xfer< HashTbl<T, Key, Hash> > xfer();
|
|
||||||
|
|
||||||
|
|
||||||
// Member Operators
|
|
||||||
|
|
||||||
//- Find and return a hashedEntry
|
|
||||||
inline T& operator[](const Key&);
|
|
||||||
|
|
||||||
//- Find and return a hashedEntry
|
|
||||||
inline const T& operator[](const Key&) const;
|
|
||||||
|
|
||||||
//- Find and return a hashedEntry, create it null if not present
|
|
||||||
inline T& operator()(const Key&);
|
|
||||||
|
|
||||||
//- Assignment
|
|
||||||
void operator=(const HashTbl<T, Key, Hash>&);
|
|
||||||
|
|
||||||
//- Equality. Hash tables are equal if the keys and values are equal.
|
|
||||||
// Independent of table storage size and table order.
|
|
||||||
bool operator==(const HashTbl<T, Key, Hash>&) const;
|
|
||||||
|
|
||||||
//- The opposite of the equality operation. Takes linear time.
|
|
||||||
bool operator!=(const HashTbl<T, Key, Hash>&) const;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// STL type definitions
|
|
||||||
|
|
||||||
//- Type of values the HashTbl contains.
|
|
||||||
typedef T value_type;
|
|
||||||
|
|
||||||
//- Type that can be used for storing into HashTbl::value_type
|
|
||||||
// objects. This type is usually List::value_type&.
|
|
||||||
typedef T& reference;
|
|
||||||
|
|
||||||
//- Type that can be used for storing into constant
|
|
||||||
// HashTbl::value_type objects. This type is usually const
|
|
||||||
// HashTbl::value_type&.
|
|
||||||
typedef const T& const_reference;
|
|
||||||
|
|
||||||
//- The type that can represent the size of a HashTbl.
|
|
||||||
typedef label size_type;
|
|
||||||
|
|
||||||
|
|
||||||
// Iterators and helpers
|
|
||||||
|
|
||||||
//- The iterator base for HashTbl
|
|
||||||
// Note: data and functions are protected, to allow reuse by iterator
|
|
||||||
// and prevent most external usage.
|
|
||||||
// iterator and const_iterator have the same size, allowing
|
|
||||||
// us to reinterpret_cast between them (if desired)
|
|
||||||
class iteratorBase
|
|
||||||
{
|
|
||||||
// Private Data
|
|
||||||
|
|
||||||
//- Pointer to the HashTbl for which this is an iterator
|
|
||||||
// This also lets us use the default bitwise copy/assignment
|
|
||||||
HashTbl<T, Key, Hash>* hashTable_;
|
|
||||||
|
|
||||||
//- Current element
|
|
||||||
hashedEntry* entryPtr_;
|
|
||||||
|
|
||||||
//- Current hash index
|
|
||||||
label hashIndex_;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Protected Member Functions
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct null - equivalent to an 'end' position
|
|
||||||
inline iteratorBase();
|
|
||||||
|
|
||||||
//- Construct from hash table, moving to its 'begin' position
|
|
||||||
inline explicit iteratorBase
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>* curHashTbl
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Construct from hash table, element and hash index
|
|
||||||
inline explicit iteratorBase
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>* curHashTbl,
|
|
||||||
const hashedEntry* elmt,
|
|
||||||
const label hashIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Increment to the next position
|
|
||||||
inline void increment();
|
|
||||||
|
|
||||||
//- Erase the HashTbl element at the current position
|
|
||||||
bool erase();
|
|
||||||
|
|
||||||
//- Return non-const access to referenced object
|
|
||||||
inline T& object();
|
|
||||||
|
|
||||||
//- Return const access to referenced object
|
|
||||||
inline const T& cobject() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Member operators
|
|
||||||
|
|
||||||
// Access
|
|
||||||
|
|
||||||
//- Return the Key corresponding to the iterator
|
|
||||||
inline const Key& key() const;
|
|
||||||
|
|
||||||
//- Compare hashedEntry element pointers
|
|
||||||
inline bool operator==(const iteratorBase&) const;
|
|
||||||
inline bool operator!=(const iteratorBase&) const;
|
|
||||||
|
|
||||||
//- Compare hashedEntry to iteratorEnd pointers
|
|
||||||
inline bool operator==(const iteratorEnd&) const;
|
|
||||||
inline bool operator!=(const iteratorEnd&) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//- An STL-conforming iterator
|
|
||||||
class iterator
|
|
||||||
:
|
|
||||||
public iteratorBase
|
|
||||||
{
|
|
||||||
friend class HashTbl;
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- Construct from hash table, moving to its 'begin' position
|
|
||||||
inline explicit iterator
|
|
||||||
(
|
|
||||||
HashTbl<T, Key, Hash>* curHashTbl
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Construct from hash table, element and hash index
|
|
||||||
inline explicit iterator
|
|
||||||
(
|
|
||||||
HashTbl<T, Key, Hash>* curHashTbl,
|
|
||||||
hashedEntry* elmt,
|
|
||||||
const label hashIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct null (end iterator)
|
|
||||||
inline iterator();
|
|
||||||
|
|
||||||
//- Construct end iterator
|
|
||||||
inline iterator(const iteratorEnd&);
|
|
||||||
|
|
||||||
// Member operators
|
|
||||||
|
|
||||||
//- Conversion to a const_iterator
|
|
||||||
inline operator const_iterator() const;
|
|
||||||
|
|
||||||
// Access
|
|
||||||
|
|
||||||
//- Return referenced hash value
|
|
||||||
inline T& operator*();
|
|
||||||
inline T& operator()();
|
|
||||||
|
|
||||||
//- Return referenced hash value
|
|
||||||
inline const T& operator*() const;
|
|
||||||
inline const T& operator()() const;
|
|
||||||
|
|
||||||
inline iterator& operator++();
|
|
||||||
inline iterator operator++(int);
|
|
||||||
};
|
|
||||||
|
|
||||||
//- iterator set to the begining of the HashTbl
|
|
||||||
inline iterator begin();
|
|
||||||
|
|
||||||
|
|
||||||
// STL const_iterator
|
|
||||||
|
|
||||||
//- An STL-conforming const_iterator
|
|
||||||
class const_iterator
|
|
||||||
:
|
|
||||||
public iteratorBase
|
|
||||||
{
|
|
||||||
friend class HashTbl;
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- Construct from hash table, moving to its 'begin' position
|
|
||||||
inline explicit const_iterator
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>* curHashTbl
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Construct from hash table, element and hash index
|
|
||||||
inline explicit const_iterator
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>* curHashTbl,
|
|
||||||
const hashedEntry* elmt,
|
|
||||||
const label hashIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct null (end iterator)
|
|
||||||
inline const_iterator();
|
|
||||||
|
|
||||||
//- Construct end iterator
|
|
||||||
inline const_iterator(const iteratorEnd&);
|
|
||||||
|
|
||||||
// Member operators
|
|
||||||
|
|
||||||
// Access
|
|
||||||
|
|
||||||
//- Return referenced hash value
|
|
||||||
inline const T& operator*() const;
|
|
||||||
inline const T& operator()() const;
|
|
||||||
|
|
||||||
inline const_iterator& operator++();
|
|
||||||
inline const_iterator operator++(int);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//- const_iterator set to the beginning of the HashTbl
|
|
||||||
inline const_iterator cbegin() const;
|
|
||||||
|
|
||||||
//- const_iterator set to the beginning of the HashTbl
|
|
||||||
inline const_iterator begin() const;
|
|
||||||
|
|
||||||
|
|
||||||
// IOstream Operator
|
|
||||||
|
|
||||||
friend Istream& operator>> <T, Key, Hash>
|
|
||||||
(
|
|
||||||
Istream&,
|
|
||||||
HashTbl<T, Key, Hash>&
|
|
||||||
);
|
|
||||||
|
|
||||||
friend Ostream& operator<< <T, Key, Hash>
|
|
||||||
(
|
|
||||||
Ostream&,
|
|
||||||
const HashTbl<T, Key, Hash>&
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
# include "HashTblI.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#ifndef NoHashTblC
|
|
||||||
#ifdef NoRepository
|
|
||||||
# include "HashTbl.C"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,530 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by the
|
|
||||||
Free Software Foundation; either version 2 of the License, or (at your
|
|
||||||
option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "error.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::hashedEntry::hashedEntry
|
|
||||||
(
|
|
||||||
const Key& key,
|
|
||||||
hashedEntry* next,
|
|
||||||
const T& obj
|
|
||||||
)
|
|
||||||
:
|
|
||||||
key_(key),
|
|
||||||
next_(next),
|
|
||||||
obj_(obj)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::label
|
|
||||||
Foam::HashTbl<T, Key, Hash>::hashKeyIndex(const Key& key) const
|
|
||||||
{
|
|
||||||
// size is power of two - this is the modulus
|
|
||||||
return Hash()(key) & (tableSize_ - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::label Foam::HashTbl<T, Key, Hash>::capacity() const
|
|
||||||
{
|
|
||||||
return tableSize_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::label Foam::HashTbl<T, Key, Hash>::size() const
|
|
||||||
{
|
|
||||||
return nElmts_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTbl<T, Key, Hash>::empty() const
|
|
||||||
{
|
|
||||||
return !nElmts_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTbl<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::HashTbl<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::HashTbl<T, Key, Hash> >
|
|
||||||
Foam::HashTbl<T, Key, Hash>::xfer()
|
|
||||||
{
|
|
||||||
return xferMove(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline T& Foam::HashTbl<T, Key, Hash>::operator[](const Key& key)
|
|
||||||
{
|
|
||||||
iterator iter = find(key);
|
|
||||||
|
|
||||||
if (iter == end())
|
|
||||||
{
|
|
||||||
FatalErrorIn("HashTbl<T, Key, Hash>::operator[](const Key&)")
|
|
||||||
<< key << " not found in table. Valid entries: "
|
|
||||||
<< toc()
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const T& Foam::HashTbl<T, Key, Hash>::operator[](const Key& key) const
|
|
||||||
{
|
|
||||||
const_iterator iter = find(key);
|
|
||||||
|
|
||||||
if (iter == cend())
|
|
||||||
{
|
|
||||||
FatalErrorIn("HashTbl<T, Key, Hash>::operator[](const Key&) const")
|
|
||||||
<< key << " not found in table. Valid entries: "
|
|
||||||
<< toc()
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline T& Foam::HashTbl<T, Key, Hash>::operator()(const Key& key)
|
|
||||||
{
|
|
||||||
iterator iter = find(key);
|
|
||||||
|
|
||||||
if (iter == end())
|
|
||||||
{
|
|
||||||
insert(key, T());
|
|
||||||
return *find(key);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return *iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * iterator base * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::iteratorBase::iteratorBase()
|
|
||||||
:
|
|
||||||
hashTable_(0),
|
|
||||||
entryPtr_(0),
|
|
||||||
hashIndex_(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::iteratorBase::iteratorBase
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>* hashTbl
|
|
||||||
)
|
|
||||||
:
|
|
||||||
hashTable_(const_cast<HashTbl<T, Key, Hash>*>(hashTbl)),
|
|
||||||
entryPtr_(0),
|
|
||||||
hashIndex_(0)
|
|
||||||
{
|
|
||||||
if (hashTable_->nElmts_ && hashTable_->table_)
|
|
||||||
{
|
|
||||||
// find first non-NULL table entry
|
|
||||||
while
|
|
||||||
(
|
|
||||||
!(entryPtr_ = hashTable_->table_[hashIndex_])
|
|
||||||
&& ++hashIndex_ < hashTable_->tableSize_
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
if (hashIndex_ >= hashTable_->tableSize_)
|
|
||||||
{
|
|
||||||
// make into an end iterator
|
|
||||||
entryPtr_ = 0;
|
|
||||||
hashIndex_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::iteratorBase::iteratorBase
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>* hashTbl,
|
|
||||||
const hashedEntry* elmt,
|
|
||||||
const label hashIndex
|
|
||||||
)
|
|
||||||
:
|
|
||||||
hashTable_(const_cast<HashTbl<T, Key, Hash>*>(hashTbl)),
|
|
||||||
entryPtr_(const_cast<hashedEntry*>(elmt)),
|
|
||||||
hashIndex_(hashIndex)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline void
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iteratorBase::increment()
|
|
||||||
{
|
|
||||||
// A negative index is a special value from erase
|
|
||||||
if (hashIndex_ < 0)
|
|
||||||
{
|
|
||||||
// the markPos='-curPos-1', but we wish to continue at 'curPos-1'
|
|
||||||
// thus use '-(markPos+1) -1'
|
|
||||||
hashIndex_ = -(hashIndex_+1) - 1;
|
|
||||||
}
|
|
||||||
else if (entryPtr_)
|
|
||||||
{
|
|
||||||
if (entryPtr_->next_)
|
|
||||||
{
|
|
||||||
// Move to next element on the SLList
|
|
||||||
entryPtr_ = entryPtr_->next_;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// // if we reach here (entryPtr_ is NULL) it is already at the end()
|
|
||||||
// // we should probably stop
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// Step to the next table entry
|
|
||||||
while
|
|
||||||
(
|
|
||||||
++hashIndex_ < hashTable_->tableSize_
|
|
||||||
&& !(entryPtr_ = hashTable_->table_[hashIndex_])
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
if (hashIndex_ >= hashTable_->tableSize_)
|
|
||||||
{
|
|
||||||
// make into an end iterator
|
|
||||||
entryPtr_ = 0;
|
|
||||||
hashIndex_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline
|
|
||||||
const Key& Foam::HashTbl<T, Key, Hash>::iteratorBase::key() const
|
|
||||||
{
|
|
||||||
return entryPtr_->key_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline T&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iteratorBase::object()
|
|
||||||
{
|
|
||||||
return entryPtr_->obj_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const T&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iteratorBase::cobject() const
|
|
||||||
{
|
|
||||||
return entryPtr_->obj_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTbl<T, Key, Hash>::iteratorBase::operator==
|
|
||||||
(
|
|
||||||
const iteratorBase& iter
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return entryPtr_ == iter.entryPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTbl<T, Key, Hash>::iteratorBase::operator!=
|
|
||||||
(
|
|
||||||
const iteratorBase& iter
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return entryPtr_ != iter.entryPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTbl<T, Key, Hash>::iteratorBase::operator==
|
|
||||||
(
|
|
||||||
const iteratorEnd&
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return !entryPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline bool Foam::HashTbl<T, Key, Hash>::iteratorBase::operator!=
|
|
||||||
(
|
|
||||||
const iteratorEnd&
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return entryPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::iterator::iterator()
|
|
||||||
:
|
|
||||||
iteratorBase()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::iterator::iterator
|
|
||||||
(
|
|
||||||
const iteratorEnd&
|
|
||||||
)
|
|
||||||
:
|
|
||||||
iteratorBase()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::iterator::iterator
|
|
||||||
(
|
|
||||||
HashTbl<T, Key, Hash>* hashTbl
|
|
||||||
)
|
|
||||||
:
|
|
||||||
iteratorBase(hashTbl)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::iterator::iterator
|
|
||||||
(
|
|
||||||
HashTbl<T, Key, Hash>* hashTbl,
|
|
||||||
hashedEntry* elmt,
|
|
||||||
const label hashIndex
|
|
||||||
)
|
|
||||||
:
|
|
||||||
iteratorBase(hashTbl, elmt, hashIndex)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::iterator::operator
|
|
||||||
typename Foam::HashTbl<T, Key, Hash>::const_iterator() const
|
|
||||||
{
|
|
||||||
return *reinterpret_cast
|
|
||||||
<
|
|
||||||
const typename Foam::HashTbl<T, Key, Hash>::const_iterator*
|
|
||||||
>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline T&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iterator::operator*()
|
|
||||||
{
|
|
||||||
return this->object();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline T&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iterator::operator()()
|
|
||||||
{
|
|
||||||
return this->object();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const T&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iterator::operator*() const
|
|
||||||
{
|
|
||||||
return this->cobject();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const T&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iterator::operator()() const
|
|
||||||
{
|
|
||||||
return this->cobject();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline
|
|
||||||
typename Foam::HashTbl<T, Key, Hash>::iterator&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iterator::operator++()
|
|
||||||
{
|
|
||||||
this->increment();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline typename Foam::HashTbl<T, Key, Hash>::iterator
|
|
||||||
Foam::HashTbl<T, Key, Hash>::iterator::operator++(int)
|
|
||||||
{
|
|
||||||
iterator old = *this;
|
|
||||||
this->increment();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline typename Foam::HashTbl<T, Key, Hash>::iterator
|
|
||||||
Foam::HashTbl<T, Key, Hash>::begin()
|
|
||||||
{
|
|
||||||
return iterator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::const_iterator::const_iterator()
|
|
||||||
:
|
|
||||||
iteratorBase()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::const_iterator::const_iterator
|
|
||||||
(
|
|
||||||
const iteratorEnd&
|
|
||||||
)
|
|
||||||
:
|
|
||||||
iteratorBase()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::const_iterator::const_iterator
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>* hashTbl
|
|
||||||
)
|
|
||||||
:
|
|
||||||
iteratorBase(hashTbl)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline Foam::HashTbl<T, Key, Hash>::const_iterator::const_iterator
|
|
||||||
(
|
|
||||||
const HashTbl<T, Key, Hash>* hashTbl,
|
|
||||||
const hashedEntry* elmt,
|
|
||||||
const label hashIndex
|
|
||||||
)
|
|
||||||
:
|
|
||||||
iteratorBase(hashTbl, elmt, hashIndex)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const T&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::const_iterator::operator*() const
|
|
||||||
{
|
|
||||||
return this->cobject();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline const T&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::const_iterator::operator()() const
|
|
||||||
{
|
|
||||||
return this->cobject();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline
|
|
||||||
typename Foam::HashTbl<T, Key, Hash>::const_iterator&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::const_iterator::operator++()
|
|
||||||
{
|
|
||||||
this->increment();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline typename Foam::HashTbl<T, Key, Hash>::const_iterator
|
|
||||||
Foam::HashTbl<T, Key, Hash>::const_iterator::operator++(int)
|
|
||||||
{
|
|
||||||
const_iterator old = *this;
|
|
||||||
this->increment();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline typename Foam::HashTbl<T, Key, Hash>::const_iterator
|
|
||||||
Foam::HashTbl<T, Key, Hash>::cbegin() const
|
|
||||||
{
|
|
||||||
return const_iterator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
inline typename Foam::HashTbl<T, Key, Hash>::const_iterator
|
|
||||||
Foam::HashTbl<T, Key, Hash>::begin() const
|
|
||||||
{
|
|
||||||
return this->cbegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,249 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by the
|
|
||||||
Free Software Foundation; either version 2 of the License, or (at your
|
|
||||||
option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "HashTbl.H"
|
|
||||||
#include "Istream.H"
|
|
||||||
#include "Ostream.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::HashTbl<T, Key, Hash>::HashTbl(Istream& is, const label size)
|
|
||||||
:
|
|
||||||
HashTblCore(),
|
|
||||||
nElmts_(0),
|
|
||||||
tableSize_(HashTblCore::canonicalSize(size)),
|
|
||||||
table_(NULL)
|
|
||||||
{
|
|
||||||
if (tableSize_)
|
|
||||||
{
|
|
||||||
table_ = new hashedEntry*[tableSize_];
|
|
||||||
|
|
||||||
for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
|
|
||||||
{
|
|
||||||
table_[hashIdx] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator>>(is, *this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::Ostream&
|
|
||||||
Foam::HashTbl<T, Key, Hash>::printInfo(Ostream& os) const
|
|
||||||
{
|
|
||||||
label used = 0;
|
|
||||||
label maxChain = 0;
|
|
||||||
unsigned avgChain = 0;
|
|
||||||
|
|
||||||
for (label hashIdx = 0; hashIdx < tableSize_; ++hashIdx)
|
|
||||||
{
|
|
||||||
label count = 0;
|
|
||||||
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
|
||||||
{
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count)
|
|
||||||
{
|
|
||||||
++used;
|
|
||||||
avgChain += count;
|
|
||||||
|
|
||||||
if (maxChain < count)
|
|
||||||
{
|
|
||||||
maxChain = count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
os << "HashTbl<T,Key,Hash>"
|
|
||||||
<< " elements:" << size() << " slots:" << used << "/" << tableSize_
|
|
||||||
<< " chaining(avg/max):" << (used ? (float(avgChain)/used) : 0)
|
|
||||||
<< "/" << maxChain << endl;
|
|
||||||
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::Istream& Foam::operator>>
|
|
||||||
(
|
|
||||||
Istream& is,
|
|
||||||
HashTbl<T, Key, Hash>& L
|
|
||||||
)
|
|
||||||
{
|
|
||||||
is.fatalCheck("operator>>(Istream&, HashTbl<T, Key, Hash>&)");
|
|
||||||
|
|
||||||
// Anull list
|
|
||||||
L.clear();
|
|
||||||
|
|
||||||
is.fatalCheck("operator>>(Istream&, HashTbl<T, Key, Hash>&)");
|
|
||||||
|
|
||||||
token firstToken(is);
|
|
||||||
|
|
||||||
is.fatalCheck
|
|
||||||
(
|
|
||||||
"operator>>(Istream&, HashTbl<T, Key, Hash>&) : "
|
|
||||||
"reading first token"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (firstToken.isLabel())
|
|
||||||
{
|
|
||||||
label s = firstToken.labelToken();
|
|
||||||
|
|
||||||
// Read beginning of contents
|
|
||||||
char delimiter = is.readBeginList("HashTbl<T, Key, Hash>");
|
|
||||||
|
|
||||||
if (s)
|
|
||||||
{
|
|
||||||
if (2*s > L.tableSize_)
|
|
||||||
{
|
|
||||||
L.resize(2*s);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delimiter == token::BEGIN_LIST)
|
|
||||||
{
|
|
||||||
for (label i=0; i<s; i++)
|
|
||||||
{
|
|
||||||
Key key;
|
|
||||||
is >> key;
|
|
||||||
L.insert(key, pTraits<T>(is));
|
|
||||||
|
|
||||||
is.fatalCheck
|
|
||||||
(
|
|
||||||
"operator>>(Istream&, HashTbl<T, Key, Hash>&) : "
|
|
||||||
"reading entry"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FatalIOErrorIn
|
|
||||||
(
|
|
||||||
"operator>>(Istream&, HashTbl<T, Key, Hash>&)",
|
|
||||||
is
|
|
||||||
) << "incorrect first token, '(', found " << firstToken.info()
|
|
||||||
<< exit(FatalIOError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read end of contents
|
|
||||||
is.readEndList("HashTbl");
|
|
||||||
}
|
|
||||||
else if (firstToken.isPunctuation())
|
|
||||||
{
|
|
||||||
if (firstToken.pToken() != token::BEGIN_LIST)
|
|
||||||
{
|
|
||||||
FatalIOErrorIn
|
|
||||||
(
|
|
||||||
"operator>>(Istream&, HashTbl<T, Key, Hash>&)",
|
|
||||||
is
|
|
||||||
) << "incorrect first token, '(', found " << firstToken.info()
|
|
||||||
<< exit(FatalIOError);
|
|
||||||
}
|
|
||||||
|
|
||||||
token lastToken(is);
|
|
||||||
while
|
|
||||||
(
|
|
||||||
!(
|
|
||||||
lastToken.isPunctuation()
|
|
||||||
&& lastToken.pToken() == token::END_LIST
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
is.putBack(lastToken);
|
|
||||||
|
|
||||||
Key key;
|
|
||||||
is >> key;
|
|
||||||
|
|
||||||
T element;
|
|
||||||
is >> element;
|
|
||||||
|
|
||||||
L.insert(key, element);
|
|
||||||
|
|
||||||
is.fatalCheck
|
|
||||||
(
|
|
||||||
"operator>>(Istream&, HashTbl<T, Key, Hash>&) : "
|
|
||||||
"reading entry"
|
|
||||||
);
|
|
||||||
|
|
||||||
is >> lastToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FatalIOErrorIn
|
|
||||||
(
|
|
||||||
"operator>>(Istream&, HashTbl<T, Key, Hash>&)",
|
|
||||||
is
|
|
||||||
) << "incorrect first token, expected <int> or '(', found "
|
|
||||||
<< firstToken.info()
|
|
||||||
<< exit(FatalIOError);
|
|
||||||
}
|
|
||||||
|
|
||||||
is.fatalCheck("operator>>(Istream&, HashTbl<T, Key, Hash>&)");
|
|
||||||
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Key, class Hash>
|
|
||||||
Foam::Ostream& Foam::operator<<
|
|
||||||
(
|
|
||||||
Ostream& os,
|
|
||||||
const HashTbl<T, Key, Hash>& L
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Write size and start delimiter
|
|
||||||
os << nl << L.size() << nl << token::BEGIN_LIST << nl;
|
|
||||||
|
|
||||||
// Write contents
|
|
||||||
for
|
|
||||||
(
|
|
||||||
typename HashTbl<T, Key, Hash>::const_iterator iter = L.cbegin();
|
|
||||||
iter != L.cend();
|
|
||||||
++iter
|
|
||||||
)
|
|
||||||
{
|
|
||||||
os << iter.key() << token::SPACE << iter() << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write end delimiter
|
|
||||||
os << token::END_LIST;
|
|
||||||
|
|
||||||
// Check state of IOstream
|
|
||||||
os.check("Ostream& operator<<(Ostream&, const HashTbl&)");
|
|
||||||
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
Reference in New Issue
Block a user