Activate the reworked HashTable

- previous draft version was HashTbl
- accidentally still had canonicalSize in templated code
This commit is contained in:
Mark Olesen
2009-11-04 09:06:26 +01:00
parent ebe39c4ea4
commit c7c9a6e003
11 changed files with 591 additions and 2550 deletions

View File

@ -61,8 +61,7 @@ $(sha1)/SHA1Digest.C
primitives/random/Random.C
containers/HashTables/HashTbl/HashTblCore.C
containers/HashTables/HashTable/HashTableName.C
containers/HashTables/HashTable/HashTableCore.C
containers/HashTables/StaticHashTable/StaticHashTableCore.C
containers/Lists/SortableList/ParSortableListName.C
containers/Lists/PackedList/PackedListName.C

View File

@ -30,44 +30,15 @@ License
#include "HashTable.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 * * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
Foam::HashTable<T, Key, Hash>::HashTable(const label size)
:
HashTableName(),
HashTableCore(),
nElmts_(0),
tableSize_(canonicalSize(size)),
table_(NULL),
endIter_(*this, NULL, 0),
endConstIter_(*this, NULL, 0)
tableSize_(HashTableCore::canonicalSize(size)),
table_(NULL)
{
if (tableSize_)
{
@ -84,12 +55,10 @@ Foam::HashTable<T, Key, Hash>::HashTable(const label size)
template<class T, class Key, class Hash>
Foam::HashTable<T, Key, Hash>::HashTable(const HashTable<T, Key, Hash>& ht)
:
HashTableName(),
HashTableCore(),
nElmts_(0),
tableSize_(ht.tableSize_),
table_(NULL),
endIter_(*this, NULL, 0),
endConstIter_(*this, NULL, 0)
table_(NULL)
{
if (tableSize_)
{
@ -113,12 +82,10 @@ Foam::HashTable<T, Key, Hash>::HashTable
const Xfer<HashTable<T, Key, Hash> >& ht
)
:
HashTableName(),
HashTableCore(),
nElmts_(0),
tableSize_(0),
table_(NULL),
endIter_(*this, NULL, 0),
endConstIter_(*this, NULL, 0)
table_(NULL)
{
transfer(ht());
}
@ -182,7 +149,7 @@ Foam::HashTable<T, Key, Hash>::find
{
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
return end();
return iterator();
}
@ -214,7 +181,7 @@ Foam::HashTable<T, Key, Hash>::find
{
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
return cend();
return const_iterator();
}
template<class T, class Key, class Hash>
Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
{
List<Key> tofc(nElmts_);
label i = 0;
List<Key> keys(nElmts_);
label keyI = 0;
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>
Foam::List<Key> Foam::HashTable<T, Key, Hash>::sortedToc() const
{
List<Key> sortedList = this->toc();
sort(sortedList);
List<Key> sortedLst = this->toc();
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);
nElmts_++;
if (double(nElmts_)/tableSize_ > 0.8)
if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize)
{
# ifdef FULLDEBUG
if (debug)
@ -342,18 +309,22 @@ bool Foam::HashTable<T, Key, Hash>::set
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 elmtPtr_
// Search element before entryPtr_
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;
}
@ -362,98 +333,76 @@ bool Foam::HashTable<T, Key, Hash>::erase(const iterator& cit)
if (prev)
{
// Have element before elmtPtr
prev->next_ = it.elmtPtr_->next_;
delete it.elmtPtr_;
it.elmtPtr_ = prev;
// has an element before entryPtr - reposition to there
prev->next_ = entryPtr_->next_;
delete entryPtr_;
entryPtr_ = prev;
}
else
{
// elmtPtr is first element on SLList
table_[it.hashIndex_] = it.elmtPtr_->next_;
delete it.elmtPtr_;
// entryPtr was first element on SLList
hashTable_->table_[hashIndex_] = entryPtr_->next_;
delete entryPtr_;
// Search back for previous non-zero table entry
while (--it.hashIndex_ >= 0 && !table_[it.hashIndex_])
{}
// assign any non-NULL pointer value so it doesn't look
// like end()/cend()
entryPtr_ = reinterpret_cast<hashedEntry*>(this);
if (it.hashIndex_ >= 0)
{
// In table entry search for last element
it.elmtPtr_ = table_[it.hashIndex_];
while (it.elmtPtr_ && it.elmtPtr_->next_)
{
it.elmtPtr_ = it.elmtPtr_->next_;
}
}
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;
}
// 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;
}
nElmts_--;
# ifdef FULLDEBUG
if (debug)
{
Info<< "HashTable<T, Key, Hash>::erase(iterator&) : "
<< "hashedEntry " << it.elmtPtr_->key_ << " removed.\n";
}
# endif
hashTable_->nElmts_--;
return true;
}
else
{
# ifdef FULLDEBUG
if (debug)
{
Info<< "HashTable<T, Key, Hash>::erase(iterator&) : "
<< "cannot remove hashedEntry from hash table\n";
}
# endif
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>
bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
{
iterator fnd = find(key);
if (fnd != end())
{
return erase(fnd);
}
else
{
return false;
}
return erase(find(key));
}
template<class T, class Key, class Hash>
Foam::label Foam::HashTable<T, Key, Hash>::erase(const UList<Key>& keys)
{
const label nTotal = nElmts_;
label count = 0;
// Remove listed keys from this table
if (this->size())
// Remove listed keys from this table - terminates early if possible
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 AnyType>
template<class AnyType, class AnyHash>
Foam::label Foam::HashTable<T, Key, Hash>::erase
(
const HashTable<AnyType, Key, Hash>& rhs
const HashTable<AnyType, Key, AnyHash>& rhs
)
{
label count = 0;
// Remove rhs elements from this table
if (this->size())
// 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)
{
// NOTE: could further optimize depending on which hash is smaller
for (iterator iter = begin(); iter != end(); ++iter)
if (rhs.found(iter.key()) && erase(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>
void Foam::HashTable<T, Key, Hash>::resize(const label sz)
{
label newSize = canonicalSize(sz);
label newSize = HashTableCore::canonicalSize(sz);
if (newSize == tableSize_)
{
@ -505,22 +451,22 @@ void Foam::HashTable<T, Key, Hash>::resize(const label sz)
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)
{
newTable->insert(iter.key(), *iter);
tmpTable->insert(iter.key(), *iter);
}
label oldTableSize = tableSize_;
tableSize_ = newTable->tableSize_;
newTable->tableSize_ = oldTableSize;
label oldSize = tableSize_;
tableSize_ = tmpTable->tableSize_;
tmpTable->tableSize_ = oldSize;
hashedEntry** oldTable = table_;
table_ = newTable->table_;
newTable->table_ = oldTable;
table_ = tmpTable->table_;
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>
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
{
// Are all my elements in rhs?
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
// sizes (number of keys) must match
if (size() != rhs.size())
{
const_iterator fnd = rhs.find(iter.key());
if (fnd == rhs.cend() || fnd() != iter())
{
return false;
}
return false;
}
// Are all rhs elements in me?
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
{
const_iterator fnd = find(iter.key());
@ -640,6 +593,7 @@ bool Foam::HashTable<T, Key, Hash>::operator==
return false;
}
}
return true;
}

View File

@ -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>
class HashTable
:
public HashTableName
public HashTableCore
{
// Private data type for table entries
//- Structure to hold a hashed entry with SLList for collisions
struct hashedEntry
{
//- The lookup key
@ -99,18 +136,15 @@ class HashTable
//- The data object
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
inline hashedEntry
(
const Key&,
hashedEntry* next,
const T& newEntry
);
private:
//- Disallow default bitwise copy construct
hashedEntry(const hashedEntry&);
//- Dissallow construction as copy
hashedEntry(const hashedEntry&);
//- Disallow default bitwise assignment
void operator=(const hashedEntry&);
};
@ -119,7 +153,7 @@ class HashTable
//- The current number of elements in table
label nElmts_;
//- Number of primary entries allocated in table (not necessarily used)
//- Number of primary entries allocated in table
label tableSize_;
//- The table of primary entries
@ -140,17 +174,23 @@ class HashTable
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;
// Forward declaration of STL iterators
class iterator;
//- Declare friendship with the iterator
friend class iterator;
class const_iterator;
//- Declare friendship with the const_iterator
friend class const_iterator;
@ -178,7 +218,10 @@ public:
// 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;
//- Return true if the hash table is empty
@ -212,10 +255,11 @@ public:
//- Assign a new hashedEntry, overwriting existing entries
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&);
//- Erase an hashedEntry specified by given key if in table
//- Erase a hashedEntry specified by the given key
bool erase(const Key&);
//- 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
// Return the number of elements removed.
// The parameter HashTable needs the same type of keys, but
// but the type of values held is arbitrary.
template<class AnyType>
label erase(const HashTable<AnyType, Key, Hash>&);
// The parameter HashTable 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 HashTable<AnyType, Key, AnyHash>&);
//- Resize the hash table for efficiency
void resize(const label newSize);
@ -239,31 +283,33 @@ public:
// 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(HashTable<T, Key, Hash>&);
//- Transfer contents to the Xfer container
inline Xfer<HashTable<T, Key, Hash> > xfer();
inline Xfer< HashTable<T, Key, Hash> > xfer();
// Member Operators
//- Find and return an hashedEntry
//- Find and return a hashedEntry
inline T& operator[](const Key&);
//- Find and return an hashedEntry
//- Find and return a hashedEntry
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&);
//- Assignment
void operator=(const HashTable<T, Key, Hash>&);
//- Equality. Two hash tables are equal if all contents of first are
// also in second and vice versa. So does not depend on table size or
// order!
//- Equality. Hash tables are equal if the keys and values are equal.
// Independent of table storage size and table order.
bool operator==(const HashTable<T, Key, Hash>&) const;
//- The opposite of the equality operation. Takes linear time.
@ -289,134 +335,193 @@ public:
typedef label size_type;
// STL iterator
// Iterators and helpers
//- An STL-conforming iterator
class iterator
//- The iterator base for HashTable
// 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;
friend class const_iterator;
// Private Data
// Private data
//- Reference to the HashTable this is an iterator for
HashTable<T, Key, Hash>& hashTable_;
//- Pointer to the HashTable for which this is an iterator
// This also lets us use the default bitwise copy/assignment
HashTable<T, Key, Hash>* hashTable_;
//- Current element
hashedEntry* elmtPtr_;
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 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:
// Constructors
//- Construct from hash table, element and hash index
inline iterator
(
HashTable<T, Key, Hash>& curHashTable,
hashedEntry* elmt,
label hashIndex
);
//- Construct null (end iterator)
inline iterator();
//- Construct end iterator
inline iterator(const iteratorEnd& unused);
// Member operators
inline void operator=(const iterator&);
//- Conversion to a const_iterator
inline operator const_iterator() const;
inline bool operator==(const iterator&) const;
inline bool operator!=(const iterator&) const;
inline bool operator==(const const_iterator&) const;
inline bool operator!=(const 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);
inline const Key& key() const;
};
//- iterator set to the begining of the HashTable
inline iterator begin();
//- iterator set to beyond the end of the HashTable
inline const iterator& end();
// STL const_iterator
//- An STL-conforming 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
const HashTable<T, Key, Hash>& hashTable_;
//- Current element
const hashedEntry* elmtPtr_;
//- Current hash index
label hashIndex_;
//- Construct from hash table, moving to its 'begin' position
inline explicit const_iterator
(
const HashTable<T, Key, Hash>* curHashTable
);
//- 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:
// Constructors
//- Construct from hash table, element and hash index
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 null (end iterator)
inline const_iterator();
//- Construct end iterator
inline const_iterator(const iteratorEnd& unused);
// Member operators
inline void operator=(const const_iterator&);
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;
// Access
//- Return referenced hash value
inline const T& operator*() const;
inline const T& operator()() const;
inline const_iterator& operator++();
inline const_iterator operator++(int);
inline const Key& key() const;
};
//- const_iterator set to the beginning of the HashTable
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
inline const_iterator begin() const;
//- const_iterator set to beyond the end of the HashTable
inline const const_iterator& end() const;
// IOstream Operator
@ -432,14 +537,6 @@ public:
const HashTable<T, Key, Hash>&
);
private:
//- iterator returned by end()
iterator endIter_;
//- const_iterator returned by end()
const_iterator endConstIter_;
};

View File

@ -24,18 +24,44 @@ License
\*---------------------------------------------------------------------------*/
#include "HashTbl.H"
#include "HashTable.H"
// * * * * * * * * * * * * * * 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
)
);
// * * * * * * * * * * * * * * 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;
}
// ************************************************************************* //

