38 template<
class WcIterator,
class ReIterator>
41 const bool patternMatch,
52 ? reIter()->
match(keyword)
53 : wcIter()->keyword() == keyword
74 enum keyType::option matchOpt
77 auto scopePos = keyword.find(
'.');
82 return csearch(keyword, matchOpt);
96 string::const_iterator it = keyword.begin()+1;
97 it != keyword.end() && *it ==
'.';
104 dictPtr = &dictPtr->parent_;
109 <<
"No parent of current dictionary when searching for "
117 return dictPtr->csearchDotScoped
119 keyword.substr(scopePos),
127 keyword.substr(0, scopePos),
137 while (!finder.isDict())
139 scopePos = keyword.find(
'.', scopePos+1);
142 finder =
csearch(keyword.substr(0, scopePos), matchOpt);
154 return finder.dict().csearchDotScoped
156 keyword.substr(scopePos),
175 const dictionary* dictPtr =
this;
177 const auto slash = keyword.find(
'/');
183 return csearch(keyword, matchOpt);
191 dictPtr = &dictPtr->parent_;
196 auto cmpts = stringOps::split<std::string>(keyword,
'/');
197 auto remaining = cmpts.size();
199 for (
const auto& cmpt : cmpts)
207 else if (cmpt ==
"..")
212 dictPtr = &dictPtr->parent_;
217 <<
"No parent of current dictionary when searching for "
218 << keyword <<
" at " << cmpt
228 auto finder = dictPtr->csearch(key, matchOpt);
237 dictPtr = finder.dictPtr();
241 return const_searcher(dictPtr);
258 return const_searcher(dictPtr);
272 auto iter = hashedEntries_.cfind(keyword);
276 finder.
set(iter.val());
282 auto wcLink = patterns_.cbegin();
283 auto reLink = regexps_.cbegin();
286 if (findInPatterns(
true, keyword, wcLink, reLink))
295 return parent_.csearch(keyword, matchOpt);
308 return csearch(keyword, matchOpt);
320 return static_cast<const searcher&
>(finder);
332 return csearchSlashScoped(keyword, matchOpt);
335 if (keyword[0] ==
':' || keyword[0] ==
'^')
344 dictPtr = &dictPtr->parent_;
347 return dictPtr->csearchDotScoped(keyword.substr(1), matchOpt);
350 return csearchDotScoped(keyword, matchOpt);
360 return csearchScoped(keyword, matchOpt);
372 return static_cast<const searcher&
>(finder);
382 if (dictPath.empty())
388 if (dictPath[0] ==
'/')
394 dictPtr = &dictPtr->parent_;
402 for (
const word& cmpt : dictCmpts)
408 else if (cmpt ==
"..")
413 dictPtr = &dictPtr->parent_;
418 <<
"No parent for dictionary while searching "
430 auto iter = dictPtr->hashedEntries_.cfind(cmpt);
434 const entry *eptr = iter.val();
443 <<
"Found entry '" << cmpt
444 <<
"' but not a dictionary, while searching scoped"
468 return cfindScopedDict(dictPath);
477 const dictionary* ptr = cfindScopedDict(dictPath);
485 if (dictPath.empty())
491 if (dictPath[0] ==
'/')
497 dictPtr =
const_cast<dictionary*
>(&dictPtr->parent_);
501 std::string
path(dictPath);
505 for (
const auto& cmpt : dictCmpts)
511 else if (cmpt ==
"..")
516 dictPtr =
const_cast<dictionary*
>(&dictPtr->parent_);
521 <<
"No parent for dictionary while searching "
533 const word cmptName(cmpt.str(),
false);
535 auto iter = dictPtr->hashedEntries_.find(cmptName);
539 entry *eptr = iter.val();
548 <<
"Cannot create sub-dictionary entry '" << cmptName
549 <<
"' - a non-dictionary entry is in the way"
550 <<
nl <<
"Encountered in scope" <<
nl
565 if (dictPtr->
add(eptr,
false))
584 auto iter = hashedEntries_.find(keyword);
589 auto wcLink = patterns_.begin();
590 auto reLink = regexps_.begin();
593 if (findInPatterns(
false, keyword, wcLink, reLink))
595 patterns_.remove(wcLink);
596 regexps_.remove(reLink);
599 parent_type::remove(iter());
601 hashedEntries_.erase(iter);
618 if (oldKeyword == newKeyword)
624 auto iter = hashedEntries_.find(oldKeyword);
631 if (iter()->keyword().isPattern())
634 <<
"Old keyword " << oldKeyword <<
" is a pattern." <<
nl
635 <<
"Pattern replacement is not supported." <<
nl
640 auto iter2 = hashedEntries_.find(newKeyword);
647 if (iter2()->keyword().isPattern())
650 auto wcLink = patterns_.begin();
651 auto reLink = regexps_.begin();
654 if (findInPatterns(
false, iter2()->keyword(), wcLink, reLink))
656 patterns_.remove(wcLink);
657 regexps_.remove(reLink);
661 parent_type::replace(iter2(), iter());
663 hashedEntries_.erase(iter2);
668 <<
"Cannot rename keyword " << oldKeyword
669 <<
" to existing keyword " << newKeyword
670 <<
" in dictionary " <<
name() <<
endl;
676 iter()->keyword() = newKeyword;
677 iter()->name() =
name() +
'.' + newKeyword;
678 hashedEntries_.erase(oldKeyword);
679 hashedEntries_.insert(newKeyword, iter());
683 patterns_.prepend(iter());
unsigned int remove()
Remove and return the last element.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
A keyword and a list of tokens is a 'dictionaryEntry'.
Generic const/non-const dictionary entry searcher.
void set(pointer eptr)
Assign the entry.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
bool changeKeyword(const keyType &oldKeyword, const keyType &newKeyword, bool overwrite=false)
Change the keyword for an entry,.
dictionary()
Default construct, a top-level empty dictionary.
const_searcher csearchScoped(const word &keyword, enum keyType::option matchOpt) const
Search using scoping.
const dictionary * findScopedDict(const fileName &dictPath) const
Locate a sub-dictionary using slash-scoping.
dictionary * makeScopedDict(const fileName &dictPath)
Locate existing or create sub-dictionary using slash-scoping.
const_searcher search(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search dictionary for given keyword.
const dictionary * cfindScopedDict(const fileName &dictPath) const
Locate a sub-dictionary using slash-scoping.
const_searcher csearch(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search dictionary for given keyword.
Searcher< true > const_searcher
Searcher with const access.
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
const_searcher searchScoped(const word &keyword, enum keyType::option matchOpt) const
Search using dot or slash scoping.
A keyword and a list of tokens is an 'entry'.
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
virtual const dictionary * dictPtr() const noexcept
Return pointer to dictionary, if entry is a dictionary.
A class for handling file names.
wordList components(const char delim='/') const
Return path components as wordList.
bool clean()
Cleanup filename (inplace)
static bool clean(std::string &str)
virtual void validate()
Validate the turbulence fields after construction.
A class for handling keywords in dictionaries.
option
Enumeration for the data type and search/match modes (bitmask)
@ REGEX
Regular expression.
@ RECURSIVE
Recursive search (eg, in dictionary)
bool isPattern() const noexcept
The keyType is treated as a pattern, not as literal string.
A class for handling words, derived from Foam::string.
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
bool match(const UList< wordRe > &patterns, const std::string &text)
Return true if text matches one of the regular expressions.
Foam::SubStrings< StringType > split(const StringType &str, const char delim, const bool keepEmpty=false)
Split string into sub-strings at the delimiter character.
Ostream & endl(Ostream &os)
Add newline and flush stream.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
errorManipArg< error, int > exit(error &err, const int errNo=1)
constexpr char nl
The newline '\n' character (0x0a)