From c880d7dc7d11b25370647542ebeed8cf891535fe Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Thu, 13 Jul 2017 09:46:07 +0200
Subject: [PATCH] ENH: support '/' separators in foamDictionary

- convenience -diffEtc option that behaves like -diff, but invokes
  foamEtcFile searching

STYLE: modernize code.
---
 .../foamDictionary/foamDictionary.C           | 367 ++++++++++--------
 src/OpenFOAM/db/dictionary/dictionary.C       |  61 ++-
 src/OpenFOAM/db/dictionary/dictionary.H       | 157 ++++----
 src/OpenFOAM/db/dictionary/dictionarySearch.C |   4 +-
 .../db/dictionary/dictionaryTemplates.C       |  58 ++-
 5 files changed, 353 insertions(+), 294 deletions(-)

diff --git a/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C b/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C
index e4c31862614..57210c5a576 100644
--- a/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C
+++ b/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2016-2017 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -33,7 +33,7 @@ Usage
       - \par -entry \<name\>
         Selects an entry
 
-      - \par -keywords \<name\>
+      - \par -keywords
         Prints the keywords (of the selected entry or of the top level if
         no entry was selected
 
@@ -50,6 +50,10 @@ Usage
         Write differences with respect to the specified dictionary
         (or sub entry if -entry specified)
 
+      - \par -diffEtc \<dictionary\>
+        Write differences with respect to the specified dictionary
+        (or sub entry if -entry specified)
+
       - \par -expand
         Read the specified dictionary file, expand the macros etc. and write
         the resulting dictionary to standard output.
@@ -90,13 +94,13 @@ Usage
 
       - Write the differences with respect to a template dictionary:
         \verbatim
-          foamDictionary 0/U -diff $FOAM_ETC/templates/closedVolume/0/U
+          foamDictionary 0/U -diffEtc templates/closedVolume/0/U
         \endverbatim
 
       - Write the differences in boundaryField with respect to a
         template dictionary:
         \verbatim
-          foamDictionary 0/U -diff $FOAM_ETC/templates/closedVolume/0/U \
+          foamDictionary 0/U -diffEtc templates/closedVolume/0/U \
             -entry boundaryField
         \endverbatim
 
@@ -115,50 +119,78 @@ Usage
 #include "profiling.H"
 #include "Time.H"
 #include "Fstream.H"
+#include "etcFiles.H"
 #include "includeEntry.H"
 
 using namespace Foam;
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-//- Converts old scope syntax to new syntax
-word scope(const fileName& entryName)
+//- Convert older ':' scope syntax to newer '.' scope syntax,
+//  but leave anything with '/' delimiters untouched
+bool upgradeScope(word& entryName)
 {
-    if (entryName.find(':') != string::npos)
+    if
+    (
+        entryName.find('/') == string::npos
+     && entryName.find(':') != string::npos
+    )
     {
-        wordList entryNames(entryName.components(':'));
+        const wordList names(fileName(entryName).components(':'));
+
+        entryName.resize(0);
 
-        word entry(entryNames[0]);
-        for (label i = 1; i < entryNames.size(); i++)
+        for (const word& name : names)
         {
-            entry += word('.') + entryNames[i];
+            if (entryName.size()) entryName.append(".");
+
+            entryName.append(name);
         }
-        return entry;
-    }
-    else
-    {
-        return entryName;
+
+        return true;
     }
+
+    // Nothing changed
+    return false;
 }
 
 
-//- Extracts dict name and keyword
-Pair<word> dictAndKeyword(const word& scopedName)
+//- Split into dictionary name and the entry name
+class dictAndKeyword
 {
-    string::size_type i = scopedName.find_last_of(".");
-    if (i != string::npos)
+    word dict_;
+    word key_;
+
+public:
+    dictAndKeyword(const word& scopedName)
     {
-        return Pair<word>
-        (
-            scopedName.substr(0, i),
-            scopedName.substr(i+1, string::npos)
-        );
+        string::size_type i = scopedName.rfind('/');
+        if (i == string::npos)
+        {
+            i = scopedName.rfind('.');
+        }
+
+        if (i != string::npos)
+        {
+            dict_ = scopedName.substr(0, i);
+            key_  = scopedName.substr(i+1);
+        }
+        else
+        {
+            key_  = scopedName;
+        }
     }
-    else
+
+    inline const word& dict() const
     {
-        return Pair<word>("", scopedName);
+        return dict_;
     }
-}
+
+    inline const word& key() const
+    {
+        return key_;
+    }
+};
 
 
 const dictionary& lookupScopedDict
