38 template<
class WcIterator,
class ReIterator>
52 ? wcIter()->keyword() == keyword
53 : reIter()->
match(keyword)
74 enum keyType::option matchOpt
77 auto scopePos = keyword.find(
'.');
79 if (scopePos == std::string::npos)
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);
144 if (scopePos == std::string::npos)
154 return finder.
dict().csearchDotScoped
156 keyword.substr(scopePos),
177 const auto slash = keyword.find(
'/');
179 if (slash == std::string::npos)
183 return csearch(keyword, matchOpt);
191 dictPtr = &dictPtr->parent_;
196 auto remaining = cmpts.size();
198 for (
const auto& cmpt : cmpts)
206 else if (cmpt ==
"..")
211 dictPtr = &dictPtr->parent_;
216 <<
"No parent of current dictionary when searching for " 217 << keyword <<
" at " << cmpt
227 auto finder = dictPtr->csearch(
key, matchOpt);
236 dictPtr = finder.dictPtr();
240 return const_searcher(dictPtr);
269 const_searcher finder(
this);
271 auto iter = hashedEntries_.cfind(keyword);
275 finder.set(iter.val());
281 auto wcLink = patterns_.cbegin();
282 auto reLink = regexps_.cbegin();
285 if (findInPatterns(
false, keyword, wcLink, reLink))
294 return parent_.csearch(keyword, matchOpt);
307 return csearch(keyword, matchOpt);
319 return static_cast<const searcher&
>(finder);
331 return csearchSlashScoped(keyword, matchOpt);
334 if (keyword[0] ==
':' || keyword[0] ==
'^')
343 dictPtr = &dictPtr->parent_;
346 return dictPtr->csearchDotScoped(keyword.substr(1), matchOpt);
349 return csearchDotScoped(keyword, matchOpt);
359 return csearchScoped(keyword, matchOpt);
371 return static_cast<const searcher&
>(finder);
381 if (dictPath.empty())
387 if (dictPath[0] ==
'/')
393 dictPtr = &dictPtr->parent_;
397 fileName
path(dictPath);
401 for (
const auto& cmpt : dictCmpts)
407 else if (cmpt ==
"..")
412 dictPtr = &dictPtr->parent_;
417 <<
"No parent for dictionary while searching " 429 const word cmptName(cmpt.str(),
false);
431 auto iter = dictPtr->hashedEntries_.cfind(cmptName);
435 const entry *eptr = iter.val();
439 dictPtr = eptr->dictPtr();
444 <<
"Found entry '" << cmptName
445 <<
"' but not a dictionary, while searching scoped" 466 const fileName& dictPath
469 return cfindScopedDict(dictPath);
478 const dictionary* ptr = cfindScopedDict(dictPath);
486 if (dictPath.empty())
492 if (dictPath[0] ==
'/')
498 dictPtr =
const_cast<dictionary*
>(&dictPtr->parent_);
502 std::string
path(dictPath);
506 for (
const auto& cmpt : dictCmpts)
512 else if (cmpt ==
"..")
517 dictPtr =
const_cast<dictionary*
>(&dictPtr->parent_);
522 <<
"No parent for dictionary while searching " 534 const word cmptName(cmpt.str(),
false);
536 auto iter = dictPtr->hashedEntries_.find(cmptName);
540 entry *eptr = iter.val();
544 dictPtr = eptr->dictPtr();
549 <<
"Cannot create sub-dictionary entry '" << cmptName
550 <<
"' - a non-dictionary entry is in the way" 551 <<
nl <<
"Encountered in scope" <<
nl 560 dictionaryEntry *eptr =
561 new dictionaryEntry(cmptName, *dictPtr,
dictionary());
566 if (dictPtr->add(eptr,
false))
585 auto iter = hashedEntries_.find(keyword);
590 auto wcLink = patterns_.begin();
591 auto reLink = regexps_.begin();
594 if (findInPatterns(
true, keyword, wcLink, reLink))
596 patterns_.remove(wcLink);
597 regexps_.remove(reLink);
600 parent_type::remove(iter());
602 hashedEntries_.erase(iter);
613 const keyType& oldKeyword,
614 const keyType& newKeyword,
619 if (oldKeyword == newKeyword)
625 auto iter = hashedEntries_.find(oldKeyword);
632 if (iter()->keyword().isPattern())
635 <<
"Old keyword " << oldKeyword <<
" is a pattern." <<
nl 636 <<
"Pattern replacement is not supported." <<
nl 641 auto iter2 = hashedEntries_.find(newKeyword);
648 if (iter2()->keyword().isPattern())
651 auto wcLink = patterns_.begin();
652 auto reLink = regexps_.begin();
655 if (findInPatterns(
true, iter2()->keyword(), wcLink, reLink))
657 patterns_.remove(wcLink);
658 regexps_.remove(reLink);
662 parent_type::replace(iter2(), iter());
664 hashedEntries_.erase(iter2);
669 <<
"Cannot rename keyword " << oldKeyword
670 <<
" to existing keyword " << newKeyword
671 <<
" in dictionary " <<
name() <<
endl;
677 iter()->keyword() = newKeyword;
679 hashedEntries_.erase(oldKeyword);
680 hashedEntries_.insert(newKeyword, iter());
682 if (newKeyword.isPattern())
684 patterns_.push_front(iter());
dict_reference dict() const
Return the found entry as a dictionary. Error if not found, or not a dictionary.
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
A class for handling file names.
virtual const fileName & name() const
The name of the stream.
bool contains(char c) const noexcept
True if string contains given character (cf. C++23)
errorManipArg< error, int > exit(error &err, const int errNo=1)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
bool clean()
Cleanup filename (inplace)
constexpr char nl
The newline '\n' character (0x0a)
Foam::SubStrings split(const std::string &str, const char delim, std::string::size_type pos=0, const bool keepEmpty=false)
Split string into sub-strings at the delimiter character.
Ostream & endl(Ostream &os)
Add newline and flush stream.
bool match(const std::string &text) const
Test for equality.
Recursive search (eg, in dictionary)
bool remove(const word &keyword)
Remove an entry specified by keyword.
const_searcher search(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search dictionary for given keyword.
dictionary()
Default construct, a top-level empty dictionary.
const dictionary * findScopedDict(const fileName &dictPath) const
Locate a sub-dictionary using slash-scoping.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Generic const/non-const dictionary entry searcher.
A class for handling words, derived from Foam::string.
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
auto key(const Type &t) -> std::enable_if_t< std::is_enum_v< Type >, std::underlying_type_t< Type > >
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
const dictionary * cfindScopedDict(const fileName &dictPath) const
Locate a sub-dictionary using slash-scoping.
const_searcher csearchScoped(const word &keyword, enum keyType::option matchOpt) const
Search using scoping.
static bool clean(std::string &str)
Cleanup filename string, possibly applies other transformations such as changing the path separator e...
Searcher< true > const_searcher
Searcher with const access.
static fileName concat(const std::string &s1, const std::string &s2, const char delim='/')
Join two strings with a path separator ('/' by default).
const_searcher searchScoped(const word &keyword, enum keyType::option matchOpt) const
Search using dot or slash scoping.
dictionary * makeScopedDict(const fileName &dictPath)
Locate existing or create sub-dictionary using slash-scoping.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
option
Enumeration for the data type and search/match modes (bitmask)
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
const_searcher csearch(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search dictionary for given keyword.
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
bool changeKeyword(const keyType &oldKeyword, const keyType &newKeyword, bool overwrite=false)
Change the keyword for an entry,.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...