From 55a89e9db3d78dca419db5f10256b60a1306d076 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@Germany>
Date: Fri, 30 Oct 2009 18:31:28 +0100
Subject: [PATCH] added HashTbl as development replacement for HashTable

- rename to HashTable later when it is considered stable
---
 applications/test/HashTable3/Make/files       |   3 +
 applications/test/HashTable3/Make/options     |   2 +
 applications/test/HashTable3/hashTableTest3.C |  83 +++
 src/OpenFOAM/Make/files                       |   1 +
 .../containers/HashTables/HashTbl/HashTbl.C   | 665 ++++++++++++++++++
 .../containers/HashTables/HashTbl/HashTbl.H   | 466 ++++++++++++
 .../containers/HashTables/HashTbl/HashTblI.H  | 548 +++++++++++++++
 .../containers/HashTables/HashTbl/HashTblIO.C | 246 +++++++
 .../HashTables/HashTbl/HashTblName.C          |  33 +
 9 files changed, 2047 insertions(+)
 create mode 100644 applications/test/HashTable3/Make/files
 create mode 100644 applications/test/HashTable3/Make/options
 create mode 100644 applications/test/HashTable3/hashTableTest3.C
 create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C
 create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H
 create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H
 create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTblIO.C
 create mode 100644 src/OpenFOAM/containers/HashTables/HashTbl/HashTblName.C

diff --git a/applications/test/HashTable3/Make/files b/applications/test/HashTable3/Make/files
new file mode 100644
index 00000000000..e8ec193ffa2
--- /dev/null
+++ b/applications/test/HashTable3/Make/files
@@ -0,0 +1,3 @@
+hashTableTest3.C
+
+EXE = $(FOAM_USER_APPBIN)/hashTableTest3
diff --git a/applications/test/HashTable3/Make/options b/applications/test/HashTable3/Make/options
new file mode 100644
index 00000000000..6a9e9810b3d
--- /dev/null
+++ b/applications/test/HashTable3/Make/options
@@ -0,0 +1,2 @@
+/* EXE_INC = -I$(LIB_SRC)/cfdTools/include */
+/* EXE_LIBS = -lfiniteVolume */
diff --git a/applications/test/HashTable3/hashTableTest3.C b/applications/test/HashTable3/hashTableTest3.C
new file mode 100644
index 00000000000..422e35696c0
--- /dev/null
+++ b/applications/test/HashTable3/hashTableTest3.C
@@ -0,0 +1,83 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2009-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
+
+Description
+
+    Test speeds for some HashTable operations
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "HashTable.H"
+#include "HashPtrTable.H"
+#include "Map.H"
+#include "StaticHashTable.H"
+#include "HashTbl.H"
+#include "cpuTime.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// Main program:
+
+int main(int argc, char *argv[])
+{
+    const label nLoops = 30;
+    const label nBase  = 100000;
+    const label nSize  = nLoops * nBase;
+
+    cpuTime timer;
+
+    // ie, a
+    // Map<label> map(2 * nSize);
+    // HashTable<label, label, Hash<label> > map(2 * nSize);
+    // StaticHashTable<label, label, Hash<label> > map(2 * nSize);
+    HashTbl<label, label, Hash<label> > map(2 * nSize);
+
+    Info<< "Constructed map of size: " << nSize
+        << "  " << timer.cpuTimeIncrement() << " s\n\n";
+
+    for (label i = 0; i < nSize; i++)
+    {
+        map.insert(i, i);
+    }
+    Info<< "Inserted " << nSize << " elements: "
+        << timer.cpuTimeIncrement() << " s\n\n";
+
+
+    label elemI = 0;
+    for (label iLoop = 0; iLoop < nLoops; iLoop++)
+    {
+        for (label i = 0; i < nBase; i++)
+        {
+            map.erase(elemI++);
+        }
+        Info<< "loop " << iLoop << " - Erased " << nBase << " elements: "
+            << "  " << timer.cpuTimeIncrement() << " s\n";
+    }
+
+    return 0;
+}
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index 2823c2a9ec3..a290ec2847a 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -61,6 +61,7 @@ $(sha1)/SHA1Digest.C
 
 primitives/random/Random.C
 
+containers/HashTables/HashTbl/HashTblName.C
 containers/HashTables/HashTable/HashTableName.C
 containers/HashTables/StaticHashTable/StaticHashTableName.C
 containers/Lists/SortableList/ParSortableListName.C
diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C
new file mode 100644
index 00000000000..8e7be6b147d
--- /dev/null
+++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C
@@ -0,0 +1,665 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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  * * * * * * * * * * * * //
+
+template<class T, class Key, class Hash>
+Foam::label Foam::HashTbl<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::HashTbl<T, Key, Hash>::HashTbl(const label size)
+:
+    HashTblName(),
+    nElmts_(0),
+    tableSize_(canonicalSize(size)),
+    table_(NULL),
+    endIter_(*this, NULL, 0),
+    endConstIter_(*this, NULL, 0)
+{
+    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)
+:
+    HashTblName(),
+    nElmts_(0),
+    tableSize_(ht.tableSize_),
+    table_(NULL),
+    endIter_(*this, NULL, 0),
+    endConstIter_(*this, NULL, 0)
+{
+    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
+)
+:
+    HashTblName(),
+    nElmts_(0),
+    tableSize_(0),
+    table_(NULL),
+    endIter_(*this, NULL, 0),
+    endConstIter_(*this, NULL, 0)
+{
+    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 end();
+}
+
+
+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 cend();
+}
+
+
+template<class T, class Key, class Hash>
+Foam::List<Key> Foam::HashTbl<T, Key, Hash>::toc() const
+{
+    List<Key> tofc(nElmts_);
+    label i = 0;
+
+    for (const_iterator iter = cbegin(); iter != cend(); ++iter)
+    {
+        tofc[i++] = iter.key();
+    }
+
+    return tofc;
+}
+
+
+template<class T, class Key, class Hash>
+Foam::List<Key> Foam::HashTbl<T, Key, Hash>::sortedToc() const
+{
+    List<Key> sortedList = this->toc();
+    sort(sortedList);
+
+    return sortedList;
+}
+
+
+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)
+        {
+#           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>::erase(const iterator& cit)
+{
+    if (cit.elmtPtr_)    // note: endIter_ also has 0 elmtPtr_
+    {
+        iterator& it = const_cast<iterator&>(cit);
+
+        // Search element before elmtPtr_
+        hashedEntry* prev = 0;
+
+        for (hashedEntry* ep = table_[it.hashIndex_]; ep; ep = ep->next_)
+        {
+            if (ep == it.elmtPtr_)
+            {
+                break;
+            }
+            prev = ep;
+        }
+
+        if (prev)
+        {
+            // Have element before elmtPtr
+            prev->next_ = it.elmtPtr_->next_;
+            delete it.elmtPtr_;
+            it.elmtPtr_ = prev;
+        }
+        else
+        {
+            // elmtPtr is first element on SLList
+            table_[it.hashIndex_] = it.elmtPtr_->next_;
+            delete it.elmtPtr_;
+
+            // Search back for previous non-zero table entry
+            while (--it.hashIndex_ >= 0 && !table_[it.hashIndex_])
+            {}
+
+            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;
+            }
+        }
+
+        nElmts_--;
+
+#       ifdef FULLDEBUG
+        if (debug)
+        {
+            Info<< "HashTbl<T, Key, Hash>::erase(iterator&) : "
+                << "hashedEntry " << it.elmtPtr_->key_ << " removed.\n";
+        }
+#       endif
+
+        return true;
+    }
+    else
+    {
+#       ifdef FULLDEBUG
+        if (debug)
+        {
+            Info<< "HashTbl<T, Key, Hash>::erase(iterator&) : "
+                << "cannot remove hashedEntry from hash table\n";
+        }
+#       endif
+
+        return false;
+    }
+}
+
+
+template<class T, class Key, class Hash>
+bool Foam::HashTbl<T, Key, Hash>::erase(const Key& key)
+{
+    iterator fnd = find(key);
+
+    if (fnd != end())
+    {
+        return erase(fnd);
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+template<class T, class Key, class Hash>
+Foam::label Foam::HashTbl<T, Key, Hash>::erase(const UList<Key>& keys)
+{
+    label count = 0;
+
+    // Remove listed keys from this table
+    if (this->size())
+    {
+        forAll(keys, keyI)
+        {
+            if (erase(keys[keyI]))
+            {
+                count++;
+            }
+        }
+    }
+
+    return count;
+}
+
+
+template<class T, class Key, class Hash>
+template<class AnyType>
+Foam::label Foam::HashTbl<T, Key, Hash>::erase
+(
+    const HashTbl<AnyType, Key, Hash>& rhs
+)
+{
+    label count = 0;
+
+    // Remove rhs elements from this table
+    if (this->size())
+    {
+        // NOTE: could further 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 = 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>* newTable = new HashTbl<T, Key, Hash>(newSize);
+
+    for (const_iterator iter = cbegin(); iter != cend(); ++iter)
+    {
+        newTable->insert(iter.key(), *iter);
+    }
+
+    label oldTableSize = tableSize_;
+    tableSize_ = newTable->tableSize_;
+    newTable->tableSize_ = oldTableSize;
+
+    hashedEntry** oldTable = table_;
+    table_ = newTable->table_;
+    newTable->table_ = oldTable;
+
+    delete newTable;
+}
+
+
+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>::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
+{
+    // Are all my elements in rhs?
+    for (const_iterator iter = cbegin(); iter != cend(); ++iter)
+    {
+        const_iterator fnd = rhs.find(iter.key());
+
+        if (fnd == rhs.cend() || fnd() != iter())
+        {
+            return false;
+        }
+    }
+
+    // Are all rhs elements in me?
+    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
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H
new file mode 100644
index 00000000000..1c9f6db257d
--- /dev/null
+++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.H
@@ -0,0 +1,466 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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 HashTblName Declaration
+\*---------------------------------------------------------------------------*/
+
+TemplateName(HashTbl);
+
+
+/*---------------------------------------------------------------------------*\
+                          Class HashTbl Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class T, class Key=word, class Hash=string::hash>
+class HashTbl
+:
+    public HashTblName
+{
+    // Private data type for table entries
+
+        struct hashedEntry
+        {
+            //- The lookup key
+            Key key_;
+
+            //- Pointer to next hashedEntry in sub-list
+            hashedEntry* next_;
+
+            //- The data object
+            T obj_;
+
+            //- Constructors
+
+                //- Construct given key, next pointer and object
+                inline hashedEntry
+                (
+                    const Key&,
+                    hashedEntry* next,
+                    const T& newEntry
+                );
+
+                //- Dissallow construction as copy
+                hashedEntry(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 (not necessarily used)
+        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:
+
+        //- Declare friendship with the HashPtrTable class
+        template<class T2, class Key2, class Hash2>
+        friend class HashPtrTable;
+
+
+    // Forward declaration of STL iterators
+
+        class iterator;
+        friend class iterator;
+
+        class 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
+
+            //- 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 an hashedEntry specified by given iterator
+            bool erase(const iterator&);
+
+            //- Erase an hashedEntry specified by given key if in table
+            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 keys, but
+            //  but the type of values held is arbitrary.
+            template<class AnyType>
+            label erase(const HashTbl<AnyType, Key, Hash>&);
+
+            //- 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();
+
+            //- 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 an hashedEntry
+        inline T& operator[](const Key&);
+
+        //- Find and return an hashedEntry
+        inline const T& operator[](const Key&) const;
+
+        //- Find and return an hashedEntry, create it null if not present.
+        inline T& operator()(const Key&);
+
+        //- Assignment
+        void operator=(const HashTbl<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!
+        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;
+
+
+    // STL iterator
+
+        //- An STL-conforming iterator
+        class iterator
+        {
+            friend class HashTbl;
+            friend class const_iterator;
+
+            // Private data
+
+                //- Reference to the HashTbl this is an iterator for
+                HashTbl<T, Key, Hash>& hashTable_;
+
+                //- Current element
+                hashedEntry* elmtPtr_;
+
+                //- Current hash index
+                label hashIndex_;
+
+        public:
+
+            // Constructors
+
+                //- Construct from hash table, element and hash index
+                inline iterator
+                (
+                    HashTbl<T, Key, Hash>& curHashTbl,
+                    hashedEntry* elmt,
+                    label hashIndex
+                );
+
+            // Member operators
+
+                inline void operator=(const iterator&);
+
+                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;
+
+                inline T& operator*();
+                inline T& operator()();
+
+                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 HashTbl
+        inline iterator begin();
+
+        //- iterator set to beyond the end of the HashTbl
+        inline const iterator& end();
+
+
+    // STL const_iterator
+
+        //- An STL-conforming const_iterator
+        class const_iterator
+        {
+            friend class iterator;
+
+            // Private data
+
+                //- Reference to the HashTbl this is an iterator for
+                const HashTbl<T, Key, Hash>& hashTable_;
+
+                //- Current element
+                const hashedEntry* elmtPtr_;
+
+                //- Current hash index
+                label hashIndex_;
+
+
+        public:
+
+            // Constructors
+
+                //- Construct from hash table, element and hash index
+                inline const_iterator
+                (
+                    const HashTbl<T, Key, Hash>& curHashTbl,
+                    const hashedEntry* elmt,
+                    label hashIndex
+                );
+
+                //- Construct from the non-const iterator
+                inline const_iterator(const iterator&);
+
+
+            // 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;
+
+                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 HashTbl
+        inline const_iterator cbegin() const;
+
+        //- const_iterator set to beyond the end of the HashTbl
+        inline const const_iterator& cend() const;
+
+        //- const_iterator set to the beginning of the HashTbl
+        inline const_iterator begin() const;
+
+        //- const_iterator set to beyond the end of the HashTbl
+        inline const const_iterator& end() 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>&
+        );
+
+
+private:
+
+        //- iterator returned by end()
+        iterator endIter_;
+
+        //- const_iterator returned by end()
+        const_iterator endConstIter_;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#   include "HashTblI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifndef NoHashTblC
+#ifdef NoRepository
+#   include "HashTbl.C"
+#endif
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H
new file mode 100644
index 00000000000..8dd27700b59
--- /dev/null
+++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblI.H
@@ -0,0 +1,548 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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& newEntry
+)
+:
+    key_(key),
+    next_(next),
+    obj_(newEntry)
+{}
+
+
+// * * * * * * * * * * * * 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>::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;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * STL iterator  * * * * * * * * * * * * * * //
+
+template<class T, class Key, class Hash>
+inline Foam::HashTbl<T, Key, Hash>::iterator::iterator
+(
+    HashTbl<T, Key, Hash>& hashTbl,
+    hashedEntry* elmt,
+    label hashIndex
+)
+:
+    hashTable_(hashTbl),
+    elmtPtr_(elmt),
+    hashIndex_(hashIndex)
+{}
+
+
+template<class T, class Key, class Hash>
+inline void Foam::HashTbl<T, Key, Hash>::iterator::operator=
+(
+    const iterator& iter
+)
+{
+    elmtPtr_ = iter.elmtPtr_;
+    hashIndex_ = iter.hashIndex_;
+}
+
+
+template<class T, class Key, class Hash>
+inline bool Foam::HashTbl<T, Key, Hash>::iterator::operator==
+(
+    const iterator& iter
+) const
+{
+    return elmtPtr_ == iter.elmtPtr_;
+}
+
+
+template<class T, class Key, class Hash>
+inline bool Foam::HashTbl<T, Key, Hash>::iterator::operator!=
+(
+    const iterator& iter
+) const
+{
+    return elmtPtr_ != iter.elmtPtr_;
+}
+
+
+template<class T, class Key, class Hash>
+inline bool Foam::HashTbl<T, Key, Hash>::iterator::operator==
+(
+    const const_iterator& iter
+) const
+{
+    return elmtPtr_ == iter.elmtPtr_;
+}
+
+
+template<class T, class Key, class Hash>
+inline bool Foam::HashTbl<T, Key, Hash>::iterator::operator!=
+(
+    const const_iterator& iter
+) const
+{
+    return elmtPtr_ != iter.elmtPtr_;
+}
+
+
+template<class T, class Key, class Hash>
+inline T&
+Foam::HashTbl<T, Key, Hash>::iterator::operator*()
+{
+    return elmtPtr_->obj_;
+}
+
+
+template<class T, class Key, class Hash>
+inline T&
+Foam::HashTbl<T, Key, Hash>::iterator::operator()()
+{
+    return elmtPtr_->obj_;
+}
+
+
+template<class T, class Key, class Hash>
+inline const T&
+Foam::HashTbl<T, Key, Hash>::iterator::operator*() const
+{
+    return elmtPtr_->obj_;
+}
+
+
+template<class T, class Key, class Hash>
+inline const T&
+Foam::HashTbl<T, Key, Hash>::iterator::operator()() const
+{
+    return elmtPtr_->obj_;
+}
+
+
+template<class T, class Key, class Hash>
+inline
+typename Foam::HashTbl<T, Key, Hash>::iterator&
+Foam::HashTbl<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;
+    }
+    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 tmp = *this;
+    ++*this;
+    return tmp;
+}
+
+
+template<class T, class Key, class Hash>
+inline
+const Key& Foam::HashTbl<T, Key, Hash>::iterator::key() const
+{
+    return elmtPtr_->key_;
+}
+
+
+template<class T, class Key, class Hash>
+inline typename Foam::HashTbl<T, Key, Hash>::iterator
+Foam::HashTbl<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<< "HashTbl is empty\n";
+        }
+#       endif
+
+        return HashTbl<T, Key, Hash>::endIter_;
+    }
+    else
+    {
+        return iterator(*this, table_[i], i);
+    }
+}
+
+
+template<class T, class Key, class Hash>
+inline const typename Foam::HashTbl<T, Key, Hash>::iterator&
+Foam::HashTbl<T, Key, Hash>::end()
+{
+    return HashTbl<T, Key, Hash>::endIter_;
+}
+
+
+// * * * * * * * * * * * * * * * STL const_iterator * * * * * * * * * * * * * //
+
+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,
+    label hashIndex
+)
+:
+    hashTable_(hashTbl),
+    elmtPtr_(elmt),
+    hashIndex_(hashIndex)
+{}
+
+
+template<class T, class Key, class Hash>
+inline Foam::HashTbl<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::HashTbl<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::HashTbl<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::HashTbl<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::HashTbl<T, Key, Hash>::const_iterator::operator==
+(
+    const iterator& iter
+) const
+{
+    return elmtPtr_ == iter.elmtPtr_;
+}
+
+
+template<class T, class Key, class Hash>
+inline bool Foam::HashTbl<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::HashTbl<T, Key, Hash>::const_iterator::operator*() const
+{
+    return elmtPtr_->obj_;
+}
+
+template<class T, class Key, class Hash>
+inline const T&
+Foam::HashTbl<T, Key, Hash>::const_iterator::operator()() const
+{
+    return elmtPtr_->obj_;
+}
+
+
+template<class T, class Key, class Hash>
+inline
+typename Foam::HashTbl<T, Key, Hash>::const_iterator&
+Foam::HashTbl<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_])
+        )
+        {}
+    }
+
+    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 tmp = *this;
+    ++*this;
+    return tmp;
+}
+
+
+template<class T, class Key, class Hash>
+inline
+const Key& Foam::HashTbl<T, Key, Hash>::const_iterator::key() const
+{
+    return elmtPtr_->key_;
+}
+
+
+template<class T, class Key, class Hash>
+inline typename Foam::HashTbl<T, Key, Hash>::const_iterator
+Foam::HashTbl<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<< "HashTbl is empty\n";
+        }
+#       endif
+
+        return HashTbl<T, Key, Hash>::endConstIter_;
+    }
+    else
+    {
+        return const_iterator(*this, table_[i], i);
+    }
+}
+
+
+template<class T, class Key, class Hash>
+inline const typename Foam::HashTbl<T, Key, Hash>::const_iterator&
+Foam::HashTbl<T, Key, Hash>::cend() const
+{
+    return HashTbl<T, Key, Hash>::endConstIter_;
+}
+
+
+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();
+}
+
+
+template<class T, class Key, class Hash>
+inline const typename Foam::HashTbl<T, Key, Hash>::const_iterator&
+Foam::HashTbl<T, Key, Hash>::end() const
+{
+    return HashTbl<T, Key, Hash>::endConstIter_;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTblIO.C b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblIO.C
new file mode 100644
index 00000000000..ac438f77e91
--- /dev/null
+++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblIO.C
@@ -0,0 +1,246 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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)
+:
+    HashTblName(),
+    nElmts_(0),
+    tableSize_(canonicalSize(size)),
+    table_(new hashedEntry*[tableSize_]),
+    endIter_(*this, NULL, 0),
+    endConstIter_(*this, NULL, 0)
+{
+    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;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/containers/HashTables/HashTbl/HashTblName.C b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblName.C
new file mode 100644
index 00000000000..61e198becb2
--- /dev/null
+++ b/src/OpenFOAM/containers/HashTables/HashTbl/HashTblName.C
@@ -0,0 +1,33 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+defineTypeNameAndDebug(Foam::HashTblName, 0);
+
+// ************************************************************************* //
-- 
GitLab