@@ -167,71 +199,56 @@ const dictionary& lookupScopedDict
     const word& subDictName
 )
 {
-    if (subDictName == "")
+    if (subDictName.empty())
     {
         return dict;
     }
-    else
+
+    const entry* eptr = dict.lookupScopedEntryPtr(subDictName, false, false);
+
+    if (!eptr || !eptr->isDict())
     {
-        const entry* entPtr = dict.lookupScopedEntryPtr
-        (
-            subDictName,
-            false,
-            false
-        );
-        if (!entPtr || !entPtr->isDict())
-        {
-            FatalIOErrorInFunction(dict)
-                << "keyword " << subDictName
-                << " is undefined in dictionary "
-                << dict.name() << " or is not a dictionary"
-                << endl
-                << "Valid keywords are " << dict.keys()
-                << exit(FatalIOError);
-        }
-        return entPtr->dict();
+        FatalIOErrorInFunction(dict)
+            << "keyword " << subDictName
+            << " is undefined in dictionary "
+            << dict.name() << " or is not a dictionary"
+            << endl
+            << "Valid keywords are " << dict.keys()
+            << exit(FatalIOError);
     }
+
+    return eptr->dict();
 }
 
 
-void remove(dictionary& dict, const dictionary& removeDict)
+void removeDict(dictionary& dict, const dictionary& dictToRemove)
 {
-    forAllConstIter(dictionary, removeDict, iter)
+    for (const entry& refEntry : dictToRemove)
     {
-        const entry* entPtr = dict.lookupEntryPtr
-        (
-            iter().keyword(),
-            false,
-            false
-        );
+        auto finder = dict.search(refEntry.keyword(), false, false);
 
-        if (entPtr)
+        bool purge = false;
+
+        if (finder.isDict())
         {
-            if (entPtr->isDict())
-            {
-                if (iter().isDict())
-                {
-                    remove
-                    (
-                        const_cast<dictionary&>(entPtr->dict()),
-                        iter().dict()
-                    );
-
-                    // Check if dictionary is empty
-                    if (!entPtr->dict().size())
-                    {
-                        dict.remove(iter().keyword());
-                    }
-                }
-            }
-            else if (!iter().isDict())
+            if (refEntry.isDict())
             {
-                if (*entPtr == iter())
-                {
-                    dict.remove(iter().keyword());
-                }
+                removeDict(finder.dict(), refEntry.dict());
+
+                // Purge if dictionary is empty
+                purge = finder.dict().empty();
             }
         }
+        else if (finder.found() && !refEntry.isDict())
+        {
+            // Purge if entries match
+            purge = (finder.ref() == refEntry);
+        }
+
+        if (purge)
+        {
+            dict.remove(refEntry.keyword());
+        }
     }
 }
 
@@ -243,7 +260,7 @@ int main(int argc, char *argv[])
     argList::noBanner();
     argList::noJobInfo();
     argList::validArgs.append("dictionary");
-    argList::addBoolOption("keywords", "list keywords");
+    argList::addBoolOption("keywords", "List keywords");
     argList::addOption("entry", "name", "report/select the named entry");
     argList::addBoolOption
     (
@@ -273,6 +290,12 @@ int main(int argc, char *argv[])
         "dict",
         "Write differences with respect to the specified dictionary"
     );
+    argList::addOption
+    (
+        "diffEtc",
+        "dict",
+        "As per -diff, but locate the file as per foamEtcFile"
+    );
     argList::addBoolOption
     (
         "includes",
@@ -303,13 +326,12 @@ int main(int argc, char *argv[])
     const bool disableEntries = args.optionFound("disableFunctionEntries");
     if (disableEntries)
     {
-        Info<< "Not expanding variables or dictionary directives"
-            << endl;
+        Info<< "Not expanding variables or dictionary directives" << endl;
         entry::disableFunctionEntries = true;
     }
 
 
-    fileName dictFileName(args[1]);
+    const fileName dictFileName(args[1]);
 
     autoPtr<IFstream> dictFile(new IFstream(dictFileName));
     if (!dictFile().good())
@@ -341,28 +363,55 @@ int main(int argc, char *argv[])
     }
 
 