View File

@ -33,12 +33,12 @@ inline Foam::HashTable<T, Key, Hash>::hashedEntry::hashedEntry
(
const Key& key,
hashedEntry* next,
const T& newEntry
const T& obj
)
:
key_(key),
next_(next),
obj_(newEntry)
obj_(obj)
{}
@ -55,6 +55,13 @@ Foam::HashTable<T, Key, Hash>::hashKeyIndex(const Key& key) const
// * * * * * * * * * * * * * * * 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>
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>
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,
hashedEntry* elmt,
label hashIndex
const HashTable<T, Key, Hash>* hashTbl
)
:
hashTable_(hashTbl),
elmtPtr_(elmt),
hashTable_(const_cast<HashTable<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::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)
{}
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_;
hashIndex_ = iter.hashIndex_;
}
:
iteratorBase()
{}
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
) const
{
return elmtPtr_ == iter.elmtPtr_;
}
HashTable<T, Key, Hash>* hashTbl
)
:
iteratorBase(hashTbl)
{}
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
) const
{
return elmtPtr_ != iter.elmtPtr_;
}
HashTable<T, Key, Hash>* hashTbl,
hashedEntry* elmt,
const label hashIndex
)
:
iteratorBase(hashTbl, elmt, hashIndex)
{}
template<class T, class Key, class Hash>
inline bool Foam::HashTable<T, Key, Hash>::iterator::operator==
(
const const_iterator& iter
) const
inline Foam::HashTable<T, Key, Hash>::iterator::operator
typename Foam::HashTable<T, Key, Hash>::const_iterator() const
{
return elmtPtr_ == iter.elmtPtr_;
}
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_;
return *reinterpret_cast
<
const typename Foam::HashTable<T, Key, Hash>::const_iterator*
>(this);
}
@ -223,7 +378,7 @@ template<class T, class Key, class Hash>
inline T&
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&
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&
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&
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&
Foam::HashTable<T, Key, Hash>::iterator::operator++()
{
// Check for special value from erase. (sets hashIndex to -1)
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;
}
this->increment();
return *this;
}
template<class T, class Key, class Hash>
inline typename Foam::HashTable<T, Key, Hash>::iterator
Foam::HashTable<T, Key, Hash>::iterator::operator++
(
int
)
Foam::HashTable<T, Key, Hash>::iterator::operator++(int)
{
iterator tmp = *this;
++*this;
return tmp;
}
template<class T, class Key, class Hash>
inline
const Key& Foam::HashTable<T, Key, Hash>::iterator::key() const
{
return elmtPtr_->key_;
iterator old = *this;
this->increment();
return old;
}
@ -310,135 +430,64 @@ template<class T, class Key, class Hash>
inline typename Foam::HashTable<T, Key, Hash>::iterator
Foam::HashTable<T, Key, Hash>::begin()
{
label i = 0;
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_;
return iterator(this);
}
// * * * * * * * * * * * * * * * 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>
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,
label hashIndex
const label hashIndex
)
:
hashTable_(hashTbl),
elmtPtr_(elmt),
hashIndex_(hashIndex)
iteratorBase(hashTbl, elmt, 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>
inline const T&
Foam::HashTable<T, Key, Hash>::const_iterator::operator*() const
{
return elmtPtr_->obj_;
return this->cobject();
}
template<class T, class Key, class Hash>
inline const T&
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&
Foam::HashTable<T, Key, Hash>::const_iterator::operator++()
{
if
(
!(elmtPtr_ = elmtPtr_->next_)
&& ++hashIndex_ < hashTable_.tableSize_
&& !(elmtPtr_ = hashTable_.table_[hashIndex_])
)
{
while
(
++hashIndex_ < hashTable_.tableSize_
&& !(elmtPtr_ = hashTable_.table_[hashIndex_])
)
{}
}
this->increment();
return *this;
}
template<class T, class Key, class Hash>
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
Foam::HashTable<T, Key, Hash>::const_iterator::operator++
(
int
)
Foam::HashTable<T, Key, Hash>::const_iterator::operator++(int)
{
const_iterator tmp = *this;
++*this;
return tmp;
}
template<class T, class Key, class Hash>
inline
const Key& Foam::HashTable<T, Key, Hash>::const_iterator::key() const
{
return elmtPtr_->key_;
const_iterator old = *this;
this->increment();
return old;
}
@ -491,41 +515,7 @@ template<class T, class Key, class Hash>
inline typename Foam::HashTable<T, Key, Hash>::const_iterator
Foam::HashTable<T, Key, Hash>::cbegin() const
{
label i = 0;
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_;
return const_iterator(this);
}
@ -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_;
}
// ************************************************************************* //

View File

@ -33,16 +33,19 @@ License
template<class T, class Key, class Hash>
Foam::HashTable<T, Key, Hash>::HashTable(Istream& is, const label size)
:
HashTableName(),
HashTableCore(),
nElmts_(0),
tableSize_(canonicalSize(size)),
table_(new hashedEntry*[tableSize_]),
endIter_(*this, NULL, 0),
endConstIter_(*this, NULL, 0)
tableSize_(HashTableCore::canonicalSize(size)),
table_(NULL)
{
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);

View File

@ -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);
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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();
}
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //