From 971213eb5501563494fce9ecd02b7fd73a21483c Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Mon, 10 Jul 2017 14:06:45 +0200 Subject: [PATCH 001/126] ENH: add dictionary searcher methods - csearch(), search(), csearchScoped(), searchScoped() methods can be used to find an entry and also retain the enclosing dictionary context. - To avoid ambiguity between a dot (.) as a scoping character and legal part of a keyword, entries can now be accessed directly using slash-scoping semantics similar to file-names: * cfindScopedDictPtr, findScopedDictPtr - To get or create a sub-dictionary entry: * makeScopedDictPtr, which behaves similarly to mkdirp in that it will create any intermediate dictionaries as required. --- src/OpenFOAM/Make/files | 1 + src/OpenFOAM/db/dictionary/dictionary.C | 587 +++---------- src/OpenFOAM/db/dictionary/dictionary.H | 775 ++++++++++++------ src/OpenFOAM/db/dictionary/dictionaryIO.C | 24 - src/OpenFOAM/db/dictionary/dictionarySearch.C | 719 ++++++++++++++++ .../db/dictionary/dictionaryTemplates.C | 32 +- src/OpenFOAM/db/dictionary/entry/entryIO.C | 24 +- 7 files changed, 1399 insertions(+), 763 deletions(-) create mode 100644 src/OpenFOAM/db/dictionary/dictionarySearch.C diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 4a6adb98a1..80b6239039 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -203,6 +203,7 @@ $(Pstreams)/PstreamBuffers.C dictionary = db/dictionary $(dictionary)/dictionary.C $(dictionary)/dictionaryIO.C +$(dictionary)/dictionarySearch.C entry = $(dictionary)/entry $(entry)/entry.C diff --git a/src/OpenFOAM/db/dictionary/dictionary.C b/src/OpenFOAM/db/dictionary/dictionary.C index 33acac0ace..46cee88d67 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.C +++ b/src/OpenFOAM/db/dictionary/dictionary.C @@ -45,157 +45,6 @@ bool Foam::dictionary::writeOptionalEntries ); -// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // - -namespace Foam -{ - // file-scope - //- Walk lists of patterns and regexps for an exact match - // or regular expression match - template - static bool findInPatterns - ( - const bool patternMatch, - const word& keyword, - WcIterator& wcIter, - ReIterator& reIter - ) - { - while (wcIter.found()) - { - if - ( - patternMatch - ? reIter()->match(keyword) - : wcIter()->keyword() == keyword - ) - { - return true; - } - - ++reIter; - ++wcIter; - } - - return false; - } -} - - -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - -const Foam::entry* Foam::dictionary::lookupScopedSubEntryPtr -( - const word& keyword, - bool recursive, - bool patternMatch -) const -{ - string::size_type dotPos = keyword.find('.'); - - if (dotPos == string::npos) - { - // Non-scoped lookup - return lookupEntryPtr(keyword, recursive, patternMatch); - } - else if (dotPos == 0) - { - // Starting with a '.' -> go up for every further '.' found - ++dotPos; - - const dictionary* dictPtr = this; - for - ( - string::const_iterator it = keyword.begin()+1; - it != keyword.end() && *it == '.'; - ++dotPos, ++it - ) - { - // Go to parent - if (&dictPtr->parent_ != &dictionary::null) - { - dictPtr = &dictPtr->parent_; - } - else - { - FatalIOErrorInFunction - ( - *this - ) << "No parent of current dictionary when searching for " - << keyword.substr(1) - << exit(FatalIOError); - - return nullptr; - } - } - - return dictPtr->lookupScopedSubEntryPtr - ( - keyword.substr(dotPos), - false, - patternMatch - ); - } - else - { - // The first word - const entry* entPtr = lookupScopedSubEntryPtr - ( - keyword.substr(0, dotPos), - false, - patternMatch - ); - - if (!entPtr) - { - // Fall back to finding key with '.' so e.g. if keyword is - // a.b.c.d it would try - // a.b, a.b.c, a.b.c.d - - while (true) - { - dotPos = keyword.find('.', dotPos+1); - - entPtr = lookupEntryPtr - ( - keyword.substr(0, dotPos), - false, - patternMatch - ); - - if (dotPos == string::npos) - { - // Parsed the whole word. Return entry or null. - return entPtr; - } - - if (entPtr && entPtr->isDict()) - { - return entPtr->dict().lookupScopedSubEntryPtr - ( - keyword.substr(dotPos), - false, - patternMatch - ); - } - } - } - - if (entPtr->isDict()) - { - return entPtr->dict().lookupScopedSubEntryPtr - ( - keyword.substr(dotPos), - false, - patternMatch - ); - } - } - - return nullptr; -} - - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::dictionary::dictionary() @@ -395,29 +244,7 @@ bool Foam::dictionary::found bool patternMatch ) const { - if (hashedEntries_.found(keyword)) - { - return true; - } - - if (patternMatch && patterns_.size()) - { - pattern_const_iterator wcLink = patterns_.begin(); - regexp_const_iterator reLink = regexps_.begin(); - - // Find in patterns using regular expressions only - if (findInPatterns(patternMatch, keyword, wcLink, reLink)) - { - return true; - } - } - - if (recursive && &parent_ != &dictionary::null) - { - return parent_.found(keyword, recursive, patternMatch); - } - - return false; + return csearch(keyword, recursive, patternMatch).found(); } @@ -428,31 +255,7 @@ const Foam::entry* Foam::dictionary::lookupEntryPtr bool patternMatch ) const { - auto iter = hashedEntries_.cfind(keyword); - - if (iter.found()) - { - return iter(); - } - - if (patternMatch && patterns_.size()) - { - pattern_const_iterator wcLink = patterns_.begin(); - regexp_const_iterator reLink = regexps_.begin(); - - // Find in patterns using regular expressions only - if (findInPatterns(patternMatch, keyword, wcLink, reLink)) - { - return wcLink(); - } - } - - if (recursive && &parent_ != &dictionary::null) - { - return parent_.lookupEntryPtr(keyword, recursive, patternMatch); - } - - return nullptr; + return csearch(keyword, recursive, patternMatch).ptr(); } @@ -463,36 +266,7 @@ Foam::entry* Foam::dictionary::lookupEntryPtr bool patternMatch ) { - auto iter = hashedEntries_.find(keyword); - - if (iter.found()) - { - return iter(); - } - - if (patternMatch && patterns_.size()) - { - pattern_iterator wcLink = patterns_.begin(); - regexp_iterator reLink = regexps_.begin(); - - // Find in patterns using regular expressions only - if (findInPatterns(patternMatch, keyword, wcLink, reLink)) - { - return wcLink(); - } - } - - if (recursive && &parent_ != &dictionary::null) - { - return const_cast(parent_).lookupEntryPtr - ( - keyword, - recursive, - patternMatch - ); - } - - return nullptr; + return search(keyword, recursive, patternMatch).ptr(); } @@ -503,9 +277,9 @@ const Foam::entry& Foam::dictionary::lookupEntry bool patternMatch ) const { - const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch); + auto finder = csearch(keyword, recursive, patternMatch); - if (entryPtr == nullptr) + if (!finder.found()) { FatalIOErrorInFunction ( @@ -515,7 +289,7 @@ const Foam::entry& Foam::dictionary::lookupEntry << exit(FatalIOError); } - return *entryPtr; + return finder.ref(); } @@ -537,29 +311,37 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr bool patternMatch ) const { - if ((keyword[0] == ':' || keyword[0] == '^')) - { - // Go up to top level - const dictionary* dictPtr = this; - while (&dictPtr->parent_ != &dictionary::null) - { - dictPtr = &dictPtr->parent_; - } + return csearchScoped(keyword, recursive, patternMatch).ptr(); +} - return dictPtr->lookupScopedSubEntryPtr - ( - keyword.substr(1), - false, - patternMatch - ); + +bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry) +{ + if (keyword.size() < 2) + { + return false; } - return lookupScopedSubEntryPtr - ( - keyword, - recursive, - patternMatch - ); + // Drop leading '$' to get the var-name, already validated as word. + const word varName(keyword.substr(1), false); + + // Lookup the variable name in the given dictionary + const_searcher finder = csearch(varName, true, true); + + // If defined insert its entries into this dictionary + if (finder.found()) + { + const dictionary& addDict = finder.dict(); + + forAllConstIters(addDict, iter) + { + add(iter(), mergeEntry); + } + + return true; + } + + return false; } @@ -569,16 +351,21 @@ bool Foam::dictionary::substituteScopedKeyword bool mergeEntry ) { - // Drop first character of keyword to get the var-name, already validated. + if (keyword.size() < 2) + { + return false; + } + + // Drop leading '$' to get the var-name, already validated as word. const word varName(keyword.substr(1), false); // Lookup the variable name in the given dictionary - const entry* ePtr = lookupScopedEntryPtr(varName, true, true); + const_searcher finder = csearchScoped(varName, true, true); // If defined insert its entries into this dictionary - if (ePtr != nullptr) + if (finder.found()) { - const dictionary& addDict = ePtr->dict(); + const dictionary& addDict = finder.dict(); forAllConstIter(parent_type, addDict, iter) { @@ -595,54 +382,30 @@ bool Foam::dictionary::substituteScopedKeyword bool Foam::dictionary::isDict(const word& keyword) const { // Find non-recursive with patterns - const entry* entryPtr = lookupEntryPtr(keyword, false, true); - - if (entryPtr) - { - return entryPtr->isDict(); - } - else - { - return false; - } + return csearch(keyword, false, true).isDict(); } const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const { - const entry* entryPtr = lookupEntryPtr(keyword, false, true); - - if (entryPtr) - { - return &entryPtr->dict(); - } - else - { - return nullptr; - } + // Find non-recursive with patterns + return csearch(keyword, false, true).dictPtr(); } Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) { - entry* entryPtr = lookupEntryPtr(keyword, false, true); - - if (entryPtr) - { - return &entryPtr->dict(); - } - else - { - return nullptr; - } + // Find non-recursive with patterns + return search(keyword, false, true).dictPtr(); } const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const { - const entry* entryPtr = lookupEntryPtr(keyword, false, true); + // Find non-recursive with patterns + auto finder = csearch(keyword, false, true); - if (entryPtr == nullptr) + if (!finder.found()) { FatalIOErrorInFunction ( @@ -651,15 +414,17 @@ const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const << name() << exit(FatalIOError); } - return entryPtr->dict(); + + return finder.dict(); } Foam::dictionary& Foam::dictionary::subDict(const word& keyword) { - entry* entryPtr = lookupEntryPtr(keyword, false, true); + // Find non-recursive with patterns + auto finder = search(keyword, false, true); - if (entryPtr == nullptr) + if (!finder.found()) { FatalIOErrorInFunction ( @@ -668,7 +433,8 @@ Foam::dictionary& Foam::dictionary::subDict(const word& keyword) << name() << exit(FatalIOError); } - return entryPtr->dict(); + + return finder.dict(); } @@ -678,29 +444,35 @@ Foam::dictionary Foam::dictionary::subOrEmptyDict const bool mustRead ) const { - const entry* entryPtr = lookupEntryPtr(keyword, false, true); + // Find non-recursive with patterns + auto finder = csearch(keyword, false, true); - if (entryPtr == nullptr) + if (finder.isDict()) { - if (mustRead) - { - FatalIOErrorInFunction - ( - *this - ) << "keyword " << keyword << " is undefined in dictionary " - << name() - << exit(FatalIOError); - return entryPtr->dict(); - } - else - { - return dictionary(*this, dictionary(name() + '.' + keyword)); - } + // Found and a sub-dictionary + return finder.dict(); } - else + + if (mustRead) { - return entryPtr->dict(); + FatalIOErrorInFunction + ( + *this + ) << "keyword " << keyword + << " is not a sub-dictionary in dictionary " + << name() + << exit(FatalIOError); } + + if (finder.found()) + { + IOWarningInFunction((*this)) + << "keyword " << keyword + << " found but not a sub-dictionary in dictionary " + << name() << endl; + } + + return dictionary(*this, dictionary(name() + '.' + keyword)); } @@ -709,16 +481,23 @@ const Foam::dictionary& Foam::dictionary::optionalSubDict const word& keyword ) const { - const entry* entryPtr = lookupEntryPtr(keyword, false, true); + auto finder = csearch(keyword, false, true); - if (entryPtr) + if (finder.isDict()) { - return entryPtr->dict(); + // Found and a sub-dictionary + return finder.dict(); } - else + + if (finder.found()) { - return *this; + IOWarningInFunction((*this)) + << "keyword " << keyword + << " found but not a sub-dictionary in dictionary " + << name() << endl; } + + return *this; } @@ -726,10 +505,10 @@ Foam::wordList Foam::dictionary::toc() const { wordList keys(size()); - label nKeys = 0; - forAllConstIter(parent_type, *this, iter) + label n = 0; + forAllConstIters(*this, iter) { - keys[nKeys++] = iter().keyword(); + keys[n++] = iter().keyword(); } return keys; @@ -746,15 +525,15 @@ Foam::List Foam::dictionary::keys(bool patterns) const { List keys(size()); - label nKeys = 0; - forAllConstIter(parent_type, *this, iter) + label n = 0; + forAllConstIters(*this, iter) { if (iter().keyword().isPattern() ? patterns : !patterns) { - keys[nKeys++] = iter().keyword(); + keys[n++] = iter().keyword(); } } - keys.setSize(nKeys); + keys.setSize(n); return keys; } @@ -844,55 +623,55 @@ void Foam::dictionary::add(const entry& e, bool mergeEntry) } -void Foam::dictionary::add(const keyType& k, const word& w, bool overwrite) +void Foam::dictionary::add(const keyType& k, const word& v, bool overwrite) { - add(new primitiveEntry(k, token(w)), overwrite); + add(new primitiveEntry(k, token(v)), overwrite); } void Foam::dictionary::add ( const keyType& k, - const Foam::string& s, + const Foam::string& v, bool overwrite ) { - add(new primitiveEntry(k, token(s)), overwrite); + add(new primitiveEntry(k, token(v)), overwrite); } -void Foam::dictionary::add(const keyType& k, const label l, bool overwrite) +void Foam::dictionary::add(const keyType& k, const label v, bool overwrite) { - add(new primitiveEntry(k, token(l)), overwrite); + add(new primitiveEntry(k, token(v)), overwrite); } -void Foam::dictionary::add(const keyType& k, const scalar s, bool overwrite) +void Foam::dictionary::add(const keyType& k, const scalar v, bool overwrite) { - add(new primitiveEntry(k, token(s)), overwrite); + add(new primitiveEntry(k, token(v)), overwrite); } void Foam::dictionary::add ( const keyType& k, - const dictionary& d, + const dictionary& v, bool mergeEntry ) { - add(new dictionaryEntry(k, *this, d), mergeEntry); + add(new dictionaryEntry(k, *this, v), mergeEntry); } void Foam::dictionary::set(entry* entryPtr) { // Find non-recursive with patterns - entry* existingPtr = lookupEntryPtr(entryPtr->keyword(), false, true); + auto finder = search(entryPtr->keyword(), false, true); // Clear dictionary so merge acts like overwrite - if (existingPtr && existingPtr->isDict()) + if (finder.isDict()) { - existingPtr->dict().clear(); + finder.dict().clear(); } add(entryPtr, true); } @@ -904,134 +683,14 @@ void Foam::dictionary::set(const entry& e) } -void Foam::dictionary::set(const keyType& k, const dictionary& d) +void Foam::dictionary::set(const keyType& k, const dictionary& v) { - set(new dictionaryEntry(k, *this, d)); -} - - -bool Foam::dictionary::remove(const word& keyword) -{ - auto iter = hashedEntries_.find(keyword); - - if (iter.found()) - { - // Delete from patterns - pattern_iterator wcLink = patterns_.begin(); - regexp_iterator reLink = regexps_.begin(); - - // Find in pattern using exact match only - if (findInPatterns(false, keyword, wcLink, reLink)) - { - patterns_.remove(wcLink); - regexps_.remove(reLink); - } - - parent_type::remove(iter()); - delete iter(); - hashedEntries_.erase(iter); - - return true; - } - else - { - return false; - } -} - - -bool Foam::dictionary::changeKeyword -( - const keyType& oldKeyword, - const keyType& newKeyword, - bool forceOverwrite -) -{ - // No change - if (oldKeyword == newKeyword) - { - return false; - } - - // Check that oldKeyword exists and can be changed - auto iter = hashedEntries_.find(oldKeyword); - - if (!iter.found()) - { - return false; - } - - if (iter()->keyword().isPattern()) - { - FatalIOErrorInFunction - ( - *this - ) << "Old keyword "<< oldKeyword - << " is a pattern." - << "Pattern replacement not yet implemented." - << exit(FatalIOError); - } - - - auto iter2 = hashedEntries_.find(newKeyword); - - // newKeyword already exists - if (iter2.found()) - { - if (forceOverwrite) - { - if (iter2()->keyword().isPattern()) - { - // Delete from patterns - pattern_iterator wcLink = patterns_.begin(); - regexp_iterator reLink = regexps_.begin(); - - // Find in patterns using exact match only - if (findInPatterns(false, iter2()->keyword(), wcLink, reLink)) - { - patterns_.remove(wcLink); - regexps_.remove(reLink); - } - } - - parent_type::replace(iter2(), iter()); - delete iter2(); - hashedEntries_.erase(iter2); - } - else - { - IOWarningInFunction - ( - *this - ) << "cannot rename keyword "<< oldKeyword - << " to existing keyword " << newKeyword - << " in dictionary " << name() << endl; - return false; - } - } - - // Change name and HashTable, but leave DL-List untouched - iter()->keyword() = newKeyword; - iter()->name() = name() + '.' + newKeyword; - hashedEntries_.erase(oldKeyword); - hashedEntries_.insert(newKeyword, iter()); - - if (newKeyword.isPattern()) - { - patterns_.insert(iter()); - regexps_.insert - ( - autoPtr(new regExp(newKeyword)) - ); - } - - return true; + set(new dictionaryEntry(k, *this, v)); } bool Foam::dictionary::merge(const dictionary& dict) { - // Check for assignment to self if (this == &dict) { FatalIOErrorInFunction(*this) @@ -1041,7 +700,7 @@ bool Foam::dictionary::merge(const dictionary& dict) bool changed = false; - forAllConstIter(parent_type, dict, iter) + forAllConstIters(dict, iter) { auto fnd = hashedEntries_.find(iter().keyword()); @@ -1112,7 +771,6 @@ Foam::ITstream& Foam::dictionary::operator[](const word& keyword) const void Foam::dictionary::operator=(const dictionary& rhs) { - // Check for assignment to self if (this == &rhs) { FatalIOErrorInFunction(*this) @@ -1126,7 +784,7 @@ void Foam::dictionary::operator=(const dictionary& rhs) // Create clones of the entries in the given dictionary // resetting the parentDict to this dictionary - forAllConstIter(parent_type, rhs, iter) + forAllConstIters(rhs, iter) { add(iter().clone(*this).ptr()); } @@ -1135,7 +793,6 @@ void Foam::dictionary::operator=(const dictionary& rhs) void Foam::dictionary::operator+=(const dictionary& rhs) { - // Check for assignment to self if (this == &rhs) { FatalIOErrorInFunction(*this) @@ -1143,7 +800,7 @@ void Foam::dictionary::operator+=(const dictionary& rhs) << abort(FatalIOError); } - forAllConstIter(parent_type, rhs, iter) + forAllConstIters(rhs, iter) { add(iter().clone(*this).ptr()); } @@ -1152,7 +809,6 @@ void Foam::dictionary::operator+=(const dictionary& rhs) void Foam::dictionary::operator|=(const dictionary& rhs) { - // Check for assignment to self if (this == &rhs) { FatalIOErrorInFunction(*this) @@ -1160,7 +816,7 @@ void Foam::dictionary::operator|=(const dictionary& rhs) << abort(FatalIOError); } - forAllConstIter(parent_type, rhs, iter) + forAllConstIters(rhs, iter) { if (!found(iter().keyword())) { @@ -1172,7 +828,6 @@ void Foam::dictionary::operator|=(const dictionary& rhs) void Foam::dictionary::operator<<=(const dictionary& rhs) { - // Check for assignment to self if (this == &rhs) { FatalIOErrorInFunction(*this) @@ -1180,7 +835,7 @@ void Foam::dictionary::operator<<=(const dictionary& rhs) << abort(FatalIOError); } - forAllConstIter(parent_type, rhs, iter) + forAllConstIters(rhs, iter) { set(iter().clone(*this).ptr()); } diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H index f0c66b97a8..783c643656 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.H +++ b/src/OpenFOAM/db/dictionary/dictionary.H @@ -41,10 +41,13 @@ Description Note Within dictionaries, entries can be referenced by using the '$' syntax - familiar from shell programming. A '.' separator is used when referencing - sub-dictionary entries. Leading '.' prefixes can be used to specify - an entry from a parent directory. A leading ':' or '^' prefix specifies - starting from the top-level entry. For example, + familiar from shell programming. + A '.' separator is used when referencing sub-dictionary entries. + Leading '.' prefixes can be used to specify an entry from a parent + dictionary. + An initial '^' anchor (or ':' for backward compatibility) specifies + starting from the top-level entry. + For example, \verbatim key1 val1; @@ -70,6 +73,7 @@ Note SourceFiles dictionary.C dictionaryIO.C + dictionarySearch.C SeeAlso - Foam::entry @@ -89,6 +93,7 @@ SeeAlso #include "HashTable.H" #include "wordList.H" #include "className.H" +#include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -148,22 +153,20 @@ public: const word dictName() const { const word scopedName = name_.name(); - const std::string::size_type i = scopedName.rfind('.'); + const auto i = scopedName.rfind('.'); if (i == std::string::npos) { return scopedName; } - else - { - return scopedName.substr(i+1); - } + + return scopedName.substr(i+1); } }; /*---------------------------------------------------------------------------*\ - Class dictionary Declaration + Class dictionary Declaration \*---------------------------------------------------------------------------*/ class dictionary @@ -171,15 +174,157 @@ class dictionary public dictionaryName, public IDLList { +public: + + // Searching + + //- Generic const/non-const dictionary entry %searcher. + // A %searcher provides a uniform means of finding and returning + // an entry pointer as well as the dictionary \a context in which + // the entry was located. + // + // Note that the constructors and set methods are protected such + // that only friends of the class can set things. This safeguards + // against inconsistencies in context/entry. + template + class Searcher + { + public: + friend dictionary; + + //- The const/non-const type for the context and sub-dictionaries + typedef typename std::conditional + ::type dict_type; + + //- The const/non-const type for entries + typedef typename std::conditional + ::type value_type; + + //- A pointer to a const/non-const dictionary + typedef dict_type* dict_pointer; + + //- A reference to a const/non-const dictionary + typedef dict_type& dict_reference; + + //- A pointer to a const/non-const entry + typedef value_type* pointer; + + //- A reference to a const/non-const entry + typedef value_type& reference; + + + protected: + + //- The dictionary context for the entry + dict_pointer dict_; + + //- The entry or nullptr + pointer eptr_; + + + //- Construct null + Searcher() + : + dict_(nullptr), + eptr_(nullptr) + {} + + //- Construct for the given dictionary context + Searcher(dict_pointer dict) + : + dict_(dict), + eptr_(nullptr) + {} + + //- Assign the entry + void set(pointer eptr) + { + eptr_ = eptr; + } + + + public: + + //- Entry was found. + inline bool found() const + { + return eptr_; + } + + //- The containing dictionary context + inline dict_reference context() const + { + return *dict_; + } + + //- A pointer to the entry (nullptr if not found) + inline pointer ptr() const + { + return eptr_; + } + + //- A reference to the entry (Error if not found) + inline reference ref() const + { + return *eptr_; + } + + //- True if found entry is a dictionary. + inline bool isDict() const + { + return eptr_ && eptr_->isDict(); + } + + //- Pointer to the found entry as a dictionary or nullptr otherwise. + inline dict_pointer dictPtr() const + { + return eptr_ && eptr_->isDict() ? eptr_->dictPtr() : nullptr; + } + + //- Reference the found entry as a dictionary. + // (Error if not found, or not a dictionary). + inline dict_reference dict() const + { + return eptr_->dict(); + } + + //- Permit an explicit cast to the other (const/non-const) searcher + inline explicit operator const Searcher&() const + { + return *reinterpret_cast*>(this); + } + }; + + + //- Searcher with const access + typedef Searcher const_searcher; + + //- Searcher with non-const access + typedef Searcher searcher; + + + // Friends + + //- Declare friendship with the entry class for IO + friend class entry; + + //- Declare friendship with the searcher classes + friend const_searcher; + friend searcher; + + +private: + // Private data //- Report optional keywords and values if not present in dictionary + // Set/unset via an InfoSwitch static bool writeOptionalEntries; //- Parent dictionary const dictionary& parent_; - //- HashTable of the entries held on the IDLList for quick lookup + //- Quick lookup of the entries held on the IDLList HashTable hashedEntries_; //- Entries of matching patterns @@ -196,28 +341,49 @@ class dictionary typedef DLList::iterator pattern_iterator; typedef DLList::const_iterator pattern_const_iterator; + typedef DLList>::iterator regexp_iterator; typedef DLList>::const_iterator regexp_const_iterator; // Private Member Functions - //- Find and return an entry data stream pointer if present - // otherwise return nullptr. Allows scoping using '.' - const entry* lookupScopedSubEntryPtr + //- Search using a '.' for scoping. + // A leading dot means to use the parent dictionary. + // An intermediate dot separates a sub-dictionary or sub-entry. + // However, the use of dots is unfortunately ambiguous. + // The value "a.b.c.d" could be a first-level entry, a second-level + // entry (eg, "a" with "b.c.d", "a.b" with "c.d" etc), + // or just about any other combination. + // The heuristic tries sucessively longer top-level entries + // until there is a suitable match. + // + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + const_searcher csearchDotScoped ( const word& keyword, bool recursive, bool patternMatch ) const; + //- Search using a '/' for scoping. + // Semantics as per normal files: an intermediate "." is the current + // dictionary level, an intermediate ".." is the parent dictionary. + // Note that since a slash is not a valid word character, there is no + // ambiguity between separator and content. + // No possibility or need for recursion. + // + // \param patternMatch use regular expressions + const_searcher csearchSlashScoped + ( + const word& keyword, + bool patternMatch + ) const; + public: - //- Declare friendship with the entry class for IO - friend class entry; - - // Declare name of the class and its debug switch ClassName("dictionary"); @@ -234,7 +400,7 @@ public: explicit dictionary(const fileName& name); //- Construct given the entry name, parent dictionary and Istream, - // reading entries until lastEntry or EOF + // reading entries until EOF dictionary ( const fileName& name, @@ -251,7 +417,7 @@ public: dictionary(Istream& is, const bool keepHeader); //- Construct as copy given the parent dictionary - dictionary(const dictionary& parentDict, const dictionary&); + dictionary(const dictionary& parentDict, const dictionary& dict); //- Construct top-level dictionary as copy dictionary(const dictionary& dict); @@ -303,284 +469,413 @@ public: tokenList tokens() const; - // Search and lookup + // Search and lookup - //- Search dictionary for given keyword - // If recursive, search parent dictionaries - // If patternMatch, use regular expressions - bool found - ( - const word& keyword, - bool recursive = false, - bool patternMatch = true - ) const; + //- Search dictionary for given keyword + // If recursive, search parent dictionaries + // If patternMatch, use regular expressions + // (default search: non-recursive with patterns). + bool found + ( + const word& keyword, + bool recursive = false, + 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 - const entry* lookupEntryPtr - ( - const word& keyword, - bool recursive, - bool patternMatch - ) const; + //- Find and return an entry data stream pointer if present + // otherwise return nullptr. + // If recursive, search parent dictionaries. + // If patternMatch, use regular expressions + const entry* lookupEntryPtr + ( + const word& keyword, + bool recursive, + 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. - entry* lookupEntryPtr - ( - const word& keyword, - bool recursive, - bool patternMatch - ); + //- 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. + entry* lookupEntryPtr + ( + const word& keyword, + bool recursive, + bool patternMatch + ); - //- Find and return an entry data stream if present otherwise error. - // If recursive, search parent dictionaries. - // If patternMatch, use regular expressions. - const entry& lookupEntry - ( - const word& keyword, - bool recursive, - bool patternMatch - ) const; + //- Find and return an entry data stream if present otherwise error. + // If recursive, search parent dictionaries. + // If patternMatch, use regular expressions. + const entry& lookupEntry + ( + const word& keyword, + bool recursive, + bool patternMatch + ) const; - //- Find and return an entry data stream - // If recursive, search parent dictionaries. - // If patternMatch, use regular expressions. - ITstream& lookup - ( - const word& keyword, - bool recursive = false, - bool patternMatch = true - ) const; + //- Find and return an entry data stream + // If recursive, search parent dictionaries. + // If patternMatch, use regular expressions. + // (default search: non-recursive with patterns). + ITstream& lookup + ( + const word& keyword, + bool recursive = false, + 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. - template - T lookupType - ( - const word&, - bool recursive=false, - 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). + template + T lookupType + ( + const word& keyword, + bool recursive = false, + bool patternMatch = true + ) const; - //- Find and return a T, or return the given default value - // If recursive, search parent dictionaries. - // If patternMatch, use regular expressions. - template - T lookupOrDefault - ( - const word& keyword, - const T& deflt, - bool recursive = false, - bool patternMatch = true - ) 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). + template + T lookupOrDefault + ( + const word& keyword, + const T& deflt, + bool recursive = false, + bool patternMatch = true + ) const; - //- Find and return a T, if not found return the given - // default value, and add to dictionary. - // If recursive, search parent dictionaries. - // If patternMatch, use regular expressions. - template - T lookupOrAddDefault - ( - const word& keyword, - const T& deflt, - bool recursive = false, - bool patternMatch = true - ); + //- Find and return a T, if not found return the default value + // and add it to dictionary. + // Default search: non-recursive with patterns. + // + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + template + T lookupOrAddDefault + ( + const word& keyword, + const T& deflt, + bool recursive = false, + bool patternMatch = true + ); - //- Find an entry if present, and assign to T - // Returns true if the entry was found. - // If recursive, search parent dictionaries. - // If patternMatch, use regular expressions. - template - bool readIfPresent - ( - const word& keyword, - T& val, - bool recursive = false, - bool patternMatch = true - ) const; + //- Find an entry if present, and assign to T val. + // Default search: non-recursive with patterns. + // + // \param val the value to read + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + // + // \return true if the entry was found. + template + bool readIfPresent + ( + const word& keyword, + T& val, + bool recursive = false, + bool patternMatch = true + ) const; - //- Find and return an entry data stream pointer if present - // otherwise return nullptr. Allows scoping using '.'. - // Special handling for ':' at start of keyword and '..'. - const entry* lookupScopedEntryPtr - ( - const word& keyword, - bool recursive, - bool patternMatch - ) const; + //- Find and return an entry pointer if present, or return a nullptr. + // Allows scoping using '.'. + // Special handling for an absolute anchor (^) at start of the keyword + // and for '..' to ascend into the parent dictionaries. + // + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + const entry* lookupScopedEntryPtr + ( + const word& keyword, + bool recursive, + bool patternMatch + ) const; - //- Check if entry is a sub-dictionary - bool isDict(const word& keyword) const; + //- Check if entry exists and is a sub-dictionary. + // (search type: non-recursive with patterns) + bool isDict(const word& keyword) const; - //- Find and return a sub-dictionary pointer if present - // otherwise return nullptr. - const dictionary* subDictPtr(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) + const dictionary* subDictPtr(const word& keyword) const; - //- Find and return a sub-dictionary pointer if present - // otherwise return nullptr. - dictionary* subDictPtr(const word& keyword); + //- Find and return a sub-dictionary pointer if present + // (and a sub-dictionary) otherwise return nullptr. + // + // Search type: non-recursive with patterns. + dictionary* subDictPtr(const word& keyword); - //- Find and return a sub-dictionary - const dictionary& subDict(const word& keyword) const; + //- 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) + const dictionary& subDict(const word& keyword) const; - //- Find and return a sub-dictionary for manipulation - dictionary& subDict(const word& keyword); + //- 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) + dictionary& subDict(const word& keyword); - //- Find and return a sub-dictionary as a copy, or - // return an empty dictionary if the sub-dictionary does not exist - dictionary subOrEmptyDict - ( - const word& keyword, - const bool mustRead = false - ) const; + //- 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) + dictionary subOrEmptyDict + ( + const word& keyword, + const bool mustRead = false + ) const; - //- Find and return a sub-dictionary if found - // otherwise return this dictionary - const dictionary& optionalSubDict(const word&) const; + //- 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) + const dictionary& optionalSubDict(const word& keyword) const; - //- Return the table of contents - wordList toc() const; + //- Return the table of contents + wordList toc() const; - //- Return the sorted table of contents - wordList sortedToc() const; + //- Return the sorted table of contents + wordList sortedToc() const; - //- Return table of contents sorted using the specified comparator - template - wordList sortedToc(const Compare& comp) const; + //- Return table of contents sorted using the specified comparator + template + wordList sortedToc(const Compare& comp) const; - //- Return the list of available keys or patterns - List keys(bool patterns = false) const; + //- Return the list of available keys or patterns + List keys(bool patterns = false) const; - // Editing + // Editing - //- Substitute the given keyword prepended by '$' with the - // corresponding sub-dictionary entries - bool substituteKeyword(const word& keyword, bool mergeEntry=false); + //- Substitute the given keyword (which is prefixed by '$') + // with the corresponding sub-dictionary entries + bool substituteKeyword + ( + const word& keyword, + bool mergeEntry = false + ); - //- Substitute the given scoped keyword prepended by '$' with the - // corresponding sub-dictionary entries - bool substituteScopedKeyword - ( - const word& keyword, - bool mergeEntry=false - ); + //- Substitute the given scoped keyword (which is prefixed by '$') + // with the corresponding sub-dictionary entries + bool substituteScopedKeyword + ( + const word& keyword, + bool mergeEntry = false + ); - //- Add a new entry - // With the merge option, dictionaries are interwoven and - // primitive entries are overwritten - bool add(entry* entryPtr, bool mergeEntry=false); + //- Add a new entry + // With the merge option, 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 - void add(const entry& e, bool mergeEntry=false); + //- Add an entry + // With the merge option, 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 - void add(const keyType& k, const word& w, bool overwrite=false); + //- Add a word entry + // optionally overwrite an existing entry + void add(const keyType& k, const word& v, bool overwrite=false); - //- Add a string entry - // optionally overwrite an existing entry - void add(const keyType& k, const string& s, bool overwrite=false); + //- Add a string entry + // optionally overwrite an existing entry + void add(const keyType& k, const string& v, bool overwrite=false); - //- Add a label entry - // optionally overwrite an existing entry - void add(const keyType&, const label l, bool overwrite=false); + //- Add a label entry + // optionally overwrite an existing entry + void add(const keyType& k, const label v, bool overwrite=false); - //- Add a scalar entry - // optionally overwrite an existing entry - void add(const keyType&, const scalar s, bool overwrite=false); + //- Add a scalar entry + // optionally overwrite 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 - void add - ( - const keyType& k, - const dictionary& d, - bool mergeEntry = false - ); + //- Add a dictionary entry + // optionally merge with an existing sub-dictionary + void add + ( + const keyType& k, + const dictionary& d, + bool mergeEntry = false + ); - //- Add a T entry - // optionally overwrite an existing entry - template - void add(const keyType& k, const T& t, bool overwrite=false); + //- Add a T entry + // optionally overwrite an existing entry + template + void add(const keyType& k, const T& v, bool overwrite=false); - //- Assign a new entry, overwrite any existing entry - void set(entry* entryPtr); + //- Assign a new entry, overwrite any existing entry + void set(entry* entryPtr); - //- Assign a new entry, overwrite any existing entry - void set(const entry& e); + //- Assign a new entry, overwrite any existing entry + void set(const entry& e); - //- Assign a dictionary entry, overwrite any existing entry - void set(const keyType& k, const dictionary& d); + //- Assign a dictionary entry, overwrite any existing entry + void set(const keyType& k, const dictionary& v); - //- Assign a T entry, overwrite any existing entry - template - void set(const keyType& k, const T& t); + //- Assign a T entry, overwrite any existing entry + template + void set(const keyType& k, const T& v); - //- Remove an entry specified by keyword - bool remove(const word& Keyword); + //- Remove an entry specified by keyword + bool remove(const word& keyword); - //- Change the keyword for an entry, - // optionally forcing overwrite of an existing entry - bool changeKeyword - ( - const keyType& oldKeyword, - const keyType& newKeyword, - bool forceOverwrite=false - ); + //- Change the keyword for an entry, + // optionally forcing overwrite of an existing entry + bool changeKeyword + ( + const keyType& oldKeyword, + const keyType& newKeyword, + bool forceOverwrite=false + ); - //- Merge entries from the given dictionary. - // Also merge sub-dictionaries as required. - bool merge(const dictionary& dict); + //- Merge entries from the given dictionary. + // Also merge sub-dictionaries as required. + bool merge(const dictionary& dict); - //- Clear the dictionary - void clear(); + //- Clear the dictionary + void clear(); - //- Transfer the contents of the argument and annul the argument. - void transfer(dictionary& dict); + //- Transfer the contents of the argument and annul the argument. + void transfer(dictionary& dict); - //- Transfer contents to the Xfer container - Xfer xfer(); + //- Transfer contents to the Xfer container + Xfer xfer(); - // Read + // Read - //- Read dictionary from Istream - bool read(Istream& is); + //- Read dictionary from Istream + bool read(Istream& is); - //- Read dictionary from Istream, optionally keeping the header - bool read(Istream& is, const bool keepHeader); + //- Read dictionary from Istream, optionally keeping the header + bool read(Istream& is, const bool keepHeader); - // Write + // Write - //- Write sub-dictionary with the keyword as its header - void writeEntry(const keyType& keyword, Ostream& os) const; + //- Write sub-dictionary with the keyword as its header + void writeEntry(const keyType& keyword, Ostream& os) const; - //- Write dictionary entries. - // Optionally with extra new line between entries for - // "top-level" dictionaries - void writeEntries(Ostream& os, const bool extraNewLine=false) const; + //- Write dictionary entries. + // Optionally with extra new line between entries for + // "top-level" dictionaries + void writeEntries(Ostream& os, const bool extraNewLine=false) const; - //- Write dictionary, normally with sub-dictionary formatting - void write(Ostream& os, const bool subDict=true) const; + //- Write dictionary, normally with sub-dictionary formatting + void write(Ostream& os, const bool subDict=true) const; + + + // Searching + + //- Search dictionary for given keyword + // If recursive, search parent dictionaries + // If patternMatch, use regular expressions + // (default search: non-recursive with patterns). + const_searcher csearch + ( + const word& keyword, + bool recursive = false, + bool patternMatch = true + ) const; + + //- Search dictionary for given keyword + // If recursive, search parent dictionaries + // If patternMatch, use regular expressions + // (default search: non-recursive with patterns). + const_searcher search + ( + const word& keyword, + bool recursive = false, + bool patternMatch = true + ) const; + + //- Search dictionary for given keyword + // If recursive, search parent dictionaries + // If patternMatch, use regular expressions + // (default search: non-recursive with patterns). + searcher search + ( + const word& keyword, + bool recursive = false, + bool patternMatch = true + ); + + //- Search using scoping. + // There are two types of scoping available: + // -# dot-scoping, where a '.' is used to delineate the scope + // -# slash-scoping, where a '/' is used to delineate the scope + // + // For dot-scoping, a leading '^' traverses to the top-level + // dictionary, leading dots mean use the parent dictionary and an + // intermediate dot separates a sub-dictionary or sub-entry. + // However, since the use of dots is ambiguous ("a.b.c" could be + // an entry itself or represent a "bc" entry from dictionary "a" etc), + // the heuristic backtracks and attempts successively longer + // top-level entries until a suitable match is found. + // + // For slash-scoping, semantics similar to directory structures are + // used. A leading '/' traverses to the top-level dictionary, + // a single leading or intermediate '.' references the current + // dictionary level. A '..' pair references the parent dictionary. + // Any doubled slashes are silently ignored. + // Since a slash is not a valid keyword character, there is no + // ambiguity between separator and content. + const_searcher csearchScoped + ( + const word& keyword, + bool recursive, + bool patternMatch + ) const; + + //- Search using dot or slash scoping. + const_searcher searchScoped + ( + const word& keyword, + bool recursive, + bool patternMatch + ) const; + + //- Search using dot or slash scoping. + searcher searchScoped + ( + const word& keyword, + bool recursive, + bool patternMatch + ); + + //- Locate a sub-dictionary using slash-scoping + // \return nullptr if the dictionary path does not exist + const dictionary* cfindScopedDictPtr(const fileName& dictPath) const; + + //- Locate a sub-dictionary using slash-scoping + // \return nullptr if the dictionary path does not exist + const dictionary* findScopedDictPtr(const fileName& dictPath) const; + + //- Locate a sub-dictionary using slash-scoping + // \return nullptr if the dictionary path does not exist + dictionary* findScopedDictPtr(const fileName& dictPath); + + //- Locate existing or create sub-dictionary using slash-scoping + // \return nullptr if the dictionary path could not be created + dictionary* makeScopedDictPtr(const fileName& dictPath); // Member Operators - //- Find and return entry + //- Find and return an entry data stream (identical to #lookup method). + // Default search: non-recursive with patterns. + // + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions ITstream& operator[](const word& keyword) const; + //- Copy assignment void operator=(const dictionary& rhs); //- Include entries from the given dictionary. diff --git a/src/OpenFOAM/db/dictionary/dictionaryIO.C b/src/OpenFOAM/db/dictionary/dictionaryIO.C index ddc505c661..9c1e36c1b5 100644 --- a/src/OpenFOAM/db/dictionary/dictionaryIO.C +++ b/src/OpenFOAM/db/dictionary/dictionaryIO.C @@ -128,30 +128,6 @@ bool Foam::dictionary::read(Istream& is) } -bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry) -{ - const word varName = keyword.substr(1); - - // Lookup the variable name in the given dictionary - const entry* ePtr = lookupEntryPtr(varName, true, true); - - // If defined insert its entries into this dictionary - if (ePtr != nullptr) - { - const dictionary& addDict = ePtr->dict(); - - forAllConstIter(parent_type, addDict, iter) - { - add(iter(), mergeEntry); - } - - return true; - } - - return false; -} - - // * * * * * * * * * * * * * * Istream Operator * * * * * * * * * * * * * * // Foam::Istream& Foam::operator>>(Istream& is, dictionary& dict) diff --git a/src/OpenFOAM/db/dictionary/dictionarySearch.C b/src/OpenFOAM/db/dictionary/dictionarySearch.C new file mode 100644 index 0000000000..93c5bcb884 --- /dev/null +++ b/src/OpenFOAM/db/dictionary/dictionarySearch.C @@ -0,0 +1,719 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 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 3 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, see . + +\*---------------------------------------------------------------------------*/ + +#include "dictionary.H" +#include "dictionaryEntry.H" +#include "stringOps.H" + +/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */ + +namespace Foam +{ + // file-scope + //- Walk lists of patterns and regexps for an exact match + // or regular expression match + template + static bool findInPatterns + ( + const bool patternMatch, + const word& keyword, + WcIterator& wcIter, + ReIterator& reIter + ) + { + while (wcIter.found()) + { + if + ( + patternMatch + ? reIter()->match(keyword) + : wcIter()->keyword() == keyword + ) + { + return true; + } + + ++reIter; + ++wcIter; + } + + return false; + } +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::dictionary::const_searcher Foam::dictionary::csearchDotScoped +( + const word& keyword, + bool recursive, + bool patternMatch +) const +{ + std::string::size_type scopePos = keyword.find('.'); + + if (scopePos == string::npos) + { + // Normal, non-scoped search + return csearch(keyword, recursive, patternMatch); + } + + if (scopePos == 0) + { + // Starting with a '.' -> go up for every further '.' found + ++scopePos; + + const dictionary* dictPtr = this; + for + ( + string::const_iterator it = keyword.begin()+1; + it != keyword.end() && *it == '.'; + ++scopePos, ++it + ) + { + // Go to parent + if (&dictPtr->parent_ != &dictionary::null) + { + dictPtr = &dictPtr->parent_; + } + else + { + FatalIOErrorInFunction + ( + *this + ) << "No parent of current dictionary when searching for " + << keyword.substr(1) + << exit(FatalIOError); + + return nullptr; + } + } + + return dictPtr->csearchDotScoped + ( + keyword.substr(scopePos), + false, + patternMatch + ); + } + + // The first word + const_searcher finder = csearchDotScoped + ( + keyword.substr(0, scopePos), + false, + patternMatch + ); + + // Fall back to finding key with '.' so e.g. if keyword is + // a.b.c.d it would try + // a.b, a.b.c, a.b.c.d + + if (!finder.found()) + { + while (!finder.isDict()) + { + scopePos = keyword.find('.', scopePos+1); + + // Local entry: + finder = csearch(keyword.substr(0, scopePos), false, patternMatch); + + if (scopePos == string::npos) + { + // Parsed the whole word. Return entry or null. + return finder; + } + } + } + + if (finder.isDict()) + { + return finder.dict().csearchDotScoped + ( + keyword.substr(scopePos), + false, + patternMatch + ); + } + + return finder; +} + + +Foam::dictionary::const_searcher Foam::dictionary::csearchSlashScoped +( + const word& keyword, + bool patternMatch +) const +{ + const dictionary* dictPtr = this; + + const auto slash = keyword.find('/'); + + if (slash == string::npos) + { + // No slashes: + // Can use normal (non-scoped) search at the current dictionary level + return csearch(keyword, false, patternMatch); + } + else if (slash == 0) + { + // (isAbsolute) + // Ascend to top-level + while (&dictPtr->parent_ != &dictionary::null) + { + dictPtr = &dictPtr->parent_; + } + } + + // Split on '/' + auto cmpts = stringOps::split(keyword, '/'); + auto remaining = cmpts.size(); + + for (const auto& cmpt : cmpts) + { + --remaining; // Decrement now so we can check (remaining == 0) + + if (cmpt == ".") + { + // "." - ignore + } + else if (cmpt == "..") + { + // ".." - go to parent + if (&dictPtr->parent_ != &dictionary::null) + { + dictPtr = &dictPtr->parent_; + } + else + { + FatalIOErrorInFunction + ( + *dictPtr + ) << "No parent of current dictionary when searching for " + << keyword << " at " << cmpt + << exit(FatalIOError); + break; + } + } + else + { + // Find entry + const word key = word::validate(cmpt); + + auto finder = dictPtr->csearch(key, false, patternMatch); + + if (finder.found()) + { + if (remaining) + { + // Intermediate must be a dictionary + if (finder.isDict()) + { + dictPtr = finder.dictPtr(); + } + else + { + return const_searcher(dictPtr); + } + } + else + { + // Last entry - done + return finder; + } + } + else + { + break; + } + } + } + + // Failed at this dictionary level + return const_searcher(dictPtr); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::dictionary::const_searcher Foam::dictionary::csearch +( + const word& keyword, + bool recursive, + bool patternMatch +) const +{ + const_searcher finder(this); + + auto iter = hashedEntries_.cfind(keyword); + + if (iter.found()) + { + finder.set(iter.object()); + return finder; + } + + if (patternMatch && patterns_.size()) + { + pattern_const_iterator wcLink = patterns_.begin(); + regexp_const_iterator reLink = regexps_.begin(); + + // Find in patterns using regular expressions only + if (findInPatterns(patternMatch, keyword, wcLink, reLink)) + { + finder.set(*wcLink); + return finder; + } + } + + if (recursive && &parent_ != &dictionary::null) + { + return parent_.csearch + ( + keyword, + recursive, + patternMatch + ); + } + + return finder; +} + + +Foam::dictionary::const_searcher Foam::dictionary::search +( + const word& keyword, + bool recursive, + bool patternMatch +) const +{ + return csearch(keyword, recursive, patternMatch); +} + + +Foam::dictionary::searcher Foam::dictionary::search +( + const word& keyword, + bool recursive, + bool patternMatch +) +{ + const_searcher finder = csearch(keyword, recursive, patternMatch); + + return static_cast(finder); +} + + +Foam::dictionary::const_searcher Foam::dictionary::csearchScoped +( + const word& keyword, + bool recursive, + bool patternMatch +) const +{ + if (keyword.find('/') != string::npos) + { + return csearchSlashScoped(keyword, patternMatch); + } + + if (keyword[0] == ':' || keyword[0] == '^') + { + // Ascend to top-level + const dictionary* dictPtr = this; + while (&dictPtr->parent_ != &dictionary::null) + { + dictPtr = &dictPtr->parent_; + } + + return dictPtr->csearchDotScoped + ( + keyword.substr(1), + false, + patternMatch + ); + } + + return csearchDotScoped(keyword, recursive, patternMatch); +} + + +Foam::dictionary::const_searcher Foam::dictionary::searchScoped +( + const word& keyword, + bool recursive, + bool patternMatch +) const +{ + return csearchScoped(keyword, recursive, patternMatch); +} + + +Foam::dictionary::searcher Foam::dictionary::searchScoped +( + const word& keyword, + bool recursive, + bool patternMatch +) +{ + const_searcher finder = csearchScoped(keyword, recursive, patternMatch); + + return static_cast(finder); +} + + +const Foam::dictionary* Foam::dictionary::cfindScopedDictPtr +( + const fileName& dictPath +) const +{ + // Or warning + if (dictPath.empty()) + { + return nullptr; + } + + const dictionary* dictPtr = this; + if (fileName::isAbsolute(dictPath)) + { + // Ascend to top-level + while (&dictPtr->parent_ != &dictionary::null) + { + dictPtr = &dictPtr->parent_; + } + } + + fileName path = dictPath.clean(); + const wordList cmpts = path.components(); + + for (const word& cmpt : cmpts) + { + if (cmpt == ".") + { + // "." - ignore + } + else if (cmpt == "..") + { + // ".." - go to parent + if (&dictPtr->parent_ != &dictionary::null) + { + dictPtr = &dictPtr->parent_; + } + else + { + FatalIOErrorInFunction + ( + *dictPtr + ) << "No parent for dictionary while searching " + << path + << exit(FatalIOError); + + return nullptr; + } + } + else + { + // Non-recursive, no patternMatch + // -> can do direct lookup, without csearch(cmpt, false, false); + + auto iter = dictPtr->hashedEntries_.cfind(cmpt); + + if (iter.found()) + { + const entry *eptr = iter.object(); + + if (eptr->isDict()) + { + dictPtr = eptr->dictPtr(); + } + else + { + FatalIOErrorInFunction + ( + *dictPtr + ) << "Found entry '" << cmpt + << "' but not a dictionary, while searching scoped" + << nl + << " " << path + << exit(FatalIOError); + + return nullptr; + } + } + else + { + return nullptr; + } + } + } + + return dictPtr; +} + + +const Foam::dictionary* Foam::dictionary::findScopedDictPtr +( + const fileName& dictPath +) const +{ + return cfindScopedDictPtr(dictPath); +} + + +Foam::dictionary* Foam::dictionary::findScopedDictPtr +( + const fileName& dictPath +) +{ + const dictionary* ptr = cfindScopedDictPtr(dictPath); + return const_cast(ptr); +} + + +Foam::dictionary* Foam::dictionary::makeScopedDictPtr(const fileName& dictPath) +{ + // Or warning + if (dictPath.empty()) + { + return nullptr; + } + + dictionary* dictPtr = this; + if (fileName::isAbsolute(dictPath)) + { + // Ascend to top-level + while (&dictPtr->parent_ != &dictionary::null) + { + dictPtr = const_cast(&dictPtr->parent_); + } + } + + // Work on a copy, without any assumptions + std::string path = dictPath; + fileName::clean(path); + + // Split on '/' + auto cmpts = stringOps::split(path, '/'); + + for (const auto& cmpt : cmpts) + { + if (cmpt == ".") + { + // "." - ignore + } + else if (cmpt == "..") + { + // ".." - go to parent + if (&dictPtr->parent_ != &dictionary::null) + { + dictPtr = const_cast(&dictPtr->parent_); + } + else + { + FatalIOErrorInFunction + ( + *dictPtr + ) << "No parent for dictionary while searching " + << path + << exit(FatalIOError); + + return nullptr; + } + } + else + { + // Non-recursive, no patternMatch + // -> can do direct lookup, without csearch(cmptName, false, false); + const word cmptName(cmpt.str(), false); + + auto iter = dictPtr->hashedEntries_.find(cmptName); + + if (iter.found()) + { + entry *eptr = iter.object(); + + if (eptr->isDict()) + { + dictPtr = eptr->dictPtr(); + } + else + { + FatalIOErrorInFunction + ( + *dictPtr + ) << "Cannot create sub-dictionary entry '" << cmptName + << "' - a non-dictionary entry is in the way" + << nl << "Encountered in scope" << nl + << " " << path + << exit(FatalIOError); + + return nullptr; + } + } + else + { + dictionaryEntry *eptr = + new dictionaryEntry(cmptName, *dictPtr, dictionary()); + + // Add *without* merging, since we just checked that the entry + // doesn't exist and to ensure that the pointer remains valid. + + if (dictPtr->add(eptr, false)) // NO merge + { + dictPtr = eptr; + } + else + { + return nullptr; + } + } + } + } + + return dictPtr; +} + + +bool Foam::dictionary::remove(const word& keyword) +{ + auto iter = hashedEntries_.find(keyword); + + if (iter.found()) + { + // Delete from patterns + pattern_iterator wcLink = patterns_.begin(); + regexp_iterator reLink = regexps_.begin(); + + // Find in pattern using exact match only + if (findInPatterns(false, keyword, wcLink, reLink)) + { + patterns_.remove(wcLink); + regexps_.remove(reLink); + } + + parent_type::remove(iter()); + delete iter(); + hashedEntries_.erase(iter); + + return true; + } + else + { + return false; + } +} + + +bool Foam::dictionary::changeKeyword +( + const keyType& oldKeyword, + const keyType& newKeyword, + bool forceOverwrite +) +{ + // No change + if (oldKeyword == newKeyword) + { + return false; + } + + // Check that oldKeyword exists and can be changed + auto iter = hashedEntries_.find(oldKeyword); + + if (!iter.found()) + { + return false; + } + + if (iter()->keyword().isPattern()) + { + FatalIOErrorInFunction + ( + *this + ) << "Old keyword "<< oldKeyword + << " is a pattern." + << "Pattern replacement not yet implemented." + << exit(FatalIOError); + } + + + auto iter2 = hashedEntries_.find(newKeyword); + + // newKeyword already exists + if (iter2.found()) + { + if (forceOverwrite) + { + if (iter2()->keyword().isPattern()) + { + // Delete from patterns + pattern_iterator wcLink = patterns_.begin(); + regexp_iterator reLink = regexps_.begin(); + + // Find in patterns using exact match only + if (findInPatterns(false, iter2()->keyword(), wcLink, reLink)) + { + patterns_.remove(wcLink); + regexps_.remove(reLink); + } + } + + parent_type::replace(iter2(), iter()); + delete iter2(); + hashedEntries_.erase(iter2); + } + else + { + IOWarningInFunction + ( + *this + ) << "cannot rename keyword "<< oldKeyword + << " to existing keyword " << newKeyword + << " in dictionary " << name() << endl; + return false; + } + } + + // Change name and HashTable, but leave DL-List untouched + iter()->keyword() = newKeyword; + iter()->name() = name() + '.' + newKeyword; + hashedEntries_.erase(oldKeyword); + hashedEntries_.insert(newKeyword, iter()); + + if (newKeyword.isPattern()) + { + patterns_.insert(iter()); + regexps_.insert + ( + autoPtr(new regExp(newKeyword)) + ); + } + + return true; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C index 1e46e5da33..d0446b6770 100644 --- a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C +++ b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C @@ -43,9 +43,9 @@ T Foam::dictionary::lookupType bool patternMatch ) const { - const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch); + auto finder = csearch(keyword, recursive, patternMatch); - if (entryPtr == nullptr) + if (!finder.found()) { FatalIOErrorInFunction ( @@ -55,7 +55,7 @@ T Foam::dictionary::lookupType << exit(FatalIOError); } - return pTraits(entryPtr->stream()); + return pTraits(finder.ptr()->stream()); } @@ -68,11 +68,11 @@ T Foam::dictionary::lookupOrDefault bool patternMatch ) const { - const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch); + auto finder = csearch(keyword, recursive, patternMatch); - if (entryPtr) + if (finder.found()) { - return pTraits(entryPtr->stream()); + return pTraits(finder.ptr()->stream()); } else { @@ -98,11 +98,11 @@ T Foam::dictionary::lookupOrAddDefault bool patternMatch ) { - const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch); + auto finder = csearch(keyword, recursive, patternMatch); - if (entryPtr) + if (finder.found()) { - return pTraits(entryPtr->stream()); + return pTraits(finder.ptr()->stream()); } else { @@ -129,11 +129,11 @@ bool Foam::dictionary::readIfPresent bool patternMatch ) const { - const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch); + auto finder = csearch(keyword, recursive, patternMatch); - if (entryPtr) + if (finder.found()) { - entryPtr->stream() >> val; + finder.ptr()->stream() >> val; return true; } else @@ -152,16 +152,16 @@ bool Foam::dictionary::readIfPresent template -void Foam::dictionary::add(const keyType& k, const T& t, bool overwrite) +void Foam::dictionary::add(const keyType& k, const T& v, bool overwrite) { - add(new primitiveEntry(k, t), overwrite); + add(new primitiveEntry(k, v), overwrite); } template -void Foam::dictionary::set(const keyType& k, const T& t) +void Foam::dictionary::set(const keyType& k, const T& v) { - set(new primitiveEntry(k, t)); + set(new primitiveEntry(k, v)); } diff --git a/src/OpenFOAM/db/dictionary/entry/entryIO.C b/src/OpenFOAM/db/dictionary/entry/entryIO.C index b8a75380ab..f6879570d2 100644 --- a/src/OpenFOAM/db/dictionary/entry/entryIO.C +++ b/src/OpenFOAM/db/dictionary/entry/entryIO.C @@ -224,17 +224,12 @@ bool Foam::entry::New const word varName = keyword.substr(1); // Lookup the variable name in the given dictionary - const entry* ePtr = parentDict.lookupScopedEntryPtr - ( - varName, - true, - true - ); + const auto finder = parentDict.csearchScoped(varName, true, true); - if (ePtr) + if (finder.found()) { // Read as primitiveEntry - const keyType newKeyword(ePtr->stream()); + const keyType newKeyword(finder.ptr()->stream()); return parentDict.add ( @@ -285,14 +280,9 @@ bool Foam::entry::New bool mergeEntry = false; // See (using exact match) if entry already present - entry* existingPtr = parentDict.lookupEntryPtr - ( - keyword, - false, - false - ); + auto finder = parentDict.search(keyword, false, false); - if (existingPtr) + if (finder.found()) { if (mode == inputMode::MERGE) { @@ -301,9 +291,9 @@ bool Foam::entry::New else if (mode == inputMode::OVERWRITE) { // Clear existing dictionary so merge acts like overwrite - if (existingPtr->isDict()) + if (finder.isDict()) { - existingPtr->dict().clear(); + finder.dict().clear(); } mergeEntry = true; } From c880d7dc7d11b25370647542ebeed8cf891535fe Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Thu, 13 Jul 2017 09:46:07 +0200 Subject: [PATCH 002/126] ENH: support '/' separators in foamDictionary - convenience -diffEtc option that behaves like -diff, but invokes foamEtcFile searching STYLE: modernize code. --- .../foamDictionary/foamDictionary.C | 373 ++++++++++-------- 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, 356 insertions(+), 297 deletions(-) diff --git a/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C b/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C index e4c3186261..57210c5a57 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 \ Selects an entry - - \par -keywords \ + - \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 \ + 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(':')); - word entry(entryNames[0]); - for (label i = 1; i < entryNames.size(); i++) + entryName.resize(0); + + 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 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 - ( - 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("", 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 (refEntry.isDict()) { - if (iter().isDict()) - { - remove - ( - const_cast(entPtr->dict()), - iter().dict() - ); + removeDict(finder.dict(), refEntry.dict()); - // Check if dictionary is empty - if (!entPtr->dict().size()) - { - dict.remove(iter().keyword()); - } - } - } - else if (!iter().isDict()) - { - if (*entPtr == iter()) - { - dict.remove(iter().keyword()); - } + // 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 dictFile(new IFstream(dictFileName)); if (!dictFile().good()) @@ -341,28 +363,55 @@ int main(int argc, char *argv[]) } - // Second dictionary for -diff - dictionary diffDict; - fileName diffFileName; - if (args.optionReadIfPresent("diff", diffFileName)) - { - autoPtr diffFile(new IFstream(diffFileName)); - if (!diffFile().good()) - { - FatalErrorInFunction - << "Cannot open file " << diffFileName - << exit(FatalError, 1); - } + // Has "diff" or "diffEtc" + bool optDiff = false; - // Read but preserve headers - diffDict.read(diffFile(), true); + // Reference dictionary for -diff / -diffEtc + dictionary diffDict; + { + fileName diffFileName; + if (args.optionReadIfPresent("diff", diffFileName)) + { + 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); + } + + 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 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 dAk(dictAndKeyword(scopedName)); + // Dictionary name and keyword + const dictAndKeyword dAk(scopedName); - const dictionary& d(lookupScopedDict(dict, dAk.first())); - const_cast(d).remove(dAk.second()); + // The context for the action + const dictionary& d(lookupScopedDict(dict, dAk.dict())); + + const_cast(d).remove(dAk.key()); changed = true; } else { // Optionally remove a second dictionary - if (args.optionFound("diff")) + if (optDiff) { - Pair 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(d).remove(dAk.second()); + const_cast(d1).remove(dAk.key()); } - else if (ePtr->isDict() && e2Ptr->isDict()) + else if (e1Ptr->isDict() && e2Ptr->isDict()) { - remove + removeDict ( - const_cast(ePtr->dict()), + const_cast(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 + } + else if (args.optionFound("value")) + { + if (finder.isDict()) { - if (args.optionFound("value")) + Info<< finder.dict(); + } + else if (finder.ref().isStream()) + { + 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 46cee88d67..a39fbf4862 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 783c643656..7b3baa055a 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 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 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 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 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 93c5bcb884..cc711af70a 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 d0446b6770..9e887c08f6 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(finder.ptr()->stream()); } - else - { - if (writeOptionalEntries) - { - IOInfoInFunction(*this) - << "Optional entry '" << keyword << "' is not present," - << " returning the default value '" << deflt << "'" - << endl; - } - return deflt; + if (writeOptionalEntries) + { + 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(finder.ptr()->stream()); } - else - { - 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; + 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; } @@ -136,18 +132,16 @@ bool Foam::dictionary::readIfPresent finder.ptr()->stream() >> val; return true; } - else - { - if (writeOptionalEntries) - { - IOInfoInFunction(*this) - << "Optional entry '" << keyword << "' is not present," - << " the default value '" << val << "' will be used." - << endl; - } - return false; + if (writeOptionalEntries) + { + IOInfoInFunction(*this) + << "Optional entry '" << keyword << "' is not present," + << " the default value '" << val << "' will be used." + << endl; } + + return false; } From 2fdc6b161adfe4d537b751f8e398a6c57a72b268 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Thu, 20 Jul 2017 10:58:05 +0200 Subject: [PATCH 003/126] ENH: support full-scoping for keywords as lvalue (issue #429) - patterns only supported for the final element. To create an element as a pattern instead of a word, an embedded string quote (single or double) is used for that element. Any of the following examples: "/top/sub/dict/'(p|U).*" 100; "/top/sub/dict/'(p|U).*'" 100; "/top/sub/dict/\"(p|U).*" 100; "/top/sub/dict/\"(p|U).*\"" 100; are equivalent to the longer form: top { sub { dict { "(p|U).*" 100; } } } It is not currently possible to auto-vivify intermediate dictionaries with patterns. NOK "/nonexistent.*/value" 100; OK "/existing.*/value" 100; - full scoping also works for the #remove directive #remove "/dict1/subdict2/entry1" --- applications/test/dictionary/testSubkeyword | 68 ++++++++- src/OpenFOAM/db/dictionary/entry/entryIO.C | 130 +++++++++++++++--- .../functionEntries/removeEntry/removeEntry.C | 34 +++-- .../functionEntries/removeEntry/removeEntry.H | 17 ++- 4 files changed, 212 insertions(+), 37 deletions(-) diff --git a/applications/test/dictionary/testSubkeyword b/applications/test/dictionary/testSubkeyword index f8ee148501..3465f0623e 100644 --- a/applications/test/dictionary/testSubkeyword +++ b/applications/test/dictionary/testSubkeyword @@ -17,6 +17,8 @@ FoamFile // #inputMode overwrite key1 val1; +val1 val1; +val2 val2; subdict { @@ -35,19 +37,75 @@ update key3 val3; key2b ${..key2}; key3b $^key1; + key100 100; + key200 200; + key300 300; + key400 400; } } +// expands update into top-level $update -// Can a leading '^' or ':' as anchor for scoping -key3 $^subdict.key1; + +_cleanup +{ + #remove "/subdict/key300" + "/subdict/key400" 400000; + + // Self-destruct not possible + // #remove "/_cleanup" +} + +#remove "/_cleanup" + +// Can use a leading '^' or ':' as anchor for scoping, but slashes are clearer +key3dot ${^subdict.key1}; +key3slash ${/subdict/key1}; key3 ${^update.subdict.key3}; key4 ${:update.subdict...subdict.key1}; -// This is currently not working -#remove update.key1 -// #remove update +// This will not work, but globs would be interesting: +#remove "/update/subdict/key*" + +// This is okay, uses a regexp directly +#remove "val.*" + +#remove "/update/subdict/key100" + +"/subdict/key2" overridden; + + +active +{ + type turbulentIntensityKineticEnergyInlet; + intensity 0.1; + value 100; +} + +// Some more with scoping + +"/active/value(pwd)" 200; +"/active/'(pwd|foo)'" 200; // Can use single or double quotes +"/active/intensity" 0.05; + +// Auto-vivify intermediate dictionaries + +"/active/subdict/type" anotherType; +"/active/subdict/value/type" anotherType; + +// This is an error - cannot change type of intermediate dictionaries! +// "active/value/type/of/things" newType; + +"/active/subdict/value" change; + +"/active/subdict/value" { entry1 value1; entry2 value2; } + +// Handle remove as per changeDictionary? TBD +// Removal: +// "~/active/subdict/value" + +// "~active" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/db/dictionary/entry/entryIO.C b/src/OpenFOAM/db/dictionary/entry/entryIO.C index f6879570d2..3e549c9faf 100644 --- a/src/OpenFOAM/db/dictionary/entry/entryIO.C +++ b/src/OpenFOAM/db/dictionary/entry/entryIO.C @@ -262,7 +262,7 @@ bool Foam::entry::New } else { - // Normal entry + // Normal or scoped entry token nextToken(is); is.putBack(nextToken); @@ -279,11 +279,25 @@ bool Foam::entry::New // How to manage duplicate entries bool mergeEntry = false; + const bool scoped = + ( + !disableFunctionEntries + && (keyword.find('/') != string::npos) + ); + // See (using exact match) if entry already present - auto finder = parentDict.search(keyword, false, false); + auto finder = + ( + scoped + ? parentDict.searchScoped(keyword, false, false) + : parentDict.search(keyword, false, false) + ); if (finder.found()) { + // Use keyword from the found entry (ie, eliminate scoping chars) + const keyType key = finder.ref().keyword(); + if (mode == inputMode::MERGE) { mergeEntry = true; @@ -306,11 +320,11 @@ bool Foam::entry::New if (nextToken == token::BEGIN_BLOCK) { - dictionaryEntry dummy("dummy", parentDict, is); + dictionaryEntry dummy("dummy", finder.context(), is); } else { - primitiveEntry dummy("dummy", parentDict, is); + primitiveEntry dummy("dummy", finder.context(), is); } entry::disableFunctionEntries = oldFlag; @@ -319,29 +333,109 @@ bool Foam::entry::New else if (mode == inputMode::ERROR) { FatalIOErrorInFunction(is) - << "duplicate entry: " << keyword + << "duplicate entry: " << key << exit(FatalIOError); return false; } + + // Merge/overwrite data entry + + if (nextToken == token::BEGIN_BLOCK) + { + return finder.context().add + ( + new dictionaryEntry(key, finder.context(), is), + mergeEntry + ); + } + else + { + return finder.context().add + ( + new primitiveEntry(key, finder.context(), is), + mergeEntry + ); + } } - - - if (nextToken == token::BEGIN_BLOCK) + else if (scoped) { - return parentDict.add - ( - new dictionaryEntry(keyword, parentDict, is), - mergeEntry - ); + // A slash-scoped entry - did not previously exist + + string fullPath(keyword); + fileName::clean(fullPath); + + // Get or create the dictionary-path. + // fileName::path == dictionary-path + dictionary* subDictPtr = + parentDict.makeScopedDictPtr + ( + fileName::path(fullPath) + ); + + if (subDictPtr) + { + // fileName::name == keyword-name + string keyName = fileName::name(fullPath); + keyType key; + + // Patterns allowed for the final element. + // - use if key name begins with a (single|double) quote + + if (keyName.find_first_of("\"'") == 0) + { + // Begins with a quote - treat as pattern + key = keyType(string::validate(keyName), true); + } + else + { + // Treat as a word + key = word::validate(keyName, false); + } + + if (nextToken == token::BEGIN_BLOCK) + { + return subDictPtr->add + ( + new dictionaryEntry(key, *subDictPtr, is), + mergeEntry + ); + } + else + { + return subDictPtr->add + ( + new primitiveEntry(key, *subDictPtr, is), + mergeEntry + ); + } + } + else + { + // Some error finding/creating intermediate dictionaries + return false; + } } else { - return parentDict.add - ( - new primitiveEntry(keyword, parentDict, is), - mergeEntry - ); + // A non-scoped entry - did not previously exist + + if (nextToken == token::BEGIN_BLOCK) + { + return parentDict.add + ( + new dictionaryEntry(keyword, parentDict, is), + mergeEntry + ); + } + else + { + return parentDict.add + ( + new primitiveEntry(keyword, parentDict, is), + mergeEntry + ); + } } } } diff --git a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C index a0c413edd8..ebe2baf216 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -26,7 +26,6 @@ License #include "removeEntry.H" #include "dictionary.H" #include "stringListOps.H" -#include "StringStream.H" #include "addToMemberFunctionSelectionTable.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -55,17 +54,36 @@ bool Foam::functionEntries::removeEntry::execute Istream& is ) { - wordList dictKeys = parentDict.toc(); - wordReList patterns = readList(is); + const List patterns = readList(is); - labelList indices = findStrings(patterns, dictKeys); - - forAll(indices, indexI) + for (const keyType& key : patterns) { - parentDict.remove(dictKeys[indices[indexI]]); + if (key.find('/') != string::npos || !key.isPattern()) + { + // Remove scoped keyword, or keyword in the local scope + dictionary::searcher finder = + parentDict.searchScoped(key, false, false); + + if (finder.found()) + { + finder.context().remove(finder.ptr()->keyword()); + } + } + else + { + // Remove by pattern + const wordList dictKeys = parentDict.toc(); + const labelList indices = findStrings(regExp(key), dictKeys); + + for (const auto idx : indices) + { + parentDict.remove(dictKeys[idx]); + } + } } return true; } + // ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.H index 5e8fbdd836..6cdb5441a5 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,17 +27,22 @@ Class Description Remove a dictionary entry. - The \c \#remove directive takes a list or a single wordRe. + The \c \#remove directive takes a list or a single keyType. For example, \verbatim #remove entry0 #remove ( entry1 entry2 entry3 otherEntry ) #remove "entry[1-3]" #remove ( "entry[1-3]" otherEntry ) + #remove ^dict1.subdict2.entry2 + #remove "/dict1/subdict2/entry1" \endverbatim - The removal only occurs in the current context. - Removing sub-entries or parent entries is not supported. +Note + Unless otherwise scoped, the removal occurs in the current context. + To remove from other scopes, a dot-scoped or slash-scoped syntax is + required. The slash-scoped syntax must be quoted to ensure that it + is properly parsed. SourceFiles removeEntry.C @@ -57,7 +62,7 @@ namespace functionEntries { /*---------------------------------------------------------------------------*\ - Class removeEntry Declaration + Class removeEntry Declaration \*---------------------------------------------------------------------------*/ class removeEntry @@ -66,7 +71,7 @@ class removeEntry { public: - //- Remove entries from the current sub-dict context + //- Remove single or multiple entries. Local or scoped entries. static bool execute(dictionary& parentDict, Istream& is); }; From 4e48beffd4add6eb60f745de95bf7e438e3157d0 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Sat, 29 Jul 2017 17:44:22 +0200 Subject: [PATCH 004/126] ENH: support "one-shot" changes to the dictionary inputMode (issue #429) - Instead of relying on #inputMode to effect a global change it is now possible (and recommended) to a temporary change in the inputMode for the following entry. #default : provide default value if entry is not already defined #overwrite : silently remove a previously existing entry #warn : warn about duplicate entries #error : error if any duplicate entries occur #merge : merge sub-dictionaries when possible (the default mode) This is generally less cumbersome than the switching the global inputMode. For example to provide a set of fallback values. #includeIfPresent "user-files" ... #default value uniform 10; vs. #includeIfPresent "user-files" #inputMode protect ... value uniform 10; #inputMode merge // _Assuming_ we actually had this before These directives can also be used to suppress the normal dictionary merge semantics: #overwrite dict { entry val; ... } --- applications/test/dictionary/testDict | 19 ++-- etc/caseDicts/foamyHexMeshDict | 2 - .../functionEntries/inputMode/inputMode.C | 95 +++++++++++++++++++ .../functionEntries/inputMode/inputMode.H | 80 ++++++++++++++++ .../system/solverControls | 2 - .../system/solverControls.0 | 2 - .../system/solverControls.20 | 2 - .../system/solverControls.5 | 2 - .../system/solverControls.60 | 2 - .../steady/0.orig/include/initialConditions | 2 - .../0.orig/include/initialConditions | 1 - .../0.orig/include/initialConditions | 1 - 12 files changed, 185 insertions(+), 25 deletions(-) diff --git a/applications/test/dictionary/testDict b/applications/test/dictionary/testDict index 736f426305..a933c543e3 100644 --- a/applications/test/dictionary/testDict +++ b/applications/test/dictionary/testDict @@ -13,18 +13,19 @@ FoamFile object testDict; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -#inputMode merge + #includeIfPresent "someUnknownFile" #includeIfPresent "$FOAM_CASE/someUnknownFile" #includeIfPresent "$FOAM_CASE/someUnknownFile-$FOAM_CASENAME" internalField uniform 1; -// use 'protect' to supply defaults -#inputMode protect -internalField uniform 10; -dimensions [ 0 2 -2 0 0 0 0 ]; -#inputMode merge +// supply defaults +#default internalField uniform 10; +#default dimensions [ 1 2 -2 0 0 0 0 ]; +#overwrite dimensions [ 0 2 -2 0 0 0 0 ]; +// #warn dimensions [ 0 2 -2 0 0 0 0 ]; +// #error dimensions [ 0 2 -2 0 0 0 0 ]; active { @@ -86,12 +87,12 @@ boundaryField #remove inactive inlet_7 { ${${varType}}} // Test indirection/recursive expansion - #inputMode overwrite inlet_8 { $active } + + #overwrite inlet_8 { type none; } } -// NB: the inputMode has a global scope -#inputMode merge + #include "testDict2" foo diff --git a/etc/caseDicts/foamyHexMeshDict b/etc/caseDicts/foamyHexMeshDict index 088c1a0b98..ee8abb7e15 100644 --- a/etc/caseDicts/foamyHexMeshDict +++ b/etc/caseDicts/foamyHexMeshDict @@ -14,8 +14,6 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -#inputMode merge; - surfaceConformation { pointPairDistanceCoeff 0.1; diff --git a/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.C b/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.C index bdd92de36e..160d5ec87d 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.C @@ -41,6 +41,51 @@ namespace functionEntries dictionaryIstream, inputMode ); + + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + inputModeDefault, + execute, + dictionaryIstream, + default + ); + + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + inputModeMerge, + execute, + dictionaryIstream, + merge + ); + + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + inputModeOverwrite, + execute, + dictionaryIstream, + overwrite + ); + + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + inputModeWarn, + execute, + dictionaryIstream, + warn + ); + + addNamedToMemberFunctionSelectionTable + ( + functionEntry, + inputModeError, + execute, + dictionaryIstream, + error + ); } } @@ -90,4 +135,54 @@ bool Foam::functionEntries::inputMode::execute } +bool Foam::functionEntries::inputModeDefault::execute +( + dictionary& parentDict, + Istream& is +) +{ + return entry::New(parentDict, is, entry::inputMode::PROTECT); +} + + +bool Foam::functionEntries::inputModeMerge::execute +( + dictionary& parentDict, + Istream& is +) +{ + return entry::New(parentDict, is, entry::inputMode::MERGE); +} + + +bool Foam::functionEntries::inputModeOverwrite::execute +( + dictionary& parentDict, + Istream& is +) +{ + return entry::New(parentDict, is, entry::inputMode::OVERWRITE); +} + + +bool Foam::functionEntries::inputModeWarn::execute +( + dictionary& parentDict, + Istream& is +) +{ + return entry::New(parentDict, is, entry::inputMode::WARN); +} + + +bool Foam::functionEntries::inputModeError::execute +( + dictionary& parentDict, + Istream& is +) +{ + return entry::New(parentDict, is, entry::inputMode::ERROR); +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.H b/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.H index c670d9230d..91f0d6362b 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/inputMode/inputMode.H @@ -84,6 +84,86 @@ public: }; +/*---------------------------------------------------------------------------*\ + Class inputModeDefault Declaration +\*---------------------------------------------------------------------------*/ + +//- Temporarily change inputMode to %protect for the following entry +class inputModeDefault +: + public functionEntry +{ +public: + + //- Execute in a sub-dict context + static bool execute(dictionary& parentDict, Istream& is); +}; + + +/*---------------------------------------------------------------------------*\ + Class inputModeMerge Declaration +\*---------------------------------------------------------------------------*/ + +//- Temporarily change inputMode to %merge for the following entry +class inputModeMerge +: + public functionEntry +{ +public: + + //- Execute in a sub-dict context + static bool execute(dictionary& parentDict, Istream& is); +}; + + +/*---------------------------------------------------------------------------*\ + Class inputModeOverwrite Declaration +\*---------------------------------------------------------------------------*/ + +//- Temporarily change inputMode to %overwrite for the following entry +class inputModeOverwrite +: + public functionEntry +{ +public: + + //- Execute in a sub-dict context + static bool execute(dictionary& parentDict, Istream& is); +}; + + +/*---------------------------------------------------------------------------*\ + Class inputModeWarn Declaration +\*---------------------------------------------------------------------------*/ + +//- Temporarily change inputMode to %warn for the following entry +class inputModeWarn +: + public functionEntry +{ +public: + + //- Execute in a sub-dict context + static bool execute(dictionary& parentDict, Istream& is); +}; + + +/*---------------------------------------------------------------------------*\ + Class inputModeError Declaration +\*---------------------------------------------------------------------------*/ + +//- Temporarily change inputMode to %error for the following entry +class inputModeError +: + public functionEntry +{ +public: + + //- Execute in a sub-dict context + static bool execute(dictionary& parentDict, Istream& is); +}; + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace functionEntries diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls index 63d17474fb..0eae3d794b 100644 --- a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls +++ b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls @@ -12,6 +12,4 @@ maxCo 12; maxDeltaT 1; -#inputMode merge - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.0 b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.0 index f23b6a4f10..65697b0242 100644 --- a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.0 +++ b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.0 @@ -12,6 +12,4 @@ maxCo 2.5; maxDeltaT 0.3; -#inputMode merge - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.20 b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.20 index c1143ac2dc..56a2dc921f 100644 --- a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.20 +++ b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.20 @@ -12,6 +12,4 @@ maxCo 8; maxDeltaT 1; -#inputMode merge - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.5 b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.5 index be96ad7429..9f1c5f5932 100644 --- a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.5 +++ b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.5 @@ -12,6 +12,4 @@ maxCo 5; maxDeltaT 1; -#inputMode merge - // ************************************************************************* // diff --git a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.60 b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.60 index 63d17474fb..0eae3d794b 100644 --- a/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.60 +++ b/tutorials/heatTransfer/chtMultiRegionFoam/windshieldCondensation/system/solverControls.60 @@ -12,6 +12,4 @@ maxCo 12; maxDeltaT 1; -#inputMode merge - // ************************************************************************* // diff --git a/tutorials/incompressible/lumpedPointMotion/building/steady/0.orig/include/initialConditions b/tutorials/incompressible/lumpedPointMotion/building/steady/0.orig/include/initialConditions index 8d82530aae..30be52d972 100644 --- a/tutorials/incompressible/lumpedPointMotion/building/steady/0.orig/include/initialConditions +++ b/tutorials/incompressible/lumpedPointMotion/building/steady/0.orig/include/initialConditions @@ -12,6 +12,4 @@ turbulentKE 37; turbulentOmega 32; turbulentEpsilon 30; -#inputMode merge - // ************************************************************************* // diff --git a/tutorials/incompressible/overPimpleDyMFoam/cylinder/cylinderAndBackground/0.orig/include/initialConditions b/tutorials/incompressible/overPimpleDyMFoam/cylinder/cylinderAndBackground/0.orig/include/initialConditions index aaa6bd1c6f..d2b995d3b5 100644 --- a/tutorials/incompressible/overPimpleDyMFoam/cylinder/cylinderAndBackground/0.orig/include/initialConditions +++ b/tutorials/incompressible/overPimpleDyMFoam/cylinder/cylinderAndBackground/0.orig/include/initialConditions @@ -10,6 +10,5 @@ flowVelocity (10 0 0); pressure 0; turbulentKE 1.5; turbulentEpsilon 0.88; -#inputMode merge // ************************************************************************* // diff --git a/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/0.orig/include/initialConditions b/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/0.orig/include/initialConditions index e0b2bd996e..14ab8e962c 100644 --- a/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/0.orig/include/initialConditions +++ b/tutorials/incompressible/overSimpleFoam/aeroFoil/background_overset/0.orig/include/initialConditions @@ -11,6 +11,5 @@ pressure 0; turbulentKE 0.375; turbulentOmega 3.6; turbulentEpsilon 0.12; -#inputMode merge // ************************************************************************* // From e03ca4c4662ed6ade115944c1fcb0f268ed02c74 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Fri, 4 Aug 2017 11:09:32 +0200 Subject: [PATCH 005/126] CONFIG: add Cray compiler, cray mpich settings, wmake rules (fixes #558) - the cray C/C++ compilers appear to be option-compatible with gcc. - no wmake rules for 32bit builds (deemed to be unnecessary) --- etc/bashrc | 4 ++-- etc/config.csh/mpi | 22 ++++++++++++++++++++++ etc/config.csh/settings | 9 +++++++-- etc/config.sh/mpi | 22 ++++++++++++++++++++++ etc/config.sh/settings | 9 +++++++-- etc/cshrc | 4 ++-- wmake/rules/General/mplibCRAY-MPICH | 1 + wmake/rules/linux64Cray/c | 16 ++++++++++++++++ wmake/rules/linux64Cray/c++ | 24 ++++++++++++++++++++++++ wmake/rules/linux64Cray/c++Debug | 2 ++ wmake/rules/linux64Cray/c++Opt | 4 ++++ wmake/rules/linux64Cray/c++Prof | 2 ++ wmake/rules/linux64Cray/cDebug | 2 ++ wmake/rules/linux64Cray/cOpt | 2 ++ wmake/rules/linux64Cray/cProf | 2 ++ wmake/rules/linux64Cray/general | 9 +++++++++ wmake/rules/linux64Cray/mplibINTELMPI | 3 +++ wmake/rules/linux64Cray/openmp | 4 ++++ 18 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 wmake/rules/General/mplibCRAY-MPICH create mode 100644 wmake/rules/linux64Cray/c create mode 100644 wmake/rules/linux64Cray/c++ create mode 100644 wmake/rules/linux64Cray/c++Debug create mode 100644 wmake/rules/linux64Cray/c++Opt create mode 100644 wmake/rules/linux64Cray/c++Prof create mode 100644 wmake/rules/linux64Cray/cDebug create mode 100644 wmake/rules/linux64Cray/cOpt create mode 100644 wmake/rules/linux64Cray/cProf create mode 100644 wmake/rules/linux64Cray/general create mode 100644 wmake/rules/linux64Cray/mplibINTELMPI create mode 100644 wmake/rules/linux64Cray/openmp diff --git a/etc/bashrc b/etc/bashrc index e2e887ac64..597d5494d6 100644 --- a/etc/bashrc +++ b/etc/bashrc @@ -65,7 +65,7 @@ export WM_COMPILER_TYPE=system #- Compiler: # WM_COMPILER = Gcc | Gcc4[8-9] | Gcc5[1-4] | Gcc6[1-3] | GccKNL -# | Clang | Clang3[8-9] | Clang40 | Icc | IccKNL +# | Clang | Clang3[8-9] | Clang40 | Icc | IccKNL | Cray export WM_COMPILER=Gcc unset WM_COMPILER_ARCH WM_COMPILER_LIB_ARCH @@ -89,7 +89,7 @@ export WM_COMPILE_OPTION=Opt #- MPI implementation: # WM_MPLIB = SYSTEMOPENMPI | OPENMPI | SYSTEMMPI | MPICH | MPICH-GM | HPMPI -# | MPI | FJMPI | QSMPI | SGIMPI | INTELMPI | USERMPI +# | MPI | CRAY-MPICH | FJMPI | QSMPI | SGIMPI | INTELMPI | USERMPI export WM_MPLIB=SYSTEMOPENMPI #- Operating System: diff --git a/etc/config.csh/mpi b/etc/config.csh/mpi index e2ec875e4f..ae9a7c15a4 100644 --- a/etc/config.csh/mpi +++ b/etc/config.csh/mpi @@ -141,6 +141,28 @@ case MPICH-GM: _foamAddLib $GM_LIB_PATH breaksw +case CRAY-MPICH: + if ( ! $?MPICH_DIR ) setenv MPICH_DIR /dev/null + setenv FOAM_MPI cray-mpich + setenv MPI_ARCH_PATH $MPICH_DIR + + if ($?FOAM_VERBOSE && $?prompt) then + echo "Using $WM_MPLIB" + echo " FOAM_MPI : $FOAM_MPI" + echo " MPICH_DIR : $MPI_ARCH_PATH" + endif + + if ( ! -d "$MPI_ARCH_PATH" ) then + echo "Warning in $WM_PROJECT_DIR/etc/config.csh/mpi:" + echo " Not a valid $WM_MPLIB installation directory." + echo " Please set MPICH_DIR properly." + echo " Currently using '$MPI_ARCH_PATH'" + endif + + # _foamAddPath $MPI_ARCH_PATH/bin + _foamAddLib $MPI_ARCH_PATH/lib + breaksw + case HPMPI: setenv FOAM_MPI hpmpi setenv MPI_HOME /opt/hpmpi diff --git a/etc/config.csh/settings b/etc/config.csh/settings index 98442b94a1..40c3df8985 100644 --- a/etc/config.csh/settings +++ b/etc/config.csh/settings @@ -214,12 +214,17 @@ if (! $?WM_COMPILER_TYPE ) setenv WM_COMPILER_TYPE system # Adjustments for non-gcc compilers switch ("$WM_COMPILER") case Clang*: - # Using clang - not gcc + # Using clang compiler suite setenv WM_CC 'clang' setenv WM_CXX 'clang++' breaksw +case Cray*: + # Using cray system compilers + setenv WM_CC 'cc' + setenv WM_CXX 'CC' + breaksw case Icc*: - # Using icc - not gcc + # Using intel compilers setenv WM_CC 'icc' setenv WM_CXX 'icpc' breaksw diff --git a/etc/config.sh/mpi b/etc/config.sh/mpi index a2d676d76b..1a87bf238f 100644 --- a/etc/config.sh/mpi +++ b/etc/config.sh/mpi @@ -160,6 +160,28 @@ MPICH-GM) _foamAddLib $GM_LIB_PATH ;; +CRAY-MPICH) + export FOAM_MPI=cray-mpich + export MPI_ARCH_PATH=$MPICH_DIR + + if [ "$FOAM_VERBOSE" -a "$PS1" ] + then + echo "Using $WM_MPLIB" 1>&2 + echo " FOAM_MPI : $FOAM_MPI" 1>&2 + echo " MPICH_DIR : $MPI_ARCH_PATH" 1>&2 + fi + + [ -d "$MPI_ARCH_PATH" ] || { + echo "Warning in $WM_PROJECT_DIR/etc/config.sh/mpi:" 1>&2 + echo " Not a valid $WM_MPLIB installation directory." 1>&2 + echo " Please set MPICH_DIR properly" 1>&2 + echo " Currently using '$MPI_ARCH_PATH'" 1>&2 + } + + # _foamAddPath $MPI_ARCH_PATH/bin + _foamAddLib $MPI_ARCH_PATH/lib + ;; + HPMPI) export FOAM_MPI=hpmpi export MPI_HOME=/opt/hpmpi diff --git a/etc/config.sh/settings b/etc/config.sh/settings index ebc4bf435a..20821fae2e 100644 --- a/etc/config.sh/settings +++ b/etc/config.sh/settings @@ -216,12 +216,17 @@ _foamAddLib $FOAM_USER_LIBBIN:$FOAM_SITE_LIBBIN:$FOAM_LIBBIN # Adjust for non-gcc compilers case "$WM_COMPILER" in Clang*) - # Using clang - not gcc + # Using clang compiler suite export WM_CC='clang' export WM_CXX='clang++' ;; +Cray*) + # Using cray system compilers + export WM_CC='cc' + export WM_CXX='CC' + ;; Icc*) - # Using icc - not gcc + # Using intel compilers export WM_CC='icc' export WM_CXX='icpc' ;; diff --git a/etc/cshrc b/etc/cshrc index 7b8da52c26..7cefb2f383 100644 --- a/etc/cshrc +++ b/etc/cshrc @@ -61,7 +61,7 @@ setenv WM_COMPILER_TYPE system #- Compiler: # WM_COMPILER = Gcc | Gcc4[8-9] | Gcc5[1-4] | Gcc6[1-3] | GccKNL -# | Clang | Clang3[8-9] | Clang40 | Icc | IccKNL +# | Clang | Clang3[8-9] | Clang40 | Icc | IccKNL | Cray setenv WM_COMPILER Gcc setenv WM_COMPILER_ARCH # defined but empty unsetenv WM_COMPILER_LIB_ARCH @@ -86,7 +86,7 @@ setenv WM_COMPILE_OPTION Opt #- MPI implementation: # WM_MPLIB = SYSTEMOPENMPI | OPENMPI | SYSTEMMPI | MPICH | MPICH-GM | HPMPI -# | MPI | FJMPI | QSMPI | SGIMPI | INTELMPI | USERMPI +# | MPI | CRAY-MPICH | FJMPI | QSMPI | SGIMPI | INTELMPI | USERMPI setenv WM_MPLIB SYSTEMOPENMPI #- Operating System: diff --git a/wmake/rules/General/mplibCRAY-MPICH b/wmake/rules/General/mplibCRAY-MPICH new file mode 100644 index 0000000000..fdb91c1379 --- /dev/null +++ b/wmake/rules/General/mplibCRAY-MPICH @@ -0,0 +1 @@ +include $(GENERAL_RULES)/mplibMPICH diff --git a/wmake/rules/linux64Cray/c b/wmake/rules/linux64Cray/c new file mode 100644 index 0000000000..d08f441440 --- /dev/null +++ b/wmake/rules/linux64Cray/c @@ -0,0 +1,16 @@ +SUFFIXES += .c + +cWARN = -Wall + +cc = cc -m64 + +include $(DEFAULT_RULES)/c$(WM_COMPILE_OPTION) + +cFLAGS = $(GFLAGS) $(cWARN) $(cOPT) $(cDBUG) $(LIB_HEADER_DIRS) -fPIC + +ctoo = $(WM_SCHEDULER) $(cc) $(cFLAGS) -c $< -o $@ + +LINK_LIBS = $(cDBUG) + +LINKLIBSO = $(cc) -shared +LINKEXE = $(cc) -Xlinker --add-needed -Xlinker -z -Xlinker nodefs diff --git a/wmake/rules/linux64Cray/c++ b/wmake/rules/linux64Cray/c++ new file mode 100644 index 0000000000..30c2bc762e --- /dev/null +++ b/wmake/rules/linux64Cray/c++ @@ -0,0 +1,24 @@ +SUFFIXES += .C + +c++WARN = -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof + +# Suppress some warnings for flex++ and CGAL +c++LESSWARN = -Wno-old-style-cast -Wno-unused-local-typedefs -Wno-array-bounds + +CC = CC -std=c++11 -m64 + +include $(DEFAULT_RULES)/c++$(WM_COMPILE_OPTION) + +ptFLAGS = -DNoRepository -ftemplate-depth-100 + +c++FLAGS = $(GFLAGS) $(c++WARN) $(c++OPT) $(c++DBUG) $(ptFLAGS) $(LIB_HEADER_DIRS) -fPIC + +Ctoo = $(WM_SCHEDULER) $(CC) $(c++FLAGS) -c $< -o $@ +cxxtoo = $(Ctoo) +cctoo = $(Ctoo) +cpptoo = $(Ctoo) + +LINK_LIBS = $(c++DBUG) + +LINKLIBSO = $(CC) $(c++FLAGS) -shared -Xlinker --add-needed -Xlinker --no-as-needed +LINKEXE = $(CC) $(c++FLAGS) -Xlinker --add-needed -Xlinker --no-as-needed diff --git a/wmake/rules/linux64Cray/c++Debug b/wmake/rules/linux64Cray/c++Debug new file mode 100644 index 0000000000..19bdb9c334 --- /dev/null +++ b/wmake/rules/linux64Cray/c++Debug @@ -0,0 +1,2 @@ +c++DBUG = -ggdb3 -DFULLDEBUG +c++OPT = -O0 -fdefault-inline diff --git a/wmake/rules/linux64Cray/c++Opt b/wmake/rules/linux64Cray/c++Opt new file mode 100644 index 0000000000..599e6aba61 --- /dev/null +++ b/wmake/rules/linux64Cray/c++Opt @@ -0,0 +1,4 @@ +c++DBUG = +c++OPT = -O3 + +ROUNDING_MATH = -frounding-math diff --git a/wmake/rules/linux64Cray/c++Prof b/wmake/rules/linux64Cray/c++Prof new file mode 100644 index 0000000000..3bda4dad55 --- /dev/null +++ b/wmake/rules/linux64Cray/c++Prof @@ -0,0 +1,2 @@ +c++DBUG = -pg +c++OPT = -O2 diff --git a/wmake/rules/linux64Cray/cDebug b/wmake/rules/linux64Cray/cDebug new file mode 100644 index 0000000000..72b638f458 --- /dev/null +++ b/wmake/rules/linux64Cray/cDebug @@ -0,0 +1,2 @@ +cDBUG = -ggdb -DFULLDEBUG +cOPT = -O1 -fdefault-inline -finline-functions diff --git a/wmake/rules/linux64Cray/cOpt b/wmake/rules/linux64Cray/cOpt new file mode 100644 index 0000000000..17318709f1 --- /dev/null +++ b/wmake/rules/linux64Cray/cOpt @@ -0,0 +1,2 @@ +cDBUG = +cOPT = -O3 diff --git a/wmake/rules/linux64Cray/cProf b/wmake/rules/linux64Cray/cProf new file mode 100644 index 0000000000..ca3ac9bf5f --- /dev/null +++ b/wmake/rules/linux64Cray/cProf @@ -0,0 +1,2 @@ +cDBUG = -pg +cOPT = -O2 diff --git a/wmake/rules/linux64Cray/general b/wmake/rules/linux64Cray/general new file mode 100644 index 0000000000..a0c807e5d8 --- /dev/null +++ b/wmake/rules/linux64Cray/general @@ -0,0 +1,9 @@ +CPP = cpp -traditional-cpp $(GFLAGS) + +PROJECT_LIBS = -l$(WM_PROJECT) -ldl + +include $(GENERAL_RULES)/standard + +# include $(DEFAULT_RULES)/openmp +include $(DEFAULT_RULES)/c +include $(DEFAULT_RULES)/c++ diff --git a/wmake/rules/linux64Cray/mplibINTELMPI b/wmake/rules/linux64Cray/mplibINTELMPI new file mode 100644 index 0000000000..278e0b0f22 --- /dev/null +++ b/wmake/rules/linux64Cray/mplibINTELMPI @@ -0,0 +1,3 @@ +PFLAGS = -DMPICH_SKIP_MPICXX +PINC = -isystem $(MPI_ARCH_PATH)/include64 +PLIBS = -L$(MPI_ARCH_PATH)/lib64 -lmpi diff --git a/wmake/rules/linux64Cray/openmp b/wmake/rules/linux64Cray/openmp new file mode 100644 index 0000000000..bcb805f57c --- /dev/null +++ b/wmake/rules/linux64Cray/openmp @@ -0,0 +1,4 @@ +# Flags for compiling/linking openmp + +COMP_OPENMP = -DUSE_OMP -fopenmp +LINK_OPENMP = -lgomp From 8b63772882abaff3b4c00eb06e05c775db5871d6 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 9 Aug 2017 13:45:30 +0200 Subject: [PATCH 006/126] ENH: simplify parsing logic in ISstream --- src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C | 211 +++++++++--------- src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H | 7 +- .../db/IOstreams/Sstreams/prefixOSstream.C | 2 +- 3 files changed, 110 insertions(+), 110 deletions(-) diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C index 15ad568f18..010eef975b 100644 --- a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C +++ b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -28,6 +28,12 @@ License #include "token.H" #include +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// Truncate error message for readability +static const unsigned errLen = 80; + + // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // char Foam::ISstream::nextValid() @@ -43,7 +49,7 @@ char Foam::ISstream::nextValid() // Return if stream is bad - ie, previous get() failed if (bad() || isspace(c)) { - break; + return 0; } // Is this the start of a C/C++ comment? @@ -51,7 +57,7 @@ char Foam::ISstream::nextValid() { if (!get(c)) { - // cannot get another character - return this one + // Cannot get another character - return this one return '/'; } @@ -63,10 +69,10 @@ char Foam::ISstream::nextValid() } else if (c == '*') { - // within a C-style comment + // Within a C-style comment while (true) { - // search for end of C-style comment - '*/' + // Search for end of C-style comment - '*/' if (get(c) && c == '*') { if (get(c)) @@ -99,7 +105,7 @@ char Foam::ISstream::nextValid() } else { - // a valid character - return it + // A valid character - return it return c; } } @@ -124,14 +130,14 @@ void Foam::ISstream::readWordToken(token& t) } else { - t = wPtr; + t = wPtr; // Token takes ownership } } Foam::Istream& Foam::ISstream::read(token& t) { - static const int maxLen = 128; + static const unsigned maxLen = 128; // When parsing labels or scalars static char buf[maxLen]; // Return the put back token if it exists @@ -151,7 +157,7 @@ Foam::Istream& Foam::ISstream::read(token& t) // Set the line number of this token to the current stream line number t.lineNumber() = lineNumber(); - // return on error + // Return on error if (!c) { t.setBad(); @@ -182,7 +188,6 @@ Foam::Istream& Foam::ISstream::read(token& t) return *this; } - // String: enclosed by double quotes. case token::BEGIN_STRING : { @@ -196,24 +201,24 @@ Foam::Istream& Foam::ISstream::read(token& t) } else { - t = sPtr; + t = sPtr; // Token takes ownership } return *this; } + // Possible verbatim string or dictionary functionEntry case token::HASH : { char nextC; if (read(nextC).bad()) { - // Return hash as word + // Return lone '#' as word t = token(word(c)); - return *this; } else if (nextC == token::BEGIN_BLOCK) { - // Verbatim string + // Verbatim string: #{ ... #} string* sPtr = new string; if (readVerbatim(*sPtr).bad()) @@ -223,36 +228,34 @@ Foam::Istream& Foam::ISstream::read(token& t) } else { - t = sPtr; + t = sPtr; // Token takes ownership t.type() = token::tokenType::VERBATIMSTRING; } - - return *this; } else { - // Word beginning with # + // Word beginning with '#'. Eg, "#include" putback(nextC); putback(c); readWordToken(t); - - return *this; } + + return *this; } + // Dictionary variable (as rvalue) case '$': { - // Look ahead char nextC; if (read(nextC).bad()) { - // Return $ as word + // Return lone '$' as word t = token(word(c)); - return *this; } else if (nextC == token::BEGIN_BLOCK) { + // Put back so that "${" is included in the variable putback(nextC); putback(c); @@ -265,18 +268,20 @@ Foam::Istream& Foam::ISstream::read(token& t) } else { - t = sPtr; + t = sPtr; // Token takes ownership t.type() = token::tokenType::VARIABLE; } - return *this; } else { + // Word/variable beginning with '$', but without "{}" + putback(nextC); putback(c); readWordToken(t); - return *this; } + + return *this; } // Number: integer or floating point @@ -292,7 +297,7 @@ Foam::Istream& Foam::ISstream::read(token& t) { bool asLabel = (c != '.'); - int nChar = 0; + unsigned nChar = 0; buf[nChar++] = c; // get everything that could resemble a number and let @@ -343,43 +348,26 @@ Foam::Istream& Foam::ISstream::read(token& t) if (nChar == 1 && buf[0] == '-') { - // a single '-' is punctuation + // A single '-' is punctuation t = token::punctuationToken(token::SUBTRACT); } else { - if (asLabel) + label labelVal; + scalar scalarVal; + + if (asLabel && Foam::read(buf, labelVal)) { - label labelVal = 0; - if (Foam::read(buf, labelVal)) - { - t = labelVal; - } - else - { - // Maybe too big? Try as scalar - scalar scalarVal; - if (readScalar(buf, scalarVal)) - { - t = scalarVal; - } - else - { - t.setBad(); - } - } + t = labelVal; + } + else if (readScalar(buf, scalarVal)) + { + // A scalar or too big to fit as a label + t = scalarVal; } else { - scalar scalarVal; - if (readScalar(buf, scalarVal)) - { - t = scalarVal; - } - else - { - t.setBad(); - } + t.setBad(); } } } @@ -409,28 +397,28 @@ Foam::Istream& Foam::ISstream::read(char& c) Foam::Istream& Foam::ISstream::read(word& str) { - static const int maxLen = 1024; - static const int errLen = 80; // truncate error message for readability + static const unsigned maxLen = 1024; static char buf[maxLen]; - int nChar = 0; - int listDepth = 0; + unsigned nChar = 0; + unsigned depth = 0; // Track depth of "()" nesting char c; while (get(c) && word::valid(c)) { if (c == token::BEGIN_LIST) { - listDepth++; + ++depth; } else if (c == token::END_LIST) { - if (listDepth) + if (depth) { - listDepth--; + --depth; } else { + // Had ')' without a previous '(' ... stop break; } } @@ -449,10 +437,13 @@ Foam::Istream& Foam::ISstream::read(word& str) } } - // we could probably skip this check + // Terminate string with nul char + buf[nChar] = '\0'; + + // We could probably skip this check if (bad()) { - buf[errLen] = buf[nChar] = '\0'; + buf[errLen] = '\0'; FatalIOErrorInFunction(*this) << "problem while reading word '" << buf << "...' after " @@ -468,9 +459,14 @@ Foam::Istream& Foam::ISstream::read(word& str) << "invalid first character found : " << c << exit(FatalIOError); } + else if (depth) + { + IOWarningInFunction(*this) + << "Missing " << depth << " closing ')' while parsing" << nl << nl + << buf << nl << endl; + } - // done reading - buf[nChar] = '\0'; + // Finalize str = buf; putback(c); @@ -480,8 +476,7 @@ Foam::Istream& Foam::ISstream::read(word& str) Foam::Istream& Foam::ISstream::read(string& str) { - static const int maxLen = 1024; - static const int errLen = 80; // truncate error message for readability + static const unsigned maxLen = 1024; static char buf[maxLen]; char c; @@ -505,7 +500,7 @@ Foam::Istream& Foam::ISstream::read(string& str) return *this; } - int nChar = 0; + unsigned nChar = 0; bool escaped = false; while (get(c)) @@ -515,11 +510,11 @@ Foam::Istream& Foam::ISstream::read(string& str) if (escaped) { escaped = false; - nChar--; // overwrite backslash + --nChar; // Overwrite backslash } else { - // done reading + // Done reading buf[nChar] = '\0'; str = buf; return *this; @@ -530,7 +525,7 @@ Foam::Istream& Foam::ISstream::read(string& str) if (escaped) { escaped = false; - nChar--; // overwrite backslash + --nChar; // Overwrite backslash } else { @@ -581,12 +576,11 @@ Foam::Istream& Foam::ISstream::read(string& str) Foam::Istream& Foam::ISstream::readVariable(string& str) { - static const int maxLen = 1024; - static const int errLen = 80; // truncate error message for readability + static const unsigned maxLen = 1024; static char buf[maxLen]; - int nChar = 0; - int blockCount = 0; + unsigned nChar = 0; + unsigned depth = 0; // Track depth of "{}" nesting char c; if (!get(c) || c != '$') @@ -601,8 +595,8 @@ Foam::Istream& Foam::ISstream::readVariable(string& str) // Read next character to see if '{' if (get(c) && c == token::BEGIN_BLOCK) { - // Read, counting brackets buf[nChar++] = c; + ++depth; // Starts with '{' // Also allow '/' between ${...} blocks for slash-scoping of entries while @@ -615,6 +609,23 @@ Foam::Istream& Foam::ISstream::readVariable(string& str) ) ) { + if (c == token::BEGIN_BLOCK) + { + ++depth; + } + else if (c == token::END_BLOCK) + { + if (depth) + { + --depth; + } + else + { + // Had '}' without a previous '{' ... stop + break; + } + } + buf[nChar++] = c; if (nChar == maxLen) { @@ -627,22 +638,6 @@ Foam::Istream& Foam::ISstream::readVariable(string& str) return *this; } - - if (c == token::BEGIN_BLOCK) - { - blockCount++; - } - else if (c == token::END_BLOCK) - { - if (blockCount) - { - blockCount--; - } - else - { - break; - } - } } } else @@ -666,10 +661,13 @@ Foam::Istream& Foam::ISstream::readVariable(string& str) } } + // Terminate string with nul char + buf[nChar] = '\0'; + // we could probably skip this check if (bad()) { - buf[errLen] = buf[nChar] = '\0'; + buf[errLen] = '\0'; FatalIOErrorInFunction(*this) << "problem while reading string '" << buf << "...' after " @@ -685,31 +683,29 @@ Foam::Istream& Foam::ISstream::readVariable(string& str) << "invalid first character found : " << c << exit(FatalIOError); } - - // done reading - buf[nChar] = '\0'; - str = buf; - - // Note: check if we exited due to '}' or just !word::valid. - if (c != token::END_BLOCK) + else if (depth) { - putback(c); + IOWarningInFunction(*this) + << "Missing " << depth << " closing '}' while parsing" << nl << nl + << buf << nl << endl; } + // Finalize + str = buf; + putback(c); + return *this; } Foam::Istream& Foam::ISstream::readVerbatim(string& str) { - static const int maxLen = 8000; - static const int errLen = 80; // truncate error message for readability + static const unsigned maxLen = 8000; static char buf[maxLen]; + unsigned nChar = 0; char c; - int nChar = 0; - while (get(c)) { if (c == token::HASH) @@ -718,6 +714,7 @@ Foam::Istream& Foam::ISstream::readVerbatim(string& str) get(nextC); if (nextC == token::END_BLOCK) { + // The closing "#}" found buf[nChar] = '\0'; str = buf; return *this; diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H index 4a2b510b5b..e446272f85 100644 --- a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H +++ b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -69,9 +69,12 @@ class ISstream //- Read a verbatim string (excluding block delimiters). + // The leading "#{" has been removed prior to calling, + // continues until the closing "#}" has been found. Istream& readVerbatim(string& str); - //- Read a variable name (includes '{') + //- Read a variable name starting with '$'. + // Handles both "$var" and "${var}" forms. Istream& readVariable(string& str); //- Disallow default bitwise assignment diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/prefixOSstream.C b/src/OpenFOAM/db/IOstreams/Sstreams/prefixOSstream.C index cb28408f7d..42a2df76c9 100644 --- a/src/OpenFOAM/db/IOstreams/Sstreams/prefixOSstream.C +++ b/src/OpenFOAM/db/IOstreams/Sstreams/prefixOSstream.C @@ -102,7 +102,7 @@ Foam::Ostream& Foam::prefixOSstream::write(const char* str) checkWritePrefix(); OSstream::write(str); - size_t len = strlen(str); + const size_t len = strlen(str); if (len && str[len-1] == token::NL) { printPrefix_ = true; From 79f2466ca525bfbd037c2ae7d30167a465e20272 Mon Sep 17 00:00:00 2001 From: Andrew Heather Date: Mon, 18 Sep 2017 10:17:24 +0100 Subject: [PATCH 007/126] BUG: DESModelRegions - added missing field write() - see #591 --- src/functionObjects/field/DESModelRegions/DESModelRegions.C | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/functionObjects/field/DESModelRegions/DESModelRegions.C b/src/functionObjects/field/DESModelRegions/DESModelRegions.C index bb94a12767..ba30876431 100644 --- a/src/functionObjects/field/DESModelRegions/DESModelRegions.C +++ b/src/functionObjects/field/DESModelRegions/DESModelRegions.C @@ -172,6 +172,8 @@ bool Foam::functionObjects::DESModelRegions::write() << " writing field " << DESModelRegions.name() << nl << endl; + DESModelRegions.write(); + return true; } From 94cf702f6976527eef8a3923bd8f0359dec13606 Mon Sep 17 00:00:00 2001 From: Andrew Heather Date: Mon, 18 Sep 2017 10:48:39 +0100 Subject: [PATCH 008/126] BUG: kOmegaSSTLM - corrected writing of coefficients. Fixes #592 --- .../turbulenceModels/RAS/kOmegaSSTLM/kOmegaSSTLM.C | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/TurbulenceModels/turbulenceModels/RAS/kOmegaSSTLM/kOmegaSSTLM.C b/src/TurbulenceModels/turbulenceModels/RAS/kOmegaSSTLM/kOmegaSSTLM.C index 5d14d97bf9..371b0a51f1 100644 --- a/src/TurbulenceModels/turbulenceModels/RAS/kOmegaSSTLM/kOmegaSSTLM.C +++ b/src/TurbulenceModels/turbulenceModels/RAS/kOmegaSSTLM/kOmegaSSTLM.C @@ -373,7 +373,8 @@ kOmegaSSTLM::kOmegaSSTLM alphaRhoPhi, phi, transport, - propertiesName + propertiesName, + typeName ), ca1_ @@ -477,7 +478,12 @@ kOmegaSSTLM::kOmegaSSTLM this->mesh_, dimensionedScalar("0", dimless, 0) ) -{} +{ + if (type == typeName) + { + this->printCoeffs(type); + } +} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // From 68e7533847dde7514df4cd8dcb444ec32dc380d6 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 20 Sep 2017 17:01:56 +0200 Subject: [PATCH 009/126] STYLE: include in stdFoam, formatting of list loop macros --- .../containers/Lists/FixedList/FixedList.C | 6 +- src/OpenFOAM/containers/Lists/List/List.C | 18 ++++-- .../containers/Lists/List/ListLoopM.H | 12 +--- src/OpenFOAM/containers/Lists/UList/UList.C | 12 ++-- src/OpenFOAM/fields/Fields/Field/FieldM.H | 58 ++++++++++++------- src/OpenFOAM/include/stdFoam.H | 24 ++++---- 6 files changed, 78 insertions(+), 52 deletions(-) diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedList.C b/src/OpenFOAM/containers/Lists/FixedList/FixedList.C index 03c3d16768..19163402da 100644 --- a/src/OpenFOAM/containers/Lists/FixedList/FixedList.C +++ b/src/OpenFOAM/containers/Lists/FixedList/FixedList.C @@ -35,10 +35,11 @@ void Foam::FixedList::swap(FixedList& a) List_ACCESS(T, a, ap); T tmp; List_FOR_ALL((*this), i) + { tmp = List_CELEM((*this), vp, i); List_ELEM((*this), vp, i) = List_CELEM(a, ap, i); List_ELEM(a, ap, i) = tmp; - List_END_FOR_ALL + } } @@ -53,9 +54,10 @@ bool Foam::FixedList::operator==(const FixedList& a) const List_CONST_ACCESS(T, (a), ap); List_FOR_ALL((*this), i) + { equal = (List_ELEM((*this), vp, i) == List_ELEM((a), ap, i)); if (!equal) break; - List_END_FOR_ALL + } return equal; } diff --git a/src/OpenFOAM/containers/Lists/List/List.C b/src/OpenFOAM/containers/Lists/List/List.C index ab8aea673f..04f731f211 100644 --- a/src/OpenFOAM/containers/Lists/List/List.C +++ b/src/OpenFOAM/containers/Lists/List/List.C @@ -69,8 +69,9 @@ Foam::List::List(const label s, const T& a) { List_ACCESS(T, (*this), vp); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = a; - List_END_FOR_ALL + } } } @@ -93,8 +94,9 @@ Foam::List::List(const label s, const zero) { List_ACCESS(T, (*this), vp); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = Zero; - List_END_FOR_ALL + } } } @@ -119,8 +121,9 @@ Foam::List::List(const List& a) List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T, a, ap); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = List_ELEM(a, ap, i); - List_END_FOR_ALL + } } } } @@ -139,8 +142,9 @@ Foam::List::List(const List& a) List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T2, a, ap); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = T(List_ELEM(a, ap, i)); - List_END_FOR_ALL + } } } @@ -178,8 +182,9 @@ Foam::List::List(List& a, bool reuse) List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T, a, ap); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = List_ELEM(a, ap, i); - List_END_FOR_ALL + } } } } @@ -390,8 +395,9 @@ void Foam::List::operator=(const UList& a) List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T, a, ap); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = List_ELEM(a, ap, i); - List_END_FOR_ALL + } } } } diff --git a/src/OpenFOAM/containers/Lists/List/ListLoopM.H b/src/OpenFOAM/containers/Lists/List/ListLoopM.H index 032edb3052..5f74321bc6 100644 --- a/src/OpenFOAM/containers/Lists/List/ListLoopM.H +++ b/src/OpenFOAM/containers/Lists/List/ListLoopM.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,10 +37,7 @@ Description #define List_FOR_ALL(f, i) \ const label _n##i = (f).size(); \ - for (label i=0; i<_n##i; ++i) \ - { - -#define List_END_FOR_ALL } + for (label i=0; i<_n##i; ++i) // Provide current element #define List_CELEM(f, fp, i) (fp[i]) @@ -60,10 +57,7 @@ Description #define List_FOR_ALL(f, i) \ label i = (f).size(); \ - while (i--) \ - { \ - -#define List_END_FOR_ALL } + while (i--) // Provide current element without incrementing pointer #define List_CELEM(f, fp, i) (*fp) diff --git a/src/OpenFOAM/containers/Lists/UList/UList.C b/src/OpenFOAM/containers/Lists/UList/UList.C index f479698744..599dd0f998 100644 --- a/src/OpenFOAM/containers/Lists/UList/UList.C +++ b/src/OpenFOAM/containers/Lists/UList/UList.C @@ -95,8 +95,9 @@ void Foam::UList::deepCopy(const UList& a) List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T, a, ap); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = List_ELEM(a, ap, i); - List_END_FOR_ALL + } } } } @@ -152,8 +153,9 @@ void Foam::UList::operator=(const T& t) { List_ACCESS(T, (*this), vp); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = t; - List_END_FOR_ALL + } } @@ -162,8 +164,9 @@ void Foam::UList::operator=(const zero) { List_ACCESS(T, (*this), vp); List_FOR_ALL((*this), i) + { List_ELEM((*this), vp, i) = Zero; - List_END_FOR_ALL + } } @@ -244,9 +247,10 @@ bool Foam::UList::operator==(const UList& a) const List_CONST_ACCESS(T, (a), ap); List_FOR_ALL((*this), i) + { equal = (List_ELEM((*this), vp, i) == List_ELEM((a), ap, i)); if (!equal) break; - List_END_FOR_ALL + } return equal; } diff --git a/src/OpenFOAM/fields/Fields/Field/FieldM.H b/src/OpenFOAM/fields/Fields/Field/FieldM.H index 28d4788c17..46be4b350d 100644 --- a/src/OpenFOAM/fields/Fields/Field/FieldM.H +++ b/src/OpenFOAM/fields/Fields/Field/FieldM.H @@ -120,8 +120,9 @@ void checkFields \ /* loop through fields performing f1 OP1 f2 OP2 f3 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP FUNC(List_ELEM(f2, f2P, i)); \ - List_END_FOR_ALL \ + } #define TFOR_ALL_F_OP_F_FUNC(typeF1, f1, OP, typeF2, f2, FUNC) \ @@ -135,13 +136,14 @@ void checkFields \ /* loop through fields performing f1 OP1 f2 OP2 f3 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP List_ELEM(f2, f2P, i).FUNC(); \ - List_END_FOR_ALL \ + } // member function : this field f1 OP fUNC f2, f3 -#define TFOR_ALL_F_OP_FUNC_F_F(typeF1, f1, OP, FUNC, typeF2, f2, typeF3, f3)\ +#define TFOR_ALL_F_OP_FUNC_F_F(typeF1, f1, OP, FUNC, typeF2, f2, typeF3, f3) \ \ /* check the three fields have same Field mesh */ \ checkFields(f1, f2, f3, "f1 " #OP " " #FUNC "(f2, f3)"); \ @@ -153,9 +155,10 @@ void checkFields \ /* loop through fields performing f1 OP1 f2 OP2 f3 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) \ OP FUNC(List_ELEM(f2, f2P, i), List_ELEM(f3, f3P, i)); \ - List_END_FOR_ALL \ + } // member function : this field f1 OP fUNC f2, f3 @@ -171,8 +174,9 @@ void checkFields \ /* loop through fields performing s OP FUNC(f1, f2) */ \ List_FOR_ALL(f1, i) \ + { \ (s) OP FUNC(List_ELEM(f1, f1P, i), List_ELEM(f2, f2P, i)); \ - List_END_FOR_ALL \ + } // member function : this f1 OP fUNC f2, s @@ -188,8 +192,9 @@ void checkFields \ /* loop through fields performing f1 OP1 f2 OP2 f3 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP FUNC(List_ELEM(f2, f2P, i), (s)); \ - List_END_FOR_ALL + } // member function : s1 OP fUNC f, s2 @@ -201,8 +206,9 @@ void checkFields \ /* loop through fields performing f1 OP1 f2 OP2 f3 */ \ List_FOR_ALL(f, i) \ + { \ (s1) OP FUNC(List_ELEM(f, fP, i), (s2)); \ - List_END_FOR_ALL \ + } // member function : this f1 OP fUNC s, f2 @@ -218,21 +224,23 @@ void checkFields \ /* loop through fields performing f1 OP1 f2 OP2 f3 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP FUNC((s), List_ELEM(f2, f2P, i)); \ - List_END_FOR_ALL \ + } // member function : this f1 OP fUNC s, f2 -#define TFOR_ALL_F_OP_FUNC_S_S(typeF1, f1, OP, FUNC, typeS1, s1, typeS2, s2)\ +#define TFOR_ALL_F_OP_FUNC_S_S(typeF1, f1, OP, FUNC, typeS1, s1, typeS2, s2) \ \ /* set access to f1 at end of field */ \ List_ACCESS(typeF1, f1, f1P); \ \ /* loop through fields performing f1 OP1 FUNC(s1, s2) */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP FUNC((s1), (s2)); \ - List_END_FOR_ALL \ + } // member function : this f1 OP1 f2 OP2 FUNC s @@ -248,8 +256,9 @@ void checkFields \ /* loop through fields performing f1 OP1 f2 OP2 f3 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP List_ELEM(f2, f2P, i) FUNC((s)); \ - List_END_FOR_ALL \ + } // define high performance macro functions for Field operations @@ -268,9 +277,10 @@ void checkFields \ /* loop through fields performing f1 OP1 f2 OP2 f3 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP1 List_ELEM(f2, f2P, i) \ OP2 List_ELEM(f3, f3P, i); \ - List_END_FOR_ALL \ + } // member operator : this field f1 OP1 s OP2 f2 @@ -286,8 +296,9 @@ void checkFields \ /* loop through fields performing f1 OP1 s OP2 f2 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP1 (s) OP2 List_ELEM(f2, f2P, i); \ - List_END_FOR_ALL \ + } // member operator : this field f1 OP1 f2 OP2 s @@ -303,8 +314,9 @@ void checkFields \ /* loop through fields performing f1 OP1 s OP2 f2 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP1 List_ELEM(f2, f2P, i) OP2 (s); \ - List_END_FOR_ALL \ + } // member operator : this field f1 OP f2 @@ -321,8 +333,9 @@ void checkFields \ /* loop through fields performing f1 OP f2 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP List_ELEM(f2, f2P, i); \ - List_END_FOR_ALL \ + } // member operator : this field f1 OP1 OP2 f2 @@ -338,8 +351,9 @@ void checkFields \ /* loop through fields performing f1 OP1 OP2 f2 */ \ List_FOR_ALL(f1, i) \ + { \ List_ELEM(f1, f1P, i) OP1 OP2 List_ELEM(f2, f2P, i); \ - List_END_FOR_ALL \ + } // member operator : this field f OP s @@ -351,8 +365,9 @@ void checkFields \ /* loop through field performing f OP s */ \ List_FOR_ALL(f, i) \ + { \ List_ELEM(f, fP, i) OP (s); \ - List_END_FOR_ALL \ + } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -367,8 +382,9 @@ void checkFields \ /* loop through field performing s OP f */ \ List_FOR_ALL(f, i) \ + { \ (s) OP List_ELEM(f, fP, i); \ - List_END_FOR_ALL + } // friend operator function : s OP1 f1 OP2 f2, allocates storage for s @@ -381,8 +397,9 @@ void checkFields \ /* loop through field performing s OP f */ \ List_FOR_ALL(f1, i) \ + { \ (s) OP1 List_ELEM(f1, f1P, i) OP2 List_ELEM(f2, f2P, i); \ - List_END_FOR_ALL + } // friend operator function : s OP FUNC(f), allocates storage for s @@ -394,8 +411,9 @@ void checkFields \ /* loop through field performing s OP f */ \ List_FOR_ALL(f, i) \ + { \ (s) OP FUNC(List_ELEM(f, fP, i)); \ - List_END_FOR_ALL + } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/include/stdFoam.H b/src/OpenFOAM/include/stdFoam.H index 59b0d9f704..3141c38351 100644 --- a/src/OpenFOAM/include/stdFoam.H +++ b/src/OpenFOAM/include/stdFoam.H @@ -25,12 +25,13 @@ Namespace stdFoam Description - Includes some global templates and macros used by OpenFOAM. + Some global templates and macros used by OpenFOAM and some standard + C++ headers. - Some of the templates are defined here correspond to useful + Some of the templates defined here correspond to useful std templates that are part of future C++ standards, or that are in a state of change. Defining them here provides some additional - control over which definition are used within the OpenFOAM code-base. + control over which definitions are used within the OpenFOAM code-base. SeeAlso - http://en.cppreference.com/w/cpp/iterator/end @@ -42,6 +43,7 @@ SeeAlso #define StdFoam_H #include +#include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -114,12 +116,12 @@ constexpr auto cend(const C& c) -> decltype(c.end()) // } // \endcode // \sa forAllConstIters, forAllIter, forAllConstIters -#define forAllIters(container,it) \ +#define forAllIters(container,iter) \ for \ ( \ - auto it = stdFoam::begin(container); \ - it != stdFoam::end(container); \ - ++it \ + auto iter = stdFoam::begin(container); \ + iter != stdFoam::end(container); \ + ++iter \ ) @@ -132,12 +134,12 @@ constexpr auto cend(const C& c) -> decltype(c.end()) // } // \endcode // \sa forAllIters, forAllIter, forAllConstIter -#define forAllConstIters(container,cit) \ +#define forAllConstIters(container,iter) \ for \ ( \ - auto cit = stdFoam::cbegin(container); \ - cit != stdFoam::cend(container); \ - ++cit \ + auto iter = stdFoam::cbegin(container); \ + iter != stdFoam::cend(container); \ + ++iter \ ) From 049617d037d963533d554a1efc9e110f70e05589 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 20 Sep 2017 17:20:54 +0200 Subject: [PATCH 010/126] ENH: update List and DynamicList methods (issue #595) - improve functional compatibility with DynList (remove methods) * eg, remove an element from any position in a DynamicList * reduce the number of template parameters * remove/subset regions of DynamicList - propagate Swap template specializations for lists, hashtables - move construct/assignment to various containers. - add find/found methods for FixedList and UList for a more succinct (and clearer?) usage than the equivalent global findIndex() function. - simplify List_FOR_ALL loops --- .../test/DynamicList/Test-DynamicList.C | 109 ++- applications/test/Field/Make/files | 3 - applications/test/Field/Make/options | 2 - applications/test/Field/Test-Field.C | 11 - applications/test/Field/Test-Field.H | 58 -- applications/test/FixedList/Test-FixedList.C | 65 +- applications/test/FixedList/fixedListFile | Bin 30 -> 0 bytes applications/test/FixedList2/Make/files | 3 + applications/test/FixedList2/Make/options | 0 .../test/FixedList2/Test-FixedList2.C | 190 ++++++ applications/test/Function1/Test-Function1.C | 7 +- applications/test/HashSet/Test-hashSet.C | 25 + applications/test/HashTable/Test-hashTable.C | 28 + .../test/IndirectList/Test-IndirectList.C | 56 +- applications/test/List/Test-List.C | 24 +- applications/test/List2/Make/files | 3 + applications/test/List2/Make/options | 0 applications/test/List2/Test-List2.C | 269 ++++++++ applications/test/ListOps2/Make/files | 2 + applications/test/ListOps2/Make/options | 3 + applications/test/ListOps2/Test-ListOps2.C | 144 ++++ applications/test/Map/Test-Map.C | 58 +- .../test/UIndirectList/Test-UIndirectList.C | 87 ++- applications/test/sort/Test-sortList.C | 169 +++-- .../ideasUnvToFoam/ideasUnvToFoam.C | 3 +- .../containers/HashTables/HashSet/HashSet.C | 11 +- .../containers/HashTables/HashSet/HashSet.H | 35 +- .../HashTables/HashTable/HashTable.C | 39 ++ .../HashTables/HashTable/HashTable.H | 20 + .../HashTables/HashTable/HashTableI.H | 13 + src/OpenFOAM/containers/HashTables/Map/Map.H | 31 +- .../Lists/BiIndirectList/BiIndirectList.H | 20 +- .../Lists/BiIndirectList/BiIndirectListI.H | 38 +- .../Lists/DynamicList/DynamicList.C | 76 ++- .../Lists/DynamicList/DynamicList.H | 231 +++++-- .../Lists/DynamicList/DynamicListI.H | 645 +++++++++++++----- .../containers/Lists/FixedList/FixedList.C | 94 ++- .../containers/Lists/FixedList/FixedList.H | 91 ++- .../containers/Lists/FixedList/FixedListI.H | 115 +++- .../Lists/IndirectList/IndirectList.H | 60 +- .../Lists/IndirectList/IndirectListI.H | 1 - src/OpenFOAM/containers/Lists/List/List.C | 168 +++-- src/OpenFOAM/containers/Lists/List/List.H | 59 +- src/OpenFOAM/containers/Lists/List/ListI.H | 14 +- .../containers/Lists/List/ListLoopM.H | 49 +- .../Lists/ListOps/ListOpsTemplates.C | 2 +- .../Lists/SortableList/SortableList.C | 107 ++- .../Lists/SortableList/SortableList.H | 48 +- .../Lists/UIndirectList/UIndirectList.C | 87 +++ .../Lists/UIndirectList/UIndirectList.H | 81 ++- .../Lists/UIndirectList/UIndirectListI.H | 11 + .../Lists/UIndirectList/UIndirectListIO.C | 4 +- src/OpenFOAM/containers/Lists/UList/UList.C | 135 +++- src/OpenFOAM/containers/Lists/UList/UList.H | 75 +- src/OpenFOAM/containers/Lists/UList/UListI.H | 59 +- .../fields/Fields/DynamicField/DynamicField.C | 24 +- .../fields/Fields/DynamicField/DynamicField.H | 56 +- .../Fields/DynamicField/DynamicFieldI.H | 282 ++++---- src/OpenFOAM/fields/Fields/Field/FieldM.H | 179 +++-- src/OpenFOAM/meshes/meshShapes/face/face.H | 7 +- src/OpenFOAM/meshes/meshShapes/face/faceI.H | 4 +- .../meshes/meshShapes/face/faceTemplates.C | 4 +- .../meshes/polyMesh/polyMeshFromShapeMesh.C | 6 +- .../primitiveMesh/primitiveMeshCellEdges.C | 6 +- src/OpenFOAM/primitives/Swap/Swap.H | 44 +- .../enrichedPatch/enrichedPatchPointPoints.C | 6 +- .../searchableBox/searchableBox.C | 2 +- .../searchableRotatedBox.C | 2 +- .../triSurfaceMesh/triSurfaceMesh.H | 2 +- .../triSurfaceSearch/triSurfaceSearch.C | 4 +- .../triSurfaceSearch/triSurfaceSearch.H | 2 +- wmake/rules/linux64GccKNL/c | 2 +- wmake/rules/linux64GccKNL/c++ | 2 +- wmake/rules/linux64IccKNL/c++ | 2 +- 74 files changed, 3205 insertions(+), 1169 deletions(-) delete mode 100644 applications/test/Field/Make/files delete mode 100644 applications/test/Field/Make/options delete mode 100644 applications/test/Field/Test-Field.C delete mode 100644 applications/test/Field/Test-Field.H delete mode 100644 applications/test/FixedList/fixedListFile create mode 100644 applications/test/FixedList2/Make/files create mode 100644 applications/test/FixedList2/Make/options create mode 100644 applications/test/FixedList2/Test-FixedList2.C create mode 100644 applications/test/List2/Make/files create mode 100644 applications/test/List2/Make/options create mode 100644 applications/test/List2/Test-List2.C create mode 100644 applications/test/ListOps2/Make/files create mode 100644 applications/test/ListOps2/Make/options create mode 100644 applications/test/ListOps2/Test-ListOps2.C create mode 100644 src/OpenFOAM/containers/Lists/UIndirectList/UIndirectList.C diff --git a/applications/test/DynamicList/Test-DynamicList.C b/applications/test/DynamicList/Test-DynamicList.C index c8e2ed4a93..ca3f4fc787 100644 --- a/applications/test/DynamicList/Test-DynamicList.C +++ b/applications/test/DynamicList/Test-DynamicList.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,7 +27,10 @@ Description #include "DynamicList.H" #include "IOstreams.H" +#include "FlatOutput.H" #include "ListOps.H" +#include "labelRange.H" +#include "labelIndList.H" using namespace Foam; @@ -44,15 +47,15 @@ void printInfo { Info<< " size=\"" << lst.size() << "\""; } - Info<< ">" << lst << "" << endl; + Info<< ">" << nl << flatOutput(lst) << nl << "" << endl; } -template +template void printInfo ( const word& tag, - const DynamicList& lst, + const DynamicList& lst, const bool showSize = false ) { @@ -62,7 +65,7 @@ void printInfo Info<< " size=\"" << lst.size() << "\" capacity=\"" << lst.capacity() << "\""; } - Info<< ">" << lst << "" << endl; + Info<< ">" << nl << flatOutput(lst) << nl << "" << endl; } @@ -71,7 +74,7 @@ void printInfo int main(int argc, char *argv[]) { - List> ldl(2); + List> ldl(2); ldl[0](0) = 0; ldl[0](2) = 2; @@ -89,7 +92,7 @@ int main(int argc, char *argv[]) ldl[1] = 3; - Info<< "" << ldl << "" << nl << "sizes: "; + Info<< "" << flatOutput(ldl) << "" << nl << "sizes: "; forAll(ldl, i) { Info<< " " << ldl[i].size() << "/" << ldl[i].capacity(); @@ -100,7 +103,7 @@ int main(int argc, char *argv[]) ll[0].transfer(ldl[0]); ll[1].transfer(ldl[1].shrink()); - Info<< "" << ldl << "" << nl << "sizes: "; + Info<< "" << flatOutput(ldl) << "" << nl << "sizes: "; forAll(ldl, i) { Info<< " " << ldl[i].size() << "/" << ldl[i].capacity(); @@ -111,18 +114,18 @@ int main(int argc, char *argv[]) // test the transfer between DynamicLists - DynamicList dlA + DynamicList