-    // Second dictionary for -diff
+    // Has "diff" or "diffEtc"
+    bool optDiff = false;
+
+    // Reference dictionary for -diff / -diffEtc
     dictionary diffDict;
-    fileName diffFileName;
-    if (args.optionReadIfPresent("diff", diffFileName))
     {
-        autoPtr<IFstream> diffFile(new IFstream(diffFileName));
-        if (!diffFile().good())
+        fileName diffFileName;
+        if (args.optionReadIfPresent("diff", diffFileName))
         {
-            FatalErrorInFunction
-                << "Cannot open file " << diffFileName
-                << exit(FatalError, 1);
+            IFstream diffFile(diffFileName);
+            if (!diffFile.good())
+            {
+                FatalErrorInFunction
+                    << "Cannot open file " << diffFileName
+                    << exit(FatalError, 1);
+            }
+
+            // Read but preserve headers
+            diffDict.read(diffFile, true);
+            optDiff = true;
         }
+        else if (args.optionReadIfPresent("diffEtc", diffFileName))
+        {
+            fileName foundName = findEtcFile(diffFileName);
+            if (foundName.empty())
+            {
+                FatalErrorInFunction
+                    << "Cannot find etcFile " << diffFileName
+                    << exit(FatalError, 1);
+            }
 
-        // Read but preserve headers
-        diffDict.read(diffFile(), true);
-    }
+            IFstream diffFile(foundName);
+            if (!diffFile.good())
+            {
+                FatalErrorInFunction
+                    << "Cannot open file " << foundName
+                    << exit(FatalError, 1);
+            }
 
+            // Read but preserve headers
+            diffDict.read(diffFile, true);
+            optDiff = true;
+        }
+    }
 
-    word entryName;
-    if (args.optionReadIfPresent("entry", entryName))
+    word scopedName;  // Actually fileName, since it can contain '/' scoping
+    if (args.optionReadIfPresent("entry", scopedName))
     {
-        word scopedName(scope(entryName));
+        upgradeScope(scopedName);
 
         string newValue;
         if
@@ -371,13 +420,17 @@ int main(int argc, char *argv[])
          || args.optionReadIfPresent("add", newValue)
         )
         {
-            bool overwrite = args.optionFound("set");
+            const bool overwrite = args.optionFound("set");
 
-            Pair<word> dAk(dictAndKeyword(scopedName));
+            // Dictionary name and keyword
+            const dictAndKeyword dAk(scopedName);
 
-            IStringStream str(string(dAk.second()) + ' ' + newValue + ';');
+            // The context for the action
+            const dictionary& d(lookupScopedDict(dict, dAk.dict()));
+
+            // Create a new entry
+            IStringStream str(string(dAk.key()) + ' ' + newValue + ';');
             entry* ePtr(entry::New(str).ptr());
-            const dictionary& d(lookupScopedDict(dict, dAk.first()));
 
             if (overwrite)
             {
@@ -390,122 +443,116 @@ int main(int argc, char *argv[])
             changed = true;
 
             // Print the changed entry
-            const entry* entPtr = dict.lookupScopedEntryPtr
+            const auto finder = dict.csearchScoped
             (
                 scopedName,
                 false,
-                true            // Support wildcards
+                true  // Support wildcards
             );
-            if (entPtr)
+
+            if (finder.found())
             {
-                Info<< *entPtr;
+                Info<< finder.ref();
             }
         }
         else if (args.optionFound("remove"))
         {
-            // Extract dictionary name and keyword
-            Pair<word> dAk(dictAndKeyword(scopedName));
+            // Dictionary name and keyword
+            const dictAndKeyword dAk(scopedName);
+
+            // The context for the action
+            const dictionary& d(lookupScopedDict(dict, dAk.dict()));
 
-            const dictionary& d(lookupScopedDict(dict, dAk.first()));
-            const_cast<dictionary&>(d).remove(dAk.second());
+            const_cast<dictionary&>(d).remove(dAk.key());
             changed = true;
         }
         else
         {
             // Optionally remove a second dictionary
-            if (args.optionFound("diff"))
+            if (optDiff)
             {
-                Pair<word> dAk(dictAndKeyword(scopedName));
+                // Dictionary name and keyword
+                const dictAndKeyword dAk(scopedName);
 
-                const dictionary& d(lookupScopedDict(dict, dAk.first()));
-                const dictionary& d2(lookupScopedDict(diffDict, dAk.first()));
+                const dictionary& d1(lookupScopedDict(dict, dAk.dict()));
+                const dictionary& d2(lookupScopedDict(diffDict, dAk.dict()));
 
-                const entry* ePtr =
-                    d.lookupEntryPtr(dAk.second(), false, true);
-                const entry* e2Ptr =
-                    d2.lookupEntryPtr(dAk.second(), false, true);
+                const entry* e1Ptr = d1.lookupEntryPtr(dAk.key(), false, true);
+                const entry* e2Ptr = d2.lookupEntryPtr(dAk.key(), false, true);
 
-                if (ePtr && e2Ptr)
+                if (e1Ptr && e2Ptr)
                 {
-                    if (*ePtr == *e2Ptr)
+                    if (*e1Ptr == *e2Ptr)
                     {
-                        const_cast<dictionary&>(d).remove(dAk.second());
+                        const_cast<dictionary&>(d1).remove(dAk.key());
                     }
-                    else if (ePtr->isDict() && e2Ptr->isDict())
+                    else if (e1Ptr->isDict() && e2Ptr->isDict())
                     {
-                        remove
+                        removeDict
                         (
-                            const_cast<dictionary&>(ePtr->dict()),
+                            const_cast<dictionary&>(e1Ptr->dict()),
                             e2Ptr->dict()
                         );
                     }
                 }
             }
 
-
-            const entry* entPtr = dict.lookupScopedEntryPtr
+            const auto finder = dict.csearchScoped
             (
                 scopedName,
                 false,
-                true            // Support wildcards
+                true  // Support wildcards
             );
 
-            if (entPtr)
+            if (!finder.found())
             {
-                if (args.optionFound("keywords"))
+                FatalIOErrorInFunction(dictFile())
+                    << "Cannot find entry " << scopedName
+                    << exit(FatalIOError, 2);
+            }
+            else if (args.optionFound("keywords"))
+            {
+                for (const entry& e : finder.dict())
                 {
-                    const dictionary& dict = entPtr->dict();
-                    forAllConstIter(dictionary, dict, iter)
-                    {
-                        Info<< iter().keyword() << endl;
-                    }
+                    Info<< e.keyword() << endl;
+                }
+            }
+            else if (args.optionFound("value"))
+            {
+                if (finder.isDict())
+                {
+                    Info<< finder.dict();
                 }
-                else
+                else if (finder.ref().isStream())
                 {
-                    if (args.optionFound("value"))
+                    const tokenList& tokens = finder.ref().stream();
+                    forAll(tokens, i)
                     {
-                        if (entPtr->isStream())
+                        Info<< tokens[i];
+                        if (i < tokens.size() - 1)
                         {
-                            const tokenList& tokens = entPtr->stream();
-                            forAll(tokens, i)
-                            {
-                                Info<< tokens[i];
-                                if (i < tokens.size() - 1)
-                                {
-                                    Info<< token::SPACE;
-                                }
-                            }
-                            Info<< endl;
-                        }
-                        else if (entPtr->isDict())
-                        {
-                            Info<< entPtr->dict();
+                            Info<< token::SPACE;
                         }
                     }
-                    else
-                    {
-                        Info<< *entPtr;
-                    }
+                    Info<< endl;
                 }
             }
             else
             {
-                FatalIOErrorInFunction(dictFile)
-                    << "Cannot find entry " << entryName
-                    << exit(FatalIOError, 2);
+                Info<< finder.ref();
             }
         }
     }
     else if (args.optionFound("keywords"))
     {
-        forAllConstIter(dictionary, dict, iter)
+        for (const entry& e : dict)
         {
-            Info<< iter().keyword() << endl;
+            Info<< e.keyword() << endl;
         }
     }
