mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
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.
This commit is contained in:
@ -203,6 +203,7 @@ $(Pstreams)/PstreamBuffers.C
|
|||||||
dictionary = db/dictionary
|
dictionary = db/dictionary
|
||||||
$(dictionary)/dictionary.C
|
$(dictionary)/dictionary.C
|
||||||
$(dictionary)/dictionaryIO.C
|
$(dictionary)/dictionaryIO.C
|
||||||
|
$(dictionary)/dictionarySearch.C
|
||||||
|
|
||||||
entry = $(dictionary)/entry
|
entry = $(dictionary)/entry
|
||||||
$(entry)/entry.C
|
$(entry)/entry.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<class WcIterator, class ReIterator>
|
|
||||||
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 * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::dictionary::dictionary()
|
Foam::dictionary::dictionary()
|
||||||
@ -395,29 +244,7 @@ bool Foam::dictionary::found
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
if (hashedEntries_.found(keyword))
|
return csearch(keyword, recursive, patternMatch).found();
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -428,31 +255,7 @@ const Foam::entry* Foam::dictionary::lookupEntryPtr
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
auto iter = hashedEntries_.cfind(keyword);
|
return csearch(keyword, recursive, patternMatch).ptr();
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -463,36 +266,7 @@ Foam::entry* Foam::dictionary::lookupEntryPtr
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto iter = hashedEntries_.find(keyword);
|
return search(keyword, recursive, patternMatch).ptr();
|
||||||
|
|
||||||
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<dictionary&>(parent_).lookupEntryPtr
|
|
||||||
(
|
|
||||||
keyword,
|
|
||||||
recursive,
|
|
||||||
patternMatch
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -503,9 +277,9 @@ const Foam::entry& Foam::dictionary::lookupEntry
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
auto finder = csearch(keyword, recursive, patternMatch);
|
||||||
|
|
||||||
if (entryPtr == nullptr)
|
if (!finder.found())
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction
|
FatalIOErrorInFunction
|
||||||
(
|
(
|
||||||
@ -515,7 +289,7 @@ const Foam::entry& Foam::dictionary::lookupEntry
|
|||||||
<< exit(FatalIOError);
|
<< exit(FatalIOError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *entryPtr;
|
return finder.ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -537,29 +311,37 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
if ((keyword[0] == ':' || keyword[0] == '^'))
|
return csearchScoped(keyword, recursive, patternMatch).ptr();
|
||||||
{
|
}
|
||||||
// Go up to top level
|
|
||||||
const dictionary* dictPtr = this;
|
|
||||||
while (&dictPtr->parent_ != &dictionary::null)
|
|
||||||
{
|
|
||||||
dictPtr = &dictPtr->parent_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dictPtr->lookupScopedSubEntryPtr
|
|
||||||
(
|
bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry)
|
||||||
keyword.substr(1),
|
{
|
||||||
false,
|
if (keyword.size() < 2)
|
||||||
patternMatch
|
{
|
||||||
);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lookupScopedSubEntryPtr
|
// Drop leading '$' to get the var-name, already validated as word.
|
||||||
(
|
const word varName(keyword.substr(1), false);
|
||||||
keyword,
|
|
||||||
recursive,
|
// Lookup the variable name in the given dictionary
|
||||||
patternMatch
|
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
|
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);
|
const word varName(keyword.substr(1), false);
|
||||||
|
|
||||||
// Lookup the variable name in the given dictionary
|
// 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 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)
|
forAllConstIter(parent_type, addDict, iter)
|
||||||
{
|
{
|
||||||
@ -595,54 +382,30 @@ bool Foam::dictionary::substituteScopedKeyword
|
|||||||
bool Foam::dictionary::isDict(const word& keyword) const
|
bool Foam::dictionary::isDict(const word& keyword) const
|
||||||
{
|
{
|
||||||
// Find non-recursive with patterns
|
// Find non-recursive with patterns
|
||||||
const entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
return csearch(keyword, false, true).isDict();
|
||||||
|
|
||||||
if (entryPtr)
|
|
||||||
{
|
|
||||||
return entryPtr->isDict();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
|
const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
|
||||||
{
|
{
|
||||||
const entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
// Find non-recursive with patterns
|
||||||
|
return csearch(keyword, false, true).dictPtr();
|
||||||
if (entryPtr)
|
|
||||||
{
|
|
||||||
return &entryPtr->dict();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword)
|
Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword)
|
||||||
{
|
{
|
||||||
entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
// Find non-recursive with patterns
|
||||||
|
return search(keyword, false, true).dictPtr();
|
||||||
if (entryPtr)
|
|
||||||
{
|
|
||||||
return &entryPtr->dict();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
|
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
|
FatalIOErrorInFunction
|
||||||
(
|
(
|
||||||
@ -651,15 +414,17 @@ const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
|
|||||||
<< name()
|
<< name()
|
||||||
<< exit(FatalIOError);
|
<< exit(FatalIOError);
|
||||||
}
|
}
|
||||||
return entryPtr->dict();
|
|
||||||
|
return finder.dict();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
|
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
|
FatalIOErrorInFunction
|
||||||
(
|
(
|
||||||
@ -668,7 +433,8 @@ Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
|
|||||||
<< name()
|
<< name()
|
||||||
<< exit(FatalIOError);
|
<< exit(FatalIOError);
|
||||||
}
|
}
|
||||||
return entryPtr->dict();
|
|
||||||
|
return finder.dict();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -678,29 +444,35 @@ Foam::dictionary Foam::dictionary::subOrEmptyDict
|
|||||||
const bool mustRead
|
const bool mustRead
|
||||||
) const
|
) 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)
|
// Found and a sub-dictionary
|
||||||
{
|
return finder.dict();
|
||||||
FatalIOErrorInFunction
|
|
||||||
(
|
|
||||||
*this
|
|
||||||
) << "keyword " << keyword << " is undefined in dictionary "
|
|
||||||
<< name()
|
|
||||||
<< exit(FatalIOError);
|
|
||||||
return entryPtr->dict();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return dictionary(*this, dictionary(name() + '.' + keyword));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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 word& keyword
|
||||||
) const
|
) 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());
|
wordList keys(size());
|
||||||
|
|
||||||
label nKeys = 0;
|
label n = 0;
|
||||||
forAllConstIter(parent_type, *this, iter)
|
forAllConstIters(*this, iter)
|
||||||
{
|
{
|
||||||
keys[nKeys++] = iter().keyword();
|
keys[n++] = iter().keyword();
|
||||||
}
|
}
|
||||||
|
|
||||||
return keys;
|
return keys;
|
||||||
@ -746,15 +525,15 @@ Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns) const
|
|||||||
{
|
{
|
||||||
List<keyType> keys(size());
|
List<keyType> keys(size());
|
||||||
|
|
||||||
label nKeys = 0;
|
label n = 0;
|
||||||
forAllConstIter(parent_type, *this, iter)
|
forAllConstIters(*this, iter)
|
||||||
{
|
{
|
||||||
if (iter().keyword().isPattern() ? patterns : !patterns)
|
if (iter().keyword().isPattern() ? patterns : !patterns)
|
||||||
{
|
{
|
||||||
keys[nKeys++] = iter().keyword();
|
keys[n++] = iter().keyword();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keys.setSize(nKeys);
|
keys.setSize(n);
|
||||||
|
|
||||||
return keys;
|
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
|
void Foam::dictionary::add
|
||||||
(
|
(
|
||||||
const keyType& k,
|
const keyType& k,
|
||||||
const Foam::string& s,
|
const Foam::string& v,
|
||||||
bool overwrite
|
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
|
void Foam::dictionary::add
|
||||||
(
|
(
|
||||||
const keyType& k,
|
const keyType& k,
|
||||||
const dictionary& d,
|
const dictionary& v,
|
||||||
bool mergeEntry
|
bool mergeEntry
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
add(new dictionaryEntry(k, *this, d), mergeEntry);
|
add(new dictionaryEntry(k, *this, v), mergeEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::dictionary::set(entry* entryPtr)
|
void Foam::dictionary::set(entry* entryPtr)
|
||||||
{
|
{
|
||||||
// Find non-recursive with patterns
|
// 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
|
// Clear dictionary so merge acts like overwrite
|
||||||
if (existingPtr && existingPtr->isDict())
|
if (finder.isDict())
|
||||||
{
|
{
|
||||||
existingPtr->dict().clear();
|
finder.dict().clear();
|
||||||
}
|
}
|
||||||
add(entryPtr, true);
|
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));
|
set(new dictionaryEntry(k, *this, v));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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<regExp>(new regExp(newKeyword))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::dictionary::merge(const dictionary& dict)
|
bool Foam::dictionary::merge(const dictionary& dict)
|
||||||
{
|
{
|
||||||
// Check for assignment to self
|
|
||||||
if (this == &dict)
|
if (this == &dict)
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction(*this)
|
FatalIOErrorInFunction(*this)
|
||||||
@ -1041,7 +700,7 @@ bool Foam::dictionary::merge(const dictionary& dict)
|
|||||||
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
forAllConstIter(parent_type, dict, iter)
|
forAllConstIters(dict, iter)
|
||||||
{
|
{
|
||||||
auto fnd = hashedEntries_.find(iter().keyword());
|
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)
|
void Foam::dictionary::operator=(const dictionary& rhs)
|
||||||
{
|
{
|
||||||
// Check for assignment to self
|
|
||||||
if (this == &rhs)
|
if (this == &rhs)
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction(*this)
|
FatalIOErrorInFunction(*this)
|
||||||
@ -1126,7 +784,7 @@ void Foam::dictionary::operator=(const dictionary& rhs)
|
|||||||
// Create clones of the entries in the given dictionary
|
// Create clones of the entries in the given dictionary
|
||||||
// resetting the parentDict to this dictionary
|
// resetting the parentDict to this dictionary
|
||||||
|
|
||||||
forAllConstIter(parent_type, rhs, iter)
|
forAllConstIters(rhs, iter)
|
||||||
{
|
{
|
||||||
add(iter().clone(*this).ptr());
|
add(iter().clone(*this).ptr());
|
||||||
}
|
}
|
||||||
@ -1135,7 +793,6 @@ void Foam::dictionary::operator=(const dictionary& rhs)
|
|||||||
|
|
||||||
void Foam::dictionary::operator+=(const dictionary& rhs)
|
void Foam::dictionary::operator+=(const dictionary& rhs)
|
||||||
{
|
{
|
||||||
// Check for assignment to self
|
|
||||||
if (this == &rhs)
|
if (this == &rhs)
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction(*this)
|
FatalIOErrorInFunction(*this)
|
||||||
@ -1143,7 +800,7 @@ void Foam::dictionary::operator+=(const dictionary& rhs)
|
|||||||
<< abort(FatalIOError);
|
<< abort(FatalIOError);
|
||||||
}
|
}
|
||||||
|
|
||||||
forAllConstIter(parent_type, rhs, iter)
|
forAllConstIters(rhs, iter)
|
||||||
{
|
{
|
||||||
add(iter().clone(*this).ptr());
|
add(iter().clone(*this).ptr());
|
||||||
}
|
}
|
||||||
@ -1152,7 +809,6 @@ void Foam::dictionary::operator+=(const dictionary& rhs)
|
|||||||
|
|
||||||
void Foam::dictionary::operator|=(const dictionary& rhs)
|
void Foam::dictionary::operator|=(const dictionary& rhs)
|
||||||
{
|
{
|
||||||
// Check for assignment to self
|
|
||||||
if (this == &rhs)
|
if (this == &rhs)
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction(*this)
|
FatalIOErrorInFunction(*this)
|
||||||
@ -1160,7 +816,7 @@ void Foam::dictionary::operator|=(const dictionary& rhs)
|
|||||||
<< abort(FatalIOError);
|
<< abort(FatalIOError);
|
||||||
}
|
}
|
||||||
|
|
||||||
forAllConstIter(parent_type, rhs, iter)
|
forAllConstIters(rhs, iter)
|
||||||
{
|
{
|
||||||
if (!found(iter().keyword()))
|
if (!found(iter().keyword()))
|
||||||
{
|
{
|
||||||
@ -1172,7 +828,6 @@ void Foam::dictionary::operator|=(const dictionary& rhs)
|
|||||||
|
|
||||||
void Foam::dictionary::operator<<=(const dictionary& rhs)
|
void Foam::dictionary::operator<<=(const dictionary& rhs)
|
||||||
{
|
{
|
||||||
// Check for assignment to self
|
|
||||||
if (this == &rhs)
|
if (this == &rhs)
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction(*this)
|
FatalIOErrorInFunction(*this)
|
||||||
@ -1180,7 +835,7 @@ void Foam::dictionary::operator<<=(const dictionary& rhs)
|
|||||||
<< abort(FatalIOError);
|
<< abort(FatalIOError);
|
||||||
}
|
}
|
||||||
|
|
||||||
forAllConstIter(parent_type, rhs, iter)
|
forAllConstIters(rhs, iter)
|
||||||
{
|
{
|
||||||
set(iter().clone(*this).ptr());
|
set(iter().clone(*this).ptr());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,10 +41,13 @@ Description
|
|||||||
|
|
||||||
Note
|
Note
|
||||||
Within dictionaries, entries can be referenced by using the '$' syntax
|
Within dictionaries, entries can be referenced by using the '$' syntax
|
||||||
familiar from shell programming. A '.' separator is used when referencing
|
familiar from shell programming.
|
||||||
sub-dictionary entries. Leading '.' prefixes can be used to specify
|
A '.' separator is used when referencing sub-dictionary entries.
|
||||||
an entry from a parent directory. A leading ':' or '^' prefix specifies
|
Leading '.' prefixes can be used to specify an entry from a parent
|
||||||
starting from the top-level entry. For example,
|
dictionary.
|
||||||
|
An initial '^' anchor (or ':' for backward compatibility) specifies
|
||||||
|
starting from the top-level entry.
|
||||||
|
For example,
|
||||||
|
|
||||||
\verbatim
|
\verbatim
|
||||||
key1 val1;
|
key1 val1;
|
||||||
@ -70,6 +73,7 @@ Note
|
|||||||
SourceFiles
|
SourceFiles
|
||||||
dictionary.C
|
dictionary.C
|
||||||
dictionaryIO.C
|
dictionaryIO.C
|
||||||
|
dictionarySearch.C
|
||||||
|
|
||||||
SeeAlso
|
SeeAlso
|
||||||
- Foam::entry
|
- Foam::entry
|
||||||
@ -89,6 +93,7 @@ SeeAlso
|
|||||||
#include "HashTable.H"
|
#include "HashTable.H"
|
||||||
#include "wordList.H"
|
#include "wordList.H"
|
||||||
#include "className.H"
|
#include "className.H"
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -148,22 +153,20 @@ public:
|
|||||||
const word dictName() const
|
const word dictName() const
|
||||||
{
|
{
|
||||||
const word scopedName = name_.name();
|
const word scopedName = name_.name();
|
||||||
const std::string::size_type i = scopedName.rfind('.');
|
const auto i = scopedName.rfind('.');
|
||||||
|
|
||||||
if (i == std::string::npos)
|
if (i == std::string::npos)
|
||||||
{
|
{
|
||||||
return scopedName;
|
return scopedName;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return scopedName.substr(i+1);
|
||||||
return scopedName.substr(i+1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class dictionary Declaration
|
Class dictionary Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class dictionary
|
class dictionary
|
||||||
@ -171,15 +174,157 @@ class dictionary
|
|||||||
public dictionaryName,
|
public dictionaryName,
|
||||||
public IDLList<entry>
|
public IDLList<entry>
|
||||||
{
|
{
|
||||||
|
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<bool Const>
|
||||||
|
class Searcher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend dictionary;
|
||||||
|
|
||||||
|
//- The const/non-const type for the context and sub-dictionaries
|
||||||
|
typedef typename std::conditional
|
||||||
|
<Const, const dictionary, dictionary>::type dict_type;
|
||||||
|
|
||||||
|
//- The const/non-const type for entries
|
||||||
|
typedef typename std::conditional
|
||||||
|
<Const, const entry, entry>::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>&() const
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<const Searcher<!Const>*>(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//- Searcher with const access
|
||||||
|
typedef Searcher<true> const_searcher;
|
||||||
|
|
||||||
|
//- Searcher with non-const access
|
||||||
|
typedef Searcher<false> 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
|
// Private data
|
||||||
|
|
||||||
//- Report optional keywords and values if not present in dictionary
|
//- Report optional keywords and values if not present in dictionary
|
||||||
|
// Set/unset via an InfoSwitch
|
||||||
static bool writeOptionalEntries;
|
static bool writeOptionalEntries;
|
||||||
|
|
||||||
//- Parent dictionary
|
//- Parent dictionary
|
||||||
const dictionary& parent_;
|
const dictionary& parent_;
|
||||||
|
|
||||||
//- HashTable of the entries held on the IDLList for quick lookup
|
//- Quick lookup of the entries held on the IDLList
|
||||||
HashTable<entry*> hashedEntries_;
|
HashTable<entry*> hashedEntries_;
|
||||||
|
|
||||||
//- Entries of matching patterns
|
//- Entries of matching patterns
|
||||||
@ -196,28 +341,49 @@ class dictionary
|
|||||||
|
|
||||||
typedef DLList<entry*>::iterator pattern_iterator;
|
typedef DLList<entry*>::iterator pattern_iterator;
|
||||||
typedef DLList<entry*>::const_iterator pattern_const_iterator;
|
typedef DLList<entry*>::const_iterator pattern_const_iterator;
|
||||||
|
|
||||||
typedef DLList<autoPtr<regExp>>::iterator regexp_iterator;
|
typedef DLList<autoPtr<regExp>>::iterator regexp_iterator;
|
||||||
typedef DLList<autoPtr<regExp>>::const_iterator regexp_const_iterator;
|
typedef DLList<autoPtr<regExp>>::const_iterator regexp_const_iterator;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Find and return an entry data stream pointer if present
|
//- Search using a '.' for scoping.
|
||||||
// otherwise return nullptr. Allows scoping using '.'
|
// A leading dot means to use the parent dictionary.
|
||||||
const entry* lookupScopedSubEntryPtr
|
// 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,
|
const word& keyword,
|
||||||
bool recursive,
|
bool recursive,
|
||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const;
|
) 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:
|
public:
|
||||||
|
|
||||||
//- Declare friendship with the entry class for IO
|
|
||||||
friend class entry;
|
|
||||||
|
|
||||||
|
|
||||||
// Declare name of the class and its debug switch
|
// Declare name of the class and its debug switch
|
||||||
ClassName("dictionary");
|
ClassName("dictionary");
|
||||||
|
|
||||||
@ -234,7 +400,7 @@ public:
|
|||||||
explicit dictionary(const fileName& name);
|
explicit dictionary(const fileName& name);
|
||||||
|
|
||||||
//- Construct given the entry name, parent dictionary and Istream,
|
//- Construct given the entry name, parent dictionary and Istream,
|
||||||
// reading entries until lastEntry or EOF
|
// reading entries until EOF
|
||||||
dictionary
|
dictionary
|
||||||
(
|
(
|
||||||
const fileName& name,
|
const fileName& name,
|
||||||
@ -251,7 +417,7 @@ public:
|
|||||||
dictionary(Istream& is, const bool keepHeader);
|
dictionary(Istream& is, const bool keepHeader);
|
||||||
|
|
||||||
//- Construct as copy given the parent dictionary
|
//- 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
|
//- Construct top-level dictionary as copy
|
||||||
dictionary(const dictionary& dict);
|
dictionary(const dictionary& dict);
|
||||||
@ -303,284 +469,413 @@ public:
|
|||||||
tokenList tokens() const;
|
tokenList tokens() const;
|
||||||
|
|
||||||
|
|
||||||
// Search and lookup
|
// Search and lookup
|
||||||
|
|
||||||
//- Search dictionary for given keyword
|
//- Search dictionary for given keyword
|
||||||
// If recursive, search parent dictionaries
|
// If recursive, search parent dictionaries
|
||||||
// If patternMatch, use regular expressions
|
// If patternMatch, use regular expressions
|
||||||
bool found
|
// (default search: non-recursive with patterns).
|
||||||
(
|
bool found
|
||||||
const word& keyword,
|
(
|
||||||
bool recursive = false,
|
const word& keyword,
|
||||||
bool patternMatch = true
|
bool recursive = false,
|
||||||
) const;
|
bool patternMatch = true
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Find and return an entry data stream pointer if present
|
//- Find and return an entry data stream pointer if present
|
||||||
// otherwise return nullptr.
|
// otherwise return nullptr.
|
||||||
// If recursive, search parent dictionaries.
|
// If recursive, search parent dictionaries.
|
||||||
// If patternMatch, use regular expressions
|
// If patternMatch, use regular expressions
|
||||||
const entry* lookupEntryPtr
|
const entry* lookupEntryPtr
|
||||||
(
|
(
|
||||||
const word& keyword,
|
const word& keyword,
|
||||||
bool recursive,
|
bool recursive,
|
||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Find and return an entry data stream pointer for manipulation
|
//- Find and return an entry data stream pointer for manipulation
|
||||||
// if present otherwise return nullptr.
|
// if present otherwise return nullptr.
|
||||||
// If recursive, search parent dictionaries.
|
// If recursive, search parent dictionaries.
|
||||||
// If patternMatch, use regular expressions.
|
// If patternMatch, use regular expressions.
|
||||||
entry* lookupEntryPtr
|
entry* lookupEntryPtr
|
||||||
(
|
(
|
||||||
const word& keyword,
|
const word& keyword,
|
||||||
bool recursive,
|
bool recursive,
|
||||||
bool patternMatch
|
bool patternMatch
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Find and return an entry data stream if present otherwise error.
|
//- Find and return an entry data stream if present otherwise error.
|
||||||
// If recursive, search parent dictionaries.
|
// If recursive, search parent dictionaries.
|
||||||
// If patternMatch, use regular expressions.
|
// If patternMatch, use regular expressions.
|
||||||
const entry& lookupEntry
|
const entry& lookupEntry
|
||||||
(
|
(
|
||||||
const word& keyword,
|
const word& keyword,
|
||||||
bool recursive,
|
bool recursive,
|
||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Find and return an entry data stream
|
//- Find and return an entry data stream
|
||||||
// If recursive, search parent dictionaries.
|
// If recursive, search parent dictionaries.
|
||||||
// If patternMatch, use regular expressions.
|
// If patternMatch, use regular expressions.
|
||||||
ITstream& lookup
|
// (default search: non-recursive with patterns).
|
||||||
(
|
ITstream& lookup
|
||||||
const word& keyword,
|
(
|
||||||
bool recursive = false,
|
const word& keyword,
|
||||||
bool patternMatch = true
|
bool recursive = false,
|
||||||
) const;
|
bool patternMatch = true
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Find and return a T,
|
//- Find and return a T,
|
||||||
// if not found throw a fatal error.
|
// if not found throw a fatal error.
|
||||||
// If recursive, search parent dictionaries.
|
// If recursive, search parent dictionaries.
|
||||||
// If patternMatch, use regular expressions.
|
// If patternMatch, use regular expressions.
|
||||||
template<class T>
|
// (default search: non-recursive with patterns).
|
||||||
T lookupType
|
template<class T>
|
||||||
(
|
T lookupType
|
||||||
const word&,
|
(
|
||||||
bool recursive=false,
|
const word& keyword,
|
||||||
bool patternMatch=true
|
bool recursive = false,
|
||||||
) const;
|
bool patternMatch = true
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Find and return a T, or return the given default value
|
//- Find and return a T, or return the given default value
|
||||||
// If recursive, search parent dictionaries.
|
// If recursive, search parent dictionaries.
|
||||||
// If patternMatch, use regular expressions.
|
// If patternMatch, use regular expressions.
|
||||||
template<class T>
|
// (default search: non-recursive with patterns).
|
||||||
T lookupOrDefault
|
template<class T>
|
||||||
(
|
T lookupOrDefault
|
||||||
const word& keyword,
|
(
|
||||||
const T& deflt,
|
const word& keyword,
|
||||||
bool recursive = false,
|
const T& deflt,
|
||||||
bool patternMatch = true
|
bool recursive = false,
|
||||||
) const;
|
bool patternMatch = true
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Find and return a T, if not found return the given
|
//- Find and return a T, if not found return the default value
|
||||||
// default value, and add to dictionary.
|
// and add it to dictionary.
|
||||||
// If recursive, search parent dictionaries.
|
// Default search: non-recursive with patterns.
|
||||||
// If patternMatch, use regular expressions.
|
//
|
||||||
template<class T>
|
// \param recursive search parent dictionaries
|
||||||
T lookupOrAddDefault
|
// \param patternMatch use regular expressions
|
||||||
(
|
template<class T>
|
||||||
const word& keyword,
|
T lookupOrAddDefault
|
||||||
const T& deflt,
|
(
|
||||||
bool recursive = false,
|
const word& keyword,
|
||||||
bool patternMatch = true
|
const T& deflt,
|
||||||
);
|
bool recursive = false,
|
||||||
|
bool patternMatch = true
|
||||||
|
);
|
||||||
|
|
||||||
//- Find an entry if present, and assign to T
|
//- Find an entry if present, and assign to T val.
|
||||||
// Returns true if the entry was found.
|
// Default search: non-recursive with patterns.
|
||||||
// If recursive, search parent dictionaries.
|
//
|
||||||
// If patternMatch, use regular expressions.
|
// \param val the value to read
|
||||||
template<class T>
|
// \param recursive search parent dictionaries
|
||||||
bool readIfPresent
|
// \param patternMatch use regular expressions
|
||||||
(
|
//
|
||||||
const word& keyword,
|
// \return true if the entry was found.
|
||||||
T& val,
|
template<class T>
|
||||||
bool recursive = false,
|
bool readIfPresent
|
||||||
bool patternMatch = true
|
(
|
||||||
) const;
|
const word& keyword,
|
||||||
|
T& val,
|
||||||
|
bool recursive = false,
|
||||||
|
bool patternMatch = true
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Find and return an entry data stream pointer if present
|
//- Find and return an entry pointer if present, or return a nullptr.
|
||||||
// otherwise return nullptr. Allows scoping using '.'.
|
// Allows scoping using '.'.
|
||||||
// Special handling for ':' at start of keyword and '..'.
|
// Special handling for an absolute anchor (^) at start of the keyword
|
||||||
const entry* lookupScopedEntryPtr
|
// and for '..' to ascend into the parent dictionaries.
|
||||||
(
|
//
|
||||||
const word& keyword,
|
// \param recursive search parent dictionaries
|
||||||
bool recursive,
|
// \param patternMatch use regular expressions
|
||||||
bool patternMatch
|
const entry* lookupScopedEntryPtr
|
||||||
) const;
|
(
|
||||||
|
const word& keyword,
|
||||||
|
bool recursive,
|
||||||
|
bool patternMatch
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Check if entry is a sub-dictionary
|
//- Check if entry exists and is a sub-dictionary.
|
||||||
bool isDict(const word& keyword) const;
|
// (search type: non-recursive with patterns)
|
||||||
|
bool isDict(const word& keyword) const;
|
||||||
|
|
||||||
//- Find and return a sub-dictionary pointer if present
|
//- Find and return a sub-dictionary pointer if present
|
||||||
// otherwise return nullptr.
|
// (and a sub-dictionary) otherwise return nullptr.
|
||||||
const dictionary* subDictPtr(const word& keyword) const;
|
// (search type: non-recursive with patterns)
|
||||||
|
const dictionary* subDictPtr(const word& keyword) const;
|
||||||
|
|
||||||
//- Find and return a sub-dictionary pointer if present
|
//- Find and return a sub-dictionary pointer if present
|
||||||
// otherwise return nullptr.
|
// (and a sub-dictionary) otherwise return nullptr.
|
||||||
dictionary* subDictPtr(const word& keyword);
|
//
|
||||||
|
// Search type: non-recursive with patterns.
|
||||||
|
dictionary* subDictPtr(const word& keyword);
|
||||||
|
|
||||||
//- Find and return a sub-dictionary
|
//- Find and return a sub-dictionary.
|
||||||
const dictionary& subDict(const word& keyword) const;
|
// 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
|
//- Find and return a sub-dictionary for manipulation.
|
||||||
dictionary& subDict(const word& keyword);
|
// 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
|
//- Find and return a sub-dictionary as a copy, otherwise return
|
||||||
// return an empty dictionary if the sub-dictionary does not exist
|
// an empty dictionary.
|
||||||
dictionary subOrEmptyDict
|
// Warn if the entry exists but is not a sub-dictionary.
|
||||||
(
|
// (search type: non-recursive with patterns)
|
||||||
const word& keyword,
|
dictionary subOrEmptyDict
|
||||||
const bool mustRead = false
|
(
|
||||||
) const;
|
const word& keyword,
|
||||||
|
const bool mustRead = false
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Find and return a sub-dictionary if found
|
//- Find and return a sub-dictionary, otherwise return this dictionary.
|
||||||
// otherwise return this dictionary
|
// Warn if the entry exists but is not a sub-dictionary.
|
||||||
const dictionary& optionalSubDict(const word&) const;
|
// (search type: non-recursive with patterns)
|
||||||
|
const dictionary& optionalSubDict(const word& keyword) const;
|
||||||
|
|
||||||
//- Return the table of contents
|
//- Return the table of contents
|
||||||
wordList toc() const;
|
wordList toc() const;
|
||||||
|
|
||||||
//- Return the sorted table of contents
|
//- Return the sorted table of contents
|
||||||
wordList sortedToc() const;
|
wordList sortedToc() const;
|
||||||
|
|
||||||
//- Return table of contents sorted using the specified comparator
|
//- Return table of contents sorted using the specified comparator
|
||||||
template<class Compare>
|
template<class Compare>
|
||||||
wordList sortedToc(const Compare& comp) const;
|
wordList sortedToc(const Compare& comp) const;
|
||||||
|
|
||||||
//- Return the list of available keys or patterns
|
//- Return the list of available keys or patterns
|
||||||
List<keyType> keys(bool patterns = false) const;
|
List<keyType> keys(bool patterns = false) const;
|
||||||
|
|
||||||
|
|
||||||
// Editing
|
// Editing
|
||||||
|
|
||||||
//- Substitute the given keyword prepended by '$' with the
|
//- Substitute the given keyword (which is prefixed by '$')
|
||||||
// corresponding sub-dictionary entries
|
// with the corresponding sub-dictionary entries
|
||||||
bool substituteKeyword(const word& keyword, bool mergeEntry=false);
|
bool substituteKeyword
|
||||||
|
(
|
||||||
|
const word& keyword,
|
||||||
|
bool mergeEntry = false
|
||||||
|
);
|
||||||
|
|
||||||
//- Substitute the given scoped keyword prepended by '$' with the
|
//- Substitute the given scoped keyword (which is prefixed by '$')
|
||||||
// corresponding sub-dictionary entries
|
// with the corresponding sub-dictionary entries
|
||||||
bool substituteScopedKeyword
|
bool substituteScopedKeyword
|
||||||
(
|
(
|
||||||
const word& keyword,
|
const word& keyword,
|
||||||
bool mergeEntry=false
|
bool mergeEntry = false
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Add a new entry
|
//- Add a new entry
|
||||||
// With the merge option, dictionaries are interwoven and
|
// With the merge option, dictionaries are interwoven and
|
||||||
// primitive entries are overwritten
|
// primitive entries are overwritten
|
||||||
bool add(entry* entryPtr, bool mergeEntry=false);
|
bool add(entry* entryPtr, bool mergeEntry=false);
|
||||||
|
|
||||||
//- Add an entry
|
//- Add an entry
|
||||||
// With the merge option, dictionaries are interwoven and
|
// With the merge option, dictionaries are interwoven and
|
||||||
// primitive entries are overwritten
|
// primitive entries are overwritten
|
||||||
void add(const entry& e, bool mergeEntry=false);
|
void add(const entry& e, bool mergeEntry=false);
|
||||||
|
|
||||||
//- Add a word entry
|
//- Add a word entry
|
||||||
// optionally overwrite an existing entry
|
// optionally overwrite an existing entry
|
||||||
void add(const keyType& k, const word& w, bool overwrite=false);
|
void add(const keyType& k, const word& v, bool overwrite=false);
|
||||||
|
|
||||||
//- Add a string entry
|
//- Add a string entry
|
||||||
// optionally overwrite an existing entry
|
// optionally overwrite an existing entry
|
||||||
void add(const keyType& k, const string& s, bool overwrite=false);
|
void add(const keyType& k, const string& v, bool overwrite=false);
|
||||||
|
|
||||||
//- Add a label entry
|
//- Add a label entry
|
||||||
// optionally overwrite an existing entry
|
// optionally overwrite an existing entry
|
||||||
void add(const keyType&, const label l, bool overwrite=false);
|
void add(const keyType& k, const label v, bool overwrite=false);
|
||||||
|
|
||||||
//- Add a scalar entry
|
//- Add a scalar entry
|
||||||
// optionally overwrite an existing entry
|
// optionally overwrite an existing entry
|
||||||
void add(const keyType&, const scalar s, bool overwrite=false);
|
void add(const keyType& k, const scalar v, bool overwrite=false);
|
||||||
|
|
||||||
//- Add a dictionary entry
|
//- Add a dictionary entry
|
||||||
// optionally merge with an existing sub-dictionary
|
// optionally merge with an existing sub-dictionary
|
||||||
void add
|
void add
|
||||||
(
|
(
|
||||||
const keyType& k,
|
const keyType& k,
|
||||||
const dictionary& d,
|
const dictionary& d,
|
||||||
bool mergeEntry = false
|
bool mergeEntry = false
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Add a T entry
|
//- Add a T entry
|
||||||
// optionally overwrite an existing entry
|
// optionally overwrite an existing entry
|
||||||
template<class T>
|
template<class T>
|
||||||
void add(const keyType& k, const T& t, bool overwrite=false);
|
void add(const keyType& k, const T& v, bool overwrite=false);
|
||||||
|
|
||||||
//- Assign a new entry, overwrite any existing entry
|
//- Assign a new entry, overwrite any existing entry
|
||||||
void set(entry* entryPtr);
|
void set(entry* entryPtr);
|
||||||
|
|
||||||
//- Assign a new entry, overwrite any existing entry
|
//- Assign a new entry, overwrite any existing entry
|
||||||
void set(const entry& e);
|
void set(const entry& e);
|
||||||
|
|
||||||
//- Assign a dictionary entry, overwrite any existing entry
|
//- Assign a dictionary entry, overwrite any existing entry
|
||||||
void set(const keyType& k, const dictionary& d);
|
void set(const keyType& k, const dictionary& v);
|
||||||
|
|
||||||
//- Assign a T entry, overwrite any existing entry
|
//- Assign a T entry, overwrite any existing entry
|
||||||
template<class T>
|
template<class T>
|
||||||
void set(const keyType& k, const T& t);
|
void set(const keyType& k, const T& v);
|
||||||
|
|
||||||
//- Remove an entry specified by keyword
|
//- Remove an entry specified by keyword
|
||||||
bool remove(const word& Keyword);
|
bool remove(const word& keyword);
|
||||||
|
|
||||||
//- Change the keyword for an entry,
|
//- Change the keyword for an entry,
|
||||||
// optionally forcing overwrite of an existing entry
|
// optionally forcing overwrite of an existing entry
|
||||||
bool changeKeyword
|
bool changeKeyword
|
||||||
(
|
(
|
||||||
const keyType& oldKeyword,
|
const keyType& oldKeyword,
|
||||||
const keyType& newKeyword,
|
const keyType& newKeyword,
|
||||||
bool forceOverwrite=false
|
bool forceOverwrite=false
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Merge entries from the given dictionary.
|
//- Merge entries from the given dictionary.
|
||||||
// Also merge sub-dictionaries as required.
|
// Also merge sub-dictionaries as required.
|
||||||
bool merge(const dictionary& dict);
|
bool merge(const dictionary& dict);
|
||||||
|
|
||||||
//- Clear the dictionary
|
//- Clear the dictionary
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
//- Transfer the contents of the argument and annul the argument.
|
//- Transfer the contents of the argument and annul the argument.
|
||||||
void transfer(dictionary& dict);
|
void transfer(dictionary& dict);
|
||||||
|
|
||||||
//- Transfer contents to the Xfer container
|
//- Transfer contents to the Xfer container
|
||||||
Xfer<dictionary> xfer();
|
Xfer<dictionary> xfer();
|
||||||
|
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
|
|
||||||
//- Read dictionary from Istream
|
//- Read dictionary from Istream
|
||||||
bool read(Istream& is);
|
bool read(Istream& is);
|
||||||
|
|
||||||
//- Read dictionary from Istream, optionally keeping the header
|
//- Read dictionary from Istream, optionally keeping the header
|
||||||
bool read(Istream& is, const bool keepHeader);
|
bool read(Istream& is, const bool keepHeader);
|
||||||
|
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
|
|
||||||
//- Write sub-dictionary with the keyword as its header
|
//- Write sub-dictionary with the keyword as its header
|
||||||
void writeEntry(const keyType& keyword, Ostream& os) const;
|
void writeEntry(const keyType& keyword, Ostream& os) const;
|
||||||
|
|
||||||
//- Write dictionary entries.
|
//- Write dictionary entries.
|
||||||
// Optionally with extra new line between entries for
|
// Optionally with extra new line between entries for
|
||||||
// "top-level" dictionaries
|
// "top-level" dictionaries
|
||||||
void writeEntries(Ostream& os, const bool extraNewLine=false) const;
|
void writeEntries(Ostream& os, const bool extraNewLine=false) const;
|
||||||
|
|
||||||
//- Write dictionary, normally with sub-dictionary formatting
|
//- Write dictionary, normally with sub-dictionary formatting
|
||||||
void write(Ostream& os, const bool subDict=true) const;
|
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
|
// 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;
|
ITstream& operator[](const word& keyword) const;
|
||||||
|
|
||||||
|
//- Copy assignment
|
||||||
void operator=(const dictionary& rhs);
|
void operator=(const dictionary& rhs);
|
||||||
|
|
||||||
//- Include entries from the given dictionary.
|
//- Include entries from the given dictionary.
|
||||||
|
|||||||
@ -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 * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Istream Operator * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::Istream& Foam::operator>>(Istream& is, dictionary& dict)
|
Foam::Istream& Foam::operator>>(Istream& is, dictionary& dict)
|
||||||
|
|||||||
719
src/OpenFOAM/db/dictionary/dictionarySearch.C
Normal file
719
src/OpenFOAM/db/dictionary/dictionarySearch.C
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#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<class WcIterator, class ReIterator>
|
||||||
|
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<std::string>(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<const searcher&>(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<const searcher&>(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<dictionary*>(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<dictionary*>(&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<dictionary*>(&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<regExp>(new regExp(newKeyword))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -43,9 +43,9 @@ T Foam::dictionary::lookupType
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
auto finder = csearch(keyword, recursive, patternMatch);
|
||||||
|
|
||||||
if (entryPtr == nullptr)
|
if (!finder.found())
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction
|
FatalIOErrorInFunction
|
||||||
(
|
(
|
||||||
@ -55,7 +55,7 @@ T Foam::dictionary::lookupType
|
|||||||
<< exit(FatalIOError);
|
<< exit(FatalIOError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pTraits<T>(entryPtr->stream());
|
return pTraits<T>(finder.ptr()->stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -68,11 +68,11 @@ T Foam::dictionary::lookupOrDefault
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
auto finder = csearch(keyword, recursive, patternMatch);
|
||||||
|
|
||||||
if (entryPtr)
|
if (finder.found())
|
||||||
{
|
{
|
||||||
return pTraits<T>(entryPtr->stream());
|
return pTraits<T>(finder.ptr()->stream());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -98,11 +98,11 @@ T Foam::dictionary::lookupOrAddDefault
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
auto finder = csearch(keyword, recursive, patternMatch);
|
||||||
|
|
||||||
if (entryPtr)
|
if (finder.found())
|
||||||
{
|
{
|
||||||
return pTraits<T>(entryPtr->stream());
|
return pTraits<T>(finder.ptr()->stream());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -129,11 +129,11 @@ bool Foam::dictionary::readIfPresent
|
|||||||
bool patternMatch
|
bool patternMatch
|
||||||
) const
|
) 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;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -152,16 +152,16 @@ bool Foam::dictionary::readIfPresent
|
|||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
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<class T>
|
template<class T>
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -224,17 +224,12 @@ bool Foam::entry::New
|
|||||||
const word varName = keyword.substr(1);
|
const word varName = keyword.substr(1);
|
||||||
|
|
||||||
// Lookup the variable name in the given dictionary
|
// Lookup the variable name in the given dictionary
|
||||||
const entry* ePtr = parentDict.lookupScopedEntryPtr
|
const auto finder = parentDict.csearchScoped(varName, true, true);
|
||||||
(
|
|
||||||
varName,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ePtr)
|
if (finder.found())
|
||||||
{
|
{
|
||||||
// Read as primitiveEntry
|
// Read as primitiveEntry
|
||||||
const keyType newKeyword(ePtr->stream());
|
const keyType newKeyword(finder.ptr()->stream());
|
||||||
|
|
||||||
return parentDict.add
|
return parentDict.add
|
||||||
(
|
(
|
||||||
@ -285,14 +280,9 @@ bool Foam::entry::New
|
|||||||
bool mergeEntry = false;
|
bool mergeEntry = false;
|
||||||
|
|
||||||
// See (using exact match) if entry already present
|
// See (using exact match) if entry already present
|
||||||
entry* existingPtr = parentDict.lookupEntryPtr
|
auto finder = parentDict.search(keyword, false, false);
|
||||||
(
|
|
||||||
keyword,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingPtr)
|
if (finder.found())
|
||||||
{
|
{
|
||||||
if (mode == inputMode::MERGE)
|
if (mode == inputMode::MERGE)
|
||||||
{
|
{
|
||||||
@ -301,9 +291,9 @@ bool Foam::entry::New
|
|||||||
else if (mode == inputMode::OVERWRITE)
|
else if (mode == inputMode::OVERWRITE)
|
||||||
{
|
{
|
||||||
// Clear existing dictionary so merge acts like overwrite
|
// Clear existing dictionary so merge acts like overwrite
|
||||||
if (existingPtr->isDict())
|
if (finder.isDict())
|
||||||
{
|
{
|
||||||
existingPtr->dict().clear();
|
finder.dict().clear();
|
||||||
}
|
}
|
||||||
mergeEntry = true;
|
mergeEntry = true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user