From 01083dd8775dbefd8ba96453ff8caa4ee5e1dcc6 Mon Sep 17 00:00:00 2001 From: Henry Weller Date: Fri, 2 Dec 2016 12:23:17 +0000 Subject: [PATCH] dictionary: Handle the distinction between '.' as a keyword character and a scope operator Patch contributed by Mattijs Janssens Resolves bug-report http://bugs.openfoam.org/view.php?id=2358 --- src/OpenFOAM/db/dictionary/dictionary.C | 220 ++++++++++++++---------- src/OpenFOAM/db/dictionary/dictionary.H | 12 +- 2 files changed, 143 insertions(+), 89 deletions(-) diff --git a/src/OpenFOAM/db/dictionary/dictionary.C b/src/OpenFOAM/db/dictionary/dictionary.C index d039b07ca..49cbbbb23 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.C +++ b/src/OpenFOAM/db/dictionary/dictionary.C @@ -46,6 +46,131 @@ namespace Foam // * * * * * * * * * * * * * 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 2nd '.' found + + const dictionary* dictPtr = this; + + string::size_type begVar = dotPos + 1; + string::const_iterator iter = keyword.begin() + begVar; + string::size_type endVar = begVar; + while (iter != keyword.end() && *iter == '.') + { + ++iter; + ++endVar; + + // Go to parent + if (&dictPtr->parent_ == &dictionary::null) + { + FatalIOErrorInFunction + ( + *this + ) << "No parent of current dictionary" + << " when searching for " + << keyword.substr(begVar, keyword.size()-begVar) + << exit(FatalIOError); + } + dictPtr = &dictPtr->parent_; + } + + return dictPtr->lookupScopedSubEntryPtr + ( + keyword.substr(endVar), + false, + patternMatch + ); + } + else + { + // Extract the first word + word firstWord = keyword.substr(0, dotPos); + + const entry* entPtr = lookupScopedSubEntryPtr + ( + firstWord, + false, //recursive + 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 + + string::size_type nextDotPos = keyword.find + ( + '.', + dotPos+1 + ); + + while (true) + { + const entry* subEntPtr = lookupEntryPtr + ( + keyword.substr(0, nextDotPos), + false, //recursive, + patternMatch + ); + if (nextDotPos == string::npos) + { + // Parsed the whole word. Return entry or null. + return subEntPtr; + } + + if (subEntPtr && subEntPtr->isDict()) + { + return subEntPtr->dict().lookupScopedSubEntryPtr + ( + keyword.substr + ( + nextDotPos, + keyword.size()-nextDotPos + ), + false, + patternMatch + ); + } + + nextDotPos = keyword.find('.', nextDotPos+1); + } + } + + if (entPtr->isDict()) + { + return entPtr->dict().lookupScopedSubEntryPtr + ( + keyword.substr(dotPos, keyword.size()-dotPos), + false, + patternMatch + ); + } + else + { + return nullptr; + } + } + } +} + + bool Foam::dictionary::findInPatterns ( const bool patternMatch, @@ -475,7 +600,7 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr } // At top. Recurse to find entries - return dictPtr->lookupScopedEntryPtr + return dictPtr->lookupScopedSubEntryPtr ( keyword.substr(1, keyword.size()-1), false, @@ -484,93 +609,12 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr } else { - 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 2nd '.' found - - const dictionary* dictPtr = this; - - string::size_type begVar = dotPos + 1; - string::const_iterator iter = keyword.begin() + begVar; - string::size_type endVar = begVar; - while - ( - iter != keyword.end() - && *iter == '.' - ) - { - ++iter; - ++endVar; - - // Go to parent - if (&dictPtr->parent_ == &dictionary::null) - { - FatalIOErrorInFunction - ( - *this - ) << "No parent of current dictionary" - << " when searching for " - << keyword.substr(begVar, keyword.size()-begVar) - << exit(FatalIOError); - } - dictPtr = &dictPtr->parent_; - } - - return dictPtr->lookupScopedEntryPtr - ( - keyword.substr(endVar), - false, - patternMatch - ); - } - else - { - // Extract the first word - word firstWord = keyword.substr(0, dotPos); - - const entry* entPtr = lookupScopedEntryPtr - ( - firstWord, - false, //recursive - patternMatch - ); - - if (!entPtr) - { - FatalIOErrorInFunction - ( - *this - ) << "keyword " << firstWord - << " is undefined in dictionary " - << name() << endl - << "Valid keywords are " << keys() - << exit(FatalIOError); - } - - if (entPtr->isDict()) - { - return entPtr->dict().lookupScopedEntryPtr - ( - keyword.substr(dotPos, keyword.size()-dotPos), - false, - patternMatch - ); - } - else - { - return nullptr; - } - } - } + return lookupScopedSubEntryPtr + ( + keyword, + recursive, + patternMatch + ); } } diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H index 235a5aefc..d42a934ad 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.H +++ b/src/OpenFOAM/db/dictionary/dictionary.H @@ -161,6 +161,15 @@ class dictionary // Private Member Functions + //- Find and return an entry data stream pointer if present + // otherwise return nullptr. Allows scoping using '.' + const entry* lookupScopedSubEntryPtr + ( + const word&, + bool recursive, + bool patternMatch + ) const; + //- Search patterns table for exact match or regular expression match bool findInPatterns ( @@ -364,7 +373,8 @@ public: ) const; //- Find and return an entry data stream pointer if present - // otherwise return nullptr. Allows scoping using '.' + // otherwise return nullptr. Allows scoping using '.'. + // Special handling for ':' at start of keyword and '..'. const entry* lookupScopedEntryPtr ( const word&,