-    else if (args.optionFound("diff"))
+    else if (optDiff)
     {
-        remove(dict, diffDict);
+        removeDict(dict, diffDict);
         dict.write(Info, false);
     }
     else
diff --git a/src/OpenFOAM/db/dictionary/dictionary.C b/src/OpenFOAM/db/dictionary/dictionary.C
index 46cee88d67d..a39fbf48629 100644
--- a/src/OpenFOAM/db/dictionary/dictionary.C
+++ b/src/OpenFOAM/db/dictionary/dictionary.C
@@ -171,10 +171,8 @@ const Foam::dictionary& Foam::dictionary::topDict() const
     {
         return p.topDict();
     }
-    else
-    {
-        return *this;
-    }
+
+    return *this;
 }
 
 
@@ -184,10 +182,8 @@ Foam::label Foam::dictionary::startLineNumber() const
     {
         return first()->startLineNumber();
     }
-    else
-    {
-        return -1;
-    }
+
+    return -1;
 }
 
 
@@ -197,10 +193,8 @@ Foam::label Foam::dictionary::endLineNumber() const
     {
         return last()->endLineNumber();
     }
-    else
-    {
-        return -1;
-    }
+
+    return -1;
 }
 
 
@@ -575,16 +569,15 @@ bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
 
             return true;
         }
-        else
-        {
-            IOWarningInFunction((*this))
-                << "problem replacing entry "<< entryPtr->keyword()
-                << " in dictionary " << name() << endl;
 
-            parent_type::remove(entryPtr);
-            delete entryPtr;
-            return false;
-        }
+
+        IOWarningInFunction((*this))
+            << "problem replacing entry "<< entryPtr->keyword()
+            << " in dictionary " << name() << endl;
+
+        parent_type::remove(entryPtr);
+        delete entryPtr;
+        return false;
     }
 
 
@@ -604,16 +597,15 @@ bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
 
         return true;
     }
-    else
-    {
-        IOWarningInFunction((*this))
-            << "attempt to add entry "<< entryPtr->keyword()
-            << " which already exists in dictionary " << name()
-            << endl;
 
-        delete entryPtr;
-        return false;
-    }
+
+    IOWarningInFunction((*this))
+        << "attempt to add entry "<< entryPtr->keyword()
+        << " which already exists in dictionary " << name()
+        << endl;
+
+    delete entryPtr;
+    return false;
 }
 
 
@@ -796,7 +788,8 @@ void Foam::dictionary::operator+=(const dictionary& rhs)
     if (this == &rhs)
     {
         FatalIOErrorInFunction(*this)
-            << "attempted addition assignment to self for dictionary " << name()
+            << "attempted addition assignment to self for dictionary "
+            << name()
             << abort(FatalIOError);
     }
 
@@ -812,7 +805,8 @@ void Foam::dictionary::operator|=(const dictionary& rhs)
     if (this == &rhs)
     {
         FatalIOErrorInFunction(*this)
-            << "attempted assignment to self for dictionary " << name()
+            << "attempted assignment to self for dictionary "
+            << name()
             << abort(FatalIOError);
     }
 
@@ -831,7 +825,8 @@ void Foam::dictionary::operator<<=(const dictionary& rhs)
     if (this == &rhs)
     {
         FatalIOErrorInFunction(*this)
-            << "attempted assignment to self for dictionary " << name()
+            << "attempted assignment to self for dictionary "
+            << name()
             << abort(FatalIOError);
     }
 
diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H
index 783c6436563..7b3baa055a9 100644
--- a/src/OpenFOAM/db/dictionary/dictionary.H
+++ b/src/OpenFOAM/db/dictionary/dictionary.H
@@ -471,10 +471,11 @@ public:
 
       // Search and lookup
 
-        //- Search dictionary for given keyword
-        //  If recursive, search parent dictionaries
-        //  If patternMatch, use regular expressions
-        //  (default search: non-recursive with patterns).
+        //- Search dictionary for given keyword.
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         bool found
         (
             const word& keyword,
@@ -482,10 +483,10 @@ public:
             bool patternMatch = true
         ) const;
 
