From 8bdd3501d7f6965794b3c586337b8bf67feb9dff Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@Germany>
Date: Thu, 8 May 2008 14:29:21 +0200
Subject: [PATCH] Added set() method to HashTable. Added replace() method to
 DLListBase. Modified the dictionary merge code to avoid scrambling the order,
 but left the old version active for now.

---
 .../HashTables/HashTable/HashTable.C          | 69 ++++++++++++++-----
 .../HashTables/HashTable/HashTable.H          | 10 ++-
 .../HashTables/HashTable/HashTableI.H         | 15 +++-
 .../linkTypes/DLListBase/DLListBase.C         | 37 ++++++++++
 .../linkTypes/DLListBase/DLListBase.H         |  6 ++
 .../linkTypes/DLListBase/DLListBaseI.H        | 10 +++
 src/OpenFOAM/db/dictionary/dictionary.C       | 26 +++++++
 7 files changed, 154 insertions(+), 19 deletions(-)

diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C
index 072fe7077c7..0e0d7d58f93 100644
--- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C
+++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.C
@@ -202,7 +202,12 @@ List<Key> HashTable<T, Key, Hash>::toc() const
 
 
 template<class T, class Key, class Hash>
-bool HashTable<T, Key, Hash>::insert(const Key& key, const T& newEntry)
+bool HashTable<T, Key, Hash>::set
+(
+    const Key& key,
+    const T& newEntry,
+    const bool protect
+)
 {
     if (tableSize_ == 0)
     {
@@ -210,40 +215,70 @@ bool HashTable<T, Key, Hash>::insert(const Key& key, const T& newEntry)
     }
 
     label ii = Hash()(key, tableSize_);
+    hashedEntry* existing = 0;
+    hashedEntry* prev = 0;
 
-    for (hashedEntry* n=table_[ii]; n; n=n->next_)
+    for (hashedEntry* curr = table_[ii]; curr; curr = curr->next_)
     {
-        if (key == n->key_)
+        if (key == curr->key_)
+        {
+            existing = curr;
+            break;
+        }
+        prev = curr;
+    }
+
+    // not found, insert it at the head
+    if (!existing)
+    {
+        table_[ii] = new hashedEntry(key, table_[ii], newEntry);
+        nElmts_++;
+
+        if (double(nElmts_)/tableSize_ > 0.8)
         {
 #           ifdef FULLDEBUG
             if (debug)
             {
-                Info<< "HashTable<T, Key, Hash>::insert"
-                       "(const Key& key, T newEntry) : "
-                       "Cannot insert " << key << " already in hash table\n";
+                Info<< "HashTable<T, Key, Hash>::set"
+                    "(const Key& key, T newEntry) : "
+                    "Doubling table size\n";
             }
 #           endif
 
-            return false;
+            resize(2*tableSize_);
         }
     }
-
-    table_[ii] = new hashedEntry(key, table_[ii], newEntry);
-
-    nElmts_++;
-
-    if (double(nElmts_)/tableSize_ > 0.8)
+    else if (protect)
     {
+        // found - but protected from overwriting
+        // this corresponds to the STL 'insert' convention
 #       ifdef FULLDEBUG
         if (debug)
         {
-            Info<< "HashTable<T, Key, Hash>::insert"
-                   "(const Key& key, T newEntry) : "
-                   "Doubling table size\n";
+            Info<< "HashTable<T, Key, Hash>::set"
+                "(const Key& key, T newEntry, false) : "
+                "Cannot insert " << key << " already in hash table\n";
         }
 #       endif
+        return false;
+    }
+    else
+    {
+        // found - overwrite existing entry
+        // this corresponds to the Perl convention
+        hashedEntry* elemPtr = new hashedEntry(key, existing->next_, newEntry);
+
+        // replace existing element - within list or insert at the head
+        if (prev)
+        {
+            prev->next_ = elemPtr;
+        }
+        else
+        {
+            table_[ii] = elemPtr;
+        }
 
-        resize(2*tableSize_);
+        delete existing;
     }
 
     return true;
diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
index b74ac01d336..29dd037e547 100644
--- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
+++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
@@ -123,6 +123,11 @@ class HashTable
         label nElmts_;
 
 
+    // Private Member Functions
+
+        //- Assign a new hashedEntry to a possibly already existing key
+        bool set(const Key& key, const T& newElmt, bool protect);
+
 public:
 
         //- Declare friendship with the HashPtrTable class
@@ -181,7 +186,10 @@ public:
         // Edit
 
             //- Insert a new hashedEntry
-            bool insert(const Key& key, const T& newElmt);
+            inline bool insert(const Key& key, const T& newElmt);
+
+            //- Assign a new hashedEntry, overwriting existing entries
+            inline bool set(const Key& key, const T& newElmt);
 
             //- Erase an hashedEntry specified by given iterator
             bool erase(const iterator& it);
diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H
index e934aaa3168..61c5115fa31 100644
--- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H
+++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableI.H
@@ -56,6 +56,19 @@ inline label HashTable<T, Key, Hash>::size() const
 }
 
 