-        //- Find and return an entry data stream pointer if present
-        //  otherwise return nullptr.
-        //  If recursive, search parent dictionaries.
-        //  If patternMatch, use regular expressions
+        //- Find and return an entry pointer if present, or return a nullptr.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         const entry* lookupEntryPtr
         (
             const word& keyword,
@@ -493,10 +494,11 @@ public:
             bool patternMatch
         ) const;
 
-        //- Find and return an entry data stream pointer for manipulation
-        //  if present otherwise return nullptr.
-        //  If recursive, search parent dictionaries.
-        //  If patternMatch, use regular expressions.
+        //- Find and return an entry pointer for manipulation if present,
+        //  or return a nullptr.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         entry* lookupEntryPtr
         (
             const word& keyword,
@@ -504,9 +506,10 @@ public:
             bool patternMatch
         );
 
-        //- Find and return an entry data stream if present otherwise error.
-        //  If recursive, search parent dictionaries.
-        //  If patternMatch, use regular expressions.
+        //- Find and return an entry if present otherwise error.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         const entry& lookupEntry
         (
             const word& keyword,
@@ -514,10 +517,11 @@ public:
             bool patternMatch
         ) const;
 
-        //- Find and return an entry data stream
-        //  If recursive, search parent dictionaries.
-        //  If patternMatch, use regular expressions.
-        //  (default search: non-recursive with patterns).
+        //- Find and return an entry data stream.
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         ITstream& lookup
         (
             const word& keyword,
@@ -525,11 +529,11 @@ public:
             bool patternMatch = true
         ) const;
 
-        //- Find and return a T,
-        //  if not found throw a fatal error.
-        //  If recursive, search parent dictionaries.
-        //  If patternMatch, use regular expressions.
-        //  (default search: non-recursive with patterns).
+        //- Find and return a T. FatalError if not found.
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         template<class T>
         T lookupType
         (
@@ -539,9 +543,10 @@ public:
         ) const;
 
         //- Find and return a T, or return the given default value
-        //  If recursive, search parent dictionaries.
-        //  If patternMatch, use regular expressions.
-        //  (default search: non-recursive with patterns).
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         template<class T>
         T lookupOrDefault
         (
@@ -598,12 +603,14 @@ public:
         ) const;
 
         //- Check if entry exists and is a sub-dictionary.
-        //  (search type: non-recursive with patterns)
+        //
+        //  Search type: non-recursive with patterns.
         bool isDict(const word& keyword) const;
 
         //- Find and return a sub-dictionary pointer if present
         //  (and a sub-dictionary) otherwise return nullptr.
-        //  (search type: non-recursive with patterns)
+        //
+        //  Search type: non-recursive with patterns.
         const dictionary* subDictPtr(const word& keyword) const;
 
         //- Find and return a sub-dictionary pointer if present
@@ -614,18 +621,21 @@ public:
 
         //- Find and return a sub-dictionary.
         //  Fatal if the entry does not exist or is not a sub-dictionary.
-        //  (search type: non-recursive with patterns)
+        //
+        //  Search type: non-recursive with patterns.
         const dictionary& subDict(const word& keyword) const;
 
         //- Find and return a sub-dictionary for manipulation.
         //  Fatal if the entry does not exist or is not a sub-dictionary.
-        //  (search type: non-recursive with patterns)
+        //
+        //  Search type: non-recursive with patterns.
         dictionary& subDict(const word& keyword);
 
         //- Find and return a sub-dictionary as a copy, otherwise return
         //  an empty dictionary.
         //  Warn if the entry exists but is not a sub-dictionary.
-        //  (search type: non-recursive with patterns)
+        //
+        //  Search type: non-recursive with patterns.
         dictionary subOrEmptyDict
         (
             const word& keyword,
@@ -634,7 +644,8 @@ public:
 
         //- Find and return a sub-dictionary, otherwise return this dictionary.
         //  Warn if the entry exists but is not a sub-dictionary.
-        //  (search type: non-recursive with patterns)
+        //
+        //  Search type: non-recursive with patterns.
         const dictionary& optionalSubDict(const word& keyword) const;
 
         //- Return the table of contents
@@ -669,34 +680,34 @@ public:
             bool mergeEntry = false
         );
 
-        //- Add a new entry
-        //  With the merge option, dictionaries are interwoven and
-        //  primitive entries are overwritten
+        //- Add a new entry.
+        //  \param mergeEntry dictionaries are interwoven and primitive
+        //         entries are overwritten
         bool add(entry* entryPtr, bool mergeEntry=false);
 
-        //- Add an entry
-        //  With the merge option, dictionaries are interwoven and
-        //  primitive entries are overwritten
+        //- Add an entry.
+        //  \param mergeEntry dictionaries are interwoven and primitive
+        //         entries are overwritten
         void add(const entry& e, bool mergeEntry=false);
 
-        //- Add a word entry
-        //  optionally overwrite an existing entry
+        //- Add a word entry.
+        //  \param overwrite force overwrite of an existing entry.
         void add(const keyType& k, const word& v, bool overwrite=false);
 
-        //- Add a string entry
-        //  optionally overwrite an existing entry
+        //- Add a string entry.
+        //  \param overwrite force overwrite of an existing entry.
         void add(const keyType& k, const string& v, bool overwrite=false);
 
-        //- Add a label entry
-        //  optionally overwrite an existing entry
+        //- Add a label entry.
+        //  \param overwrite force overwrite of an existing entry.
         void add(const keyType& k, const label v, bool overwrite=false);
 
-        //- Add a scalar entry
-        //  optionally overwrite an existing entry
+        //- Add a scalar entry.
+        //  \param overwrite force overwrite of an existing entry.
         void add(const keyType& k, const scalar v, bool overwrite=false);
 
-        //- Add a dictionary entry
-        //  optionally merge with an existing sub-dictionary
+        //- Add a dictionary entry.
+        //  \param mergeEntry merge into an existing sub-dictionary
         void add
         (
             const keyType& k,
@@ -705,20 +716,20 @@ public:
         );
 
         //- Add a T entry
-        //  optionally overwrite an existing entry
+        //  \param overwrite force overwrite of existing entry
         template<class T>
         void add(const keyType& k, const T& v, bool overwrite=false);
 
-        //- Assign a new entry, overwrite any existing entry
+        //- Assign a new entry, overwriting any existing entry.
         void set(entry* entryPtr);
 
-        //- Assign a new entry, overwrite any existing entry
+        //- Assign a new entry, overwriting any existing entry.
         void set(const entry& e);
 
-        //- Assign a dictionary entry, overwrite any existing entry
+        //- Assign a dictionary entry, overwriting any existing entry.
         void set(const keyType& k, const dictionary& v);
 
-        //- Assign a T entry, overwrite any existing entry
+        //- Assign a T entry, overwriting any existing entry.
         template<class T>
         void set(const keyType& k, const T& v);
 
@@ -726,12 +737,12 @@ public:
         bool remove(const word& keyword);
 
         //- Change the keyword for an entry,
-        //  optionally forcing overwrite of an existing entry
+        //  \param overwrite force overwrite of an existing entry.
         bool changeKeyword
         (
             const keyType& oldKeyword,
             const keyType& newKeyword,
-            bool forceOverwrite=false
+            bool overwrite=false
         );
 
         //- Merge entries from the given dictionary.
@@ -763,8 +774,8 @@ public:
         void writeEntry(const keyType& keyword, Ostream& os) const;
 
         //- Write dictionary entries.
-        //  Optionally with extra new line between entries for
-        //  "top-level" dictionaries
+        //  \param extraNewLine adds additional newline\n between entries
+        //         for "top-level" dictionaries
         void writeEntries(Ostream& os, const bool extraNewLine=false) const;
 
         //- Write dictionary, normally with sub-dictionary formatting
@@ -774,9 +785,10 @@ public:
       // Searching
 
         //- Search dictionary for given keyword
-        //  If recursive, search parent dictionaries
-        //  If patternMatch, use regular expressions
-        //  (default search: non-recursive with patterns).
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         const_searcher csearch
         (
             const word& keyword,
@@ -785,9 +797,10 @@ public:
         ) const;
 
         //- Search dictionary for given keyword
-        //  If recursive, search parent dictionaries
-        //  If patternMatch, use regular expressions
-        //  (default search: non-recursive with patterns).
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         const_searcher search
         (
             const word& keyword,
@@ -796,9 +809,10 @@ public:
         ) const;
 
         //- Search dictionary for given keyword