+template<class T, class Key, class Hash>
+inline bool HashTable<T, Key, Hash>::insert(const Key& key, const T& newEntry)
+{
+    return set(key, newEntry, true);
+}
+
+
+template<class T, class Key, class Hash>
+inline bool HashTable<T, Key, Hash>::set(const Key& key, const T& newEntry)
+{
+    return set(key, newEntry, false);
+}
+
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 template<class T, class Key, class Hash>
@@ -292,7 +305,7 @@ inline HashTable<T, Key, Hash>::const_iterator::const_iterator
 
 template<class T, class Key, class Hash>
 inline HashTable<T, Key, Hash>::const_iterator::const_iterator
-(   
+(
     const iterator& iter
 )
 :
diff --git a/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.C b/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.C
index a932c788d1f..077040d466c 100644
--- a/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.C
+++ b/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.C
@@ -229,6 +229,43 @@ DLListBase::link* DLListBase::remove(DLListBase::link* l)
 }
 
 
+DLListBase::link* DLListBase::replace
+(
+    DLListBase::link* oldLink,
+    DLListBase::link* newLink
+)
+{
+    link* ret = oldLink;
+
+    newLink->prev_ = oldLink->prev_;
+    newLink->next_ = oldLink->next_;
+
+    if (oldLink == first_ && first_ == last_)
+    {
+        first_ = newLink;
+        last_  = newLink;
+    }
+    else if (oldLink == first_)
+    {
+        first_ = newLink;
+        newLink->next_->prev_ = newLink;
+    }
+    else if (oldLink == last_)
+    {
+        last_ = newLink;
+        newLink->prev_->next_ = newLink;
+    }
+    else
+    {
+        newLink->prev_->next_ = newLink;
+        newLink->next_->prev_ = newLink;
+    }
+
+    ret->deregister();
+    return ret;
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.H b/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.H
index 5c7fe6e2c3d..1e51ac5c18c 100644
--- a/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.H
+++ b/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBase.H
@@ -158,6 +158,12 @@ public:
             // Remove and return element specified by iterator
             inline link* remove(iterator&);
 
+            //- Replace oldLink with newLink and return element
+            link* replace(link* oldLink, link* newLink);
+
+            //- Replace oldIter with newLink and return element
+            inline link* replace(iterator& oldIter, link* newLink);
+
             //- Clear the list
             inline void clear();
 
diff --git a/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBaseI.H b/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBaseI.H
index 84eec49d336..617253c5e33 100644
--- a/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBaseI.H
+++ b/src/OpenFOAM/containers/LinkedLists/linkTypes/DLListBase/DLListBaseI.H
@@ -148,6 +148,16 @@ inline DLListBase::link* DLListBase::remove(DLListBase::iterator& it)
 }
 
 
+inline DLListBase::link* DLListBase::replace
+(
+    DLListBase::iterator& oldIter,
+    DLListBase::link* newLink
+)
+{
+    return replace(oldIter.curElmt_, newLink);
+}
+
+
 // * * * * * * * * * * * * * * * STL iterator  * * * * * * * * * * * * * * * //
 
 inline DLListBase::iterator::iterator(DLListBase& s, link* elmt)
diff --git a/src/OpenFOAM/db/dictionary/dictionary.C b/src/OpenFOAM/db/dictionary/dictionary.C
index aea31e72c77..df4fbd8e565 100644
--- a/src/OpenFOAM/db/dictionary/dictionary.C
+++ b/src/OpenFOAM/db/dictionary/dictionary.C
@@ -34,6 +34,7 @@ defineTypeNameAndDebug(Foam::dictionary, 0);
 
 const Foam::dictionary Foam::dictionary::null;
 
+#undef DICTIONARY_INPLACE_MERGE
 
 // * * * * * * * * * * * * * Private member functions  * * * * * * * * * * * //
 
@@ -53,7 +54,27 @@ bool Foam::dictionary::add(entry* ePtr, bool mergeEntry)
         }
         else
         {
+#ifdef DICTIONARY_INPLACE_MERGE
+            if (hashedEntries_.set(ePtr->keyword(), ePtr))
+            {
+                ePtr->name() = name_ + "::" + ePtr->keyword();
+                replace(iter(), ePtr);
+
+                return true;
+            }
+            else
+            {
+                IOWarningIn("dictionary::add(entry* ePtr)", (*this))
+                    << "problem replacing entry in dictionary "
+                    << name()
+                    << endl;
+
+                delete ePtr;
+                return false;
+            }
+#else
             remove(ePtr->keyword());
+#endif
         }
     }
 
@@ -517,8 +538,12 @@ bool Foam::dictionary::merge(const dictionary& dict)
             }
             else
             {
+#ifdef DICTIONARY_INPLACE_MERGE
+                add(iter().clone(*this).ptr(), true);
+#else
                 remove(keyword);
                 add(iter().clone(*this)());
+#endif
                 changed = true;
             }
         }
@@ -526,6 +551,7 @@ bool Foam::dictionary::merge(const dictionary& dict)
         {
             // not found - just add
             add(iter().clone(*this)());
+            changed = true;
         }
     }
 
-- 
GitLab