-        //  If recursive, search parent dictionaries
-        //  If patternMatch, use regular expressions
-        //  (default search: non-recursive with patterns).
+        //  Default search: non-recursive with patterns.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         searcher search
         (
             const word& keyword,
@@ -826,6 +840,9 @@ public:
         //  Any doubled slashes are silently ignored.
         //  Since a slash is not a valid keyword character, there is no
         //  ambiguity between separator and content.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         const_searcher csearchScoped
         (
             const word& keyword,
@@ -834,6 +851,9 @@ public:
         ) const;
 
         //- Search using dot or slash scoping.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         const_searcher searchScoped
         (
             const word& keyword,
@@ -842,6 +862,9 @@ public:
         ) const;
 
         //- Search using dot or slash scoping.
+        //
+        //  \param recursive search parent dictionaries
+        //  \param patternMatch use regular expressions
         searcher searchScoped
         (
             const word& keyword,
diff --git a/src/OpenFOAM/db/dictionary/dictionarySearch.C b/src/OpenFOAM/db/dictionary/dictionarySearch.C
index 93c5bcb884a..cc711af70a5 100644
--- a/src/OpenFOAM/db/dictionary/dictionarySearch.C
+++ b/src/OpenFOAM/db/dictionary/dictionarySearch.C
@@ -631,7 +631,7 @@ bool Foam::dictionary::changeKeyword
 (
     const keyType& oldKeyword,
     const keyType& newKeyword,
-    bool forceOverwrite
+    bool overwrite
 )
 {
     // No change
@@ -665,7 +665,7 @@ bool Foam::dictionary::changeKeyword
     // newKeyword already exists
     if (iter2.found())
     {
-        if (forceOverwrite)
+        if (overwrite)
         {
             if (iter2()->keyword().isPattern())
             {
diff --git a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
index d0446b6770f..9e887c08f61 100644
--- a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
+++ b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -74,18 +74,16 @@ T Foam::dictionary::lookupOrDefault
     {
         return pTraits<T>(finder.ptr()->stream());
     }
-    else
+
+    if (writeOptionalEntries)
     {
-        if (writeOptionalEntries)
-        {
-            IOInfoInFunction(*this)
-                << "Optional entry '" << keyword << "' is not present,"
-                << " returning the default value '" << deflt << "'"
-                << endl;
-        }
-
-        return deflt;
+        IOInfoInFunction(*this)
+            << "Optional entry '" << keyword << "' is not present,"
+            << " returning the default value '" << deflt << "'"
+            << endl;
     }
+
+    return deflt;
 }
 
 
@@ -104,19 +102,17 @@ T Foam::dictionary::lookupOrAddDefault
     {
         return pTraits<T>(finder.ptr()->stream());
     }
-    else
+
+    if (writeOptionalEntries)
     {
-        if (writeOptionalEntries)
-        {
-            IOInfoInFunction(*this)
-                << "Optional entry '" << keyword << "' is not present,"
-                << " adding and returning the default value '" << deflt << "'"
-                << endl;
-        }
-
-        add(new primitiveEntry(keyword, deflt));
-        return deflt;
+        IOInfoInFunction(*this)
+            << "Optional entry '" << keyword << "' is not present,"
+            << " adding and returning the default value '" << deflt << "'"
+            << endl;
     }
+
+    add(new primitiveEntry(keyword, deflt));
+    return deflt;
 }
 
 
@@ -136,18 +132,16 @@ bool Foam::dictionary::readIfPresent
         finder.ptr()->stream() >> val;
         return true;
     }
-    else
+
+    if (writeOptionalEntries)
     {
-        if (writeOptionalEntries)
-        {
-            IOInfoInFunction(*this)
-                << "Optional entry '" << keyword << "' is not present,"
-                << " the default value '" << val << "' will be used."
-                << endl;
-        }
-
-        return false;
+        IOInfoInFunction(*this)
+            << "Optional entry '" << keyword << "' is not present,"
+            << " the default value '" << val << "' will be used."
+            << endl;
     }
+
+    return false;
 }
 
 
-- 
GitLab