mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'feature-dictionary-scoping-lvalue' into 'develop'
Feature dictionary scoping lvalue See merge request Development/OpenFOAM-plus!124
This commit is contained in:
@ -13,18 +13,19 @@ FoamFile
|
||||
object testDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
#inputMode merge
|
||||
|
||||
#includeIfPresent "someUnknownFile"
|
||||
#includeIfPresent "$FOAM_CASE/someUnknownFile"
|
||||
#includeIfPresent "$FOAM_CASE/someUnknownFile-$FOAM_CASENAME"
|
||||
|
||||
internalField uniform 1;
|
||||
|
||||
// use 'protect' to supply defaults
|
||||
#inputMode protect
|
||||
internalField uniform 10;
|
||||
dimensions [ 0 2 -2 0 0 0 0 ];
|
||||
#inputMode merge
|
||||
// supply defaults
|
||||
#default internalField uniform 10;
|
||||
#default dimensions [ 1 2 -2 0 0 0 0 ];
|
||||
#overwrite dimensions [ 0 2 -2 0 0 0 0 ];
|
||||
// #warn dimensions [ 0 2 -2 0 0 0 0 ];
|
||||
// #error dimensions [ 0 2 -2 0 0 0 0 ];
|
||||
|
||||
active
|
||||
{
|
||||
@ -86,12 +87,12 @@ boundaryField
|
||||
#remove inactive
|
||||
|
||||
inlet_7 { ${${varType}}} // Test indirection/recursive expansion
|
||||
#inputMode overwrite
|
||||
inlet_8 { $active }
|
||||
|
||||
#overwrite inlet_8 { type none; }
|
||||
}
|
||||
|
||||
// NB: the inputMode has a global scope
|
||||
#inputMode merge
|
||||
|
||||
#include "testDict2"
|
||||
|
||||
foo
|
||||
|
||||
@ -17,6 +17,8 @@ FoamFile
|
||||
// #inputMode overwrite
|
||||
|
||||
key1 val1;
|
||||
val1 val1;
|
||||
val2 val2;
|
||||
|
||||
subdict
|
||||
{
|
||||
@ -35,19 +37,75 @@ update
|
||||
key3 val3;
|
||||
key2b ${..key2};
|
||||
key3b $^key1;
|
||||
key100 100;
|
||||
key200 200;
|
||||
key300 300;
|
||||
key400 400;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// expands update into top-level
|
||||
$update
|
||||
|
||||
// Can a leading '^' or ':' as anchor for scoping
|
||||
key3 $^subdict.key1;
|
||||
|
||||
_cleanup
|
||||
{
|
||||
#remove "/subdict/key300"
|
||||
"/subdict/key400" 400000;
|
||||
|
||||
// Self-destruct not possible
|
||||
// #remove "/_cleanup"
|
||||
}
|
||||
|
||||
#remove "/_cleanup"
|
||||
|
||||
// Can use a leading '^' or ':' as anchor for scoping, but slashes are clearer
|
||||
key3dot ${^subdict.key1};
|
||||
key3slash ${/subdict/key1};
|
||||
key3 ${^update.subdict.key3};
|
||||
key4 ${:update.subdict...subdict.key1};
|
||||
|
||||
// This is currently not working
|
||||
#remove update.key1
|
||||
// #remove update
|
||||
// This will not work, but globs would be interesting:
|
||||
#remove "/update/subdict/key*"
|
||||
|
||||
// This is okay, uses a regexp directly
|
||||
#remove "val.*"
|
||||
|
||||
#remove "/update/subdict/key100"
|
||||
|
||||
"/subdict/key2" overridden;
|
||||
|
||||
|
||||
active
|
||||
{
|
||||
type turbulentIntensityKineticEnergyInlet;
|
||||
intensity 0.1;
|
||||
value 100;
|
||||
}
|
||||
|
||||
// Some more with scoping
|
||||
|
||||
"/active/value(pwd)" 200;
|
||||
"/active/'(pwd|foo)'" 200; // Can use single or double quotes
|
||||
"/active/intensity" 0.05;
|
||||
|
||||
// Auto-vivify intermediate dictionaries
|
||||
|
||||
"/active/subdict/type" anotherType;
|
||||
"/active/subdict/value/type" anotherType;
|
||||
|
||||
// This is an error - cannot change type of intermediate dictionaries!
|
||||
// "active/value/type/of/things" newType;
|
||||
|
||||
"/active/subdict/value" change;
|
||||
|
||||
"/active/subdict/value" { entry1 value1; entry2 value2; }
|
||||
|
||||
// Handle remove as per changeDictionary? TBD
|
||||
// Removal:
|
||||
// "~/active/subdict/value"
|
||||
|
||||
// "~active"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2016-2017 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -33,7 +33,7 @@ Usage
|
||||
- \par -entry \<name\>
|
||||
Selects an entry
|
||||
|
||||
- \par -keywords \<name\>
|
||||
- \par -keywords
|
||||
Prints the keywords (of the selected entry or of the top level if
|
||||
no entry was selected
|
||||
|
||||
@ -50,6 +50,10 @@ Usage
|
||||
Write differences with respect to the specified dictionary
|
||||
(or sub entry if -entry specified)
|
||||
|
||||
- \par -diffEtc \<dictionary\>
|
||||
Write differences with respect to the specified dictionary
|
||||
(or sub entry if -entry specified)
|
||||
|
||||
- \par -expand
|
||||
Read the specified dictionary file, expand the macros etc. and write
|
||||
the resulting dictionary to standard output.
|
||||
@ -90,13 +94,13 @@ Usage
|
||||
|
||||
- Write the differences with respect to a template dictionary:
|
||||
\verbatim
|
||||
foamDictionary 0/U -diff $FOAM_ETC/templates/closedVolume/0/U
|
||||
foamDictionary 0/U -diffEtc templates/closedVolume/0/U
|
||||
\endverbatim
|
||||
|
||||
- Write the differences in boundaryField with respect to a
|
||||
template dictionary:
|
||||
\verbatim
|
||||
foamDictionary 0/U -diff $FOAM_ETC/templates/closedVolume/0/U \
|
||||
foamDictionary 0/U -diffEtc templates/closedVolume/0/U \
|
||||
-entry boundaryField
|
||||
\endverbatim
|
||||
|
||||
@ -115,50 +119,78 @@ Usage
|
||||
#include "profiling.H"
|
||||
#include "Time.H"
|
||||
#include "Fstream.H"
|
||||
#include "etcFiles.H"
|
||||
#include "includeEntry.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- Converts old scope syntax to new syntax
|
||||
word scope(const fileName& entryName)
|
||||
//- Convert older ':' scope syntax to newer '.' scope syntax,
|
||||
// but leave anything with '/' delimiters untouched
|
||||
bool upgradeScope(word& entryName)
|
||||
{
|
||||
if (entryName.find(':') != string::npos)
|
||||
if
|
||||
(
|
||||
entryName.find('/') == string::npos
|
||||
&& entryName.find(':') != string::npos
|
||||
)
|
||||
{
|
||||
wordList entryNames(entryName.components(':'));
|
||||
const wordList names(fileName(entryName).components(':'));
|
||||
|
||||
word entry(entryNames[0]);
|
||||
for (label i = 1; i < entryNames.size(); i++)
|
||||
entryName.resize(0);
|
||||
|
||||
for (const word& name : names)
|
||||
{
|
||||
entry += word('.') + entryNames[i];
|
||||
if (entryName.size()) entryName.append(".");
|
||||
|
||||
entryName.append(name);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
return entryName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nothing changed
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//- Extracts dict name and keyword
|
||||
Pair<word> dictAndKeyword(const word& scopedName)
|
||||
//- Split into dictionary name and the entry name
|
||||
class dictAndKeyword
|
||||
{
|
||||
string::size_type i = scopedName.find_last_of(".");
|
||||
if (i != string::npos)
|
||||
word dict_;
|
||||
word key_;
|
||||
|
||||
public:
|
||||
dictAndKeyword(const word& scopedName)
|
||||
{
|
||||
return Pair<word>
|
||||
(
|
||||
scopedName.substr(0, i),
|
||||
scopedName.substr(i+1, string::npos)
|
||||
);
|
||||
string::size_type i = scopedName.rfind('/');
|
||||
if (i == string::npos)
|
||||
{
|
||||
i = scopedName.rfind('.');
|
||||
}
|
||||
|
||||
if (i != string::npos)
|
||||
{
|
||||
dict_ = scopedName.substr(0, i);
|
||||
key_ = scopedName.substr(i+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
key_ = scopedName;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
inline const word& dict() const
|
||||
{
|
||||
return Pair<word>("", scopedName);
|
||||
return dict_;
|
||||
}
|
||||
}
|
||||
|
||||
inline const word& key() const
|
||||
{
|
||||
return key_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const dictionary& lookupScopedDict
|
||||
@ -167,71 +199,56 @@ const dictionary& lookupScopedDict
|
||||
const word& subDictName
|
||||
)
|
||||
{
|
||||
if (subDictName == "")
|
||||
if (subDictName.empty())
|
||||
{
|
||||
return dict;
|
||||
}
|
||||
else
|
||||
|
||||
const entry* eptr = dict.lookupScopedEntryPtr(subDictName, false, false);
|
||||
|
||||
if (!eptr || !eptr->isDict())
|
||||
{
|
||||
const entry* entPtr = dict.lookupScopedEntryPtr
|
||||
(
|
||||
subDictName,
|
||||
false,
|
||||
false
|
||||
);
|
||||
if (!entPtr || !entPtr->isDict())
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "keyword " << subDictName
|
||||
<< " is undefined in dictionary "
|
||||
<< dict.name() << " or is not a dictionary"
|
||||
<< endl
|
||||
<< "Valid keywords are " << dict.keys()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
return entPtr->dict();
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "keyword " << subDictName
|
||||
<< " is undefined in dictionary "
|
||||
<< dict.name() << " or is not a dictionary"
|
||||
<< endl
|
||||
<< "Valid keywords are " << dict.keys()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
return eptr->dict();
|
||||
}
|
||||
|
||||
|
||||
void remove(dictionary& dict, const dictionary& removeDict)
|
||||
void removeDict(dictionary& dict, const dictionary& dictToRemove)
|
||||
{
|
||||
forAllConstIter(dictionary, removeDict, iter)
|
||||
for (const entry& refEntry : dictToRemove)
|
||||
{
|
||||
const entry* entPtr = dict.lookupEntryPtr
|
||||
(
|
||||
iter().keyword(),
|
||||
false,
|
||||
false
|
||||
);
|
||||
auto finder = dict.search(refEntry.keyword(), false, false);
|
||||
|
||||
if (entPtr)
|
||||
bool purge = false;
|
||||
|
||||
if (finder.isDict())
|
||||
{
|
||||
if (entPtr->isDict())
|
||||
if (refEntry.isDict())
|
||||
{
|
||||
if (iter().isDict())
|
||||
{
|
||||
remove
|
||||
(
|
||||
const_cast<dictionary&>(entPtr->dict()),
|
||||
iter().dict()
|
||||
);
|
||||
removeDict(finder.dict(), refEntry.dict());
|
||||
|
||||
// Check if dictionary is empty
|
||||
if (!entPtr->dict().size())
|
||||
{
|
||||
dict.remove(iter().keyword());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!iter().isDict())
|
||||
{
|
||||
if (*entPtr == iter())
|
||||
{
|
||||
dict.remove(iter().keyword());
|
||||
}
|
||||
// Purge if dictionary is empty
|
||||
purge = finder.dict().empty();
|
||||
}
|
||||
}
|
||||
else if (finder.found() && !refEntry.isDict())
|
||||
{
|
||||
// Purge if entries match
|
||||
purge = (finder.ref() == refEntry);
|
||||
}
|
||||
|
||||
if (purge)
|
||||
{
|
||||
dict.remove(refEntry.keyword());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,7 +260,7 @@ int main(int argc, char *argv[])
|
||||
argList::noBanner();
|
||||
argList::noJobInfo();
|
||||
argList::validArgs.append("dictionary");
|
||||
argList::addBoolOption("keywords", "list keywords");
|
||||
argList::addBoolOption("keywords", "List keywords");
|
||||
argList::addOption("entry", "name", "report/select the named entry");
|
||||
argList::addBoolOption
|
||||
(
|
||||
@ -273,6 +290,12 @@ int main(int argc, char *argv[])
|
||||
"dict",
|
||||
"Write differences with respect to the specified dictionary"
|
||||
);
|
||||
argList::addOption
|
||||
(
|
||||
"diffEtc",
|
||||
"dict",
|
||||
"As per -diff, but locate the file as per foamEtcFile"
|
||||
);
|
||||
argList::addBoolOption
|
||||
(
|
||||
"includes",
|
||||
@ -303,13 +326,12 @@ int main(int argc, char *argv[])
|
||||
const bool disableEntries = args.optionFound("disableFunctionEntries");
|
||||
if (disableEntries)
|
||||
{
|
||||
Info<< "Not expanding variables or dictionary directives"
|
||||
<< endl;
|
||||
Info<< "Not expanding variables or dictionary directives" << endl;
|
||||
entry::disableFunctionEntries = true;
|
||||
}
|
||||
|
||||
|
||||
fileName dictFileName(args[1]);
|
||||
const fileName dictFileName(args[1]);
|
||||
|
||||
autoPtr<IFstream> dictFile(new IFstream(dictFileName));
|
||||
if (!dictFile().good())
|
||||
@ -341,28 +363,55 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
// Second dictionary for -diff
|
||||
dictionary diffDict;
|
||||
fileName diffFileName;
|
||||
if (args.optionReadIfPresent("diff", diffFileName))
|
||||
{
|
||||
autoPtr<IFstream> diffFile(new IFstream(diffFileName));
|
||||
if (!diffFile().good())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot open file " << diffFileName
|
||||
<< exit(FatalError, 1);
|
||||
}
|
||||
// Has "diff" or "diffEtc"
|
||||
bool optDiff = false;
|
||||
|
||||
// Read but preserve headers
|
||||
diffDict.read(diffFile(), true);
|
||||
// Reference dictionary for -diff / -diffEtc
|
||||
dictionary diffDict;
|
||||
{
|
||||
fileName diffFileName;
|
||||
if (args.optionReadIfPresent("diff", diffFileName))
|
||||
{
|
||||
IFstream diffFile(diffFileName);
|
||||
if (!diffFile.good())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot open file " << diffFileName
|
||||
<< exit(FatalError, 1);
|
||||
}
|
||||
|
||||
// Read but preserve headers
|
||||
diffDict.read(diffFile, true);
|
||||
optDiff = true;
|
||||
}
|
||||
else if (args.optionReadIfPresent("diffEtc", diffFileName))
|
||||
{
|
||||
fileName foundName = findEtcFile(diffFileName);
|
||||
if (foundName.empty())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot find etcFile " << diffFileName
|
||||
<< exit(FatalError, 1);
|
||||
}
|
||||
|
||||
IFstream diffFile(foundName);
|
||||
if (!diffFile.good())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot open file " << foundName
|
||||
<< exit(FatalError, 1);
|
||||
}
|
||||
|
||||
// Read but preserve headers
|
||||
diffDict.read(diffFile, true);
|
||||
optDiff = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
word entryName;
|
||||
if (args.optionReadIfPresent("entry", entryName))
|
||||
word scopedName; // Actually fileName, since it can contain '/' scoping
|
||||
if (args.optionReadIfPresent("entry", scopedName))
|
||||
{
|
||||
word scopedName(scope(entryName));
|
||||
upgradeScope(scopedName);
|
||||
|
||||
string newValue;
|
||||
if
|
||||
@ -371,13 +420,17 @@ int main(int argc, char *argv[])
|
||||
|| args.optionReadIfPresent("add", newValue)
|
||||
)
|
||||
{
|
||||
bool overwrite = args.optionFound("set");
|
||||
const bool overwrite = args.optionFound("set");
|
||||
|
||||
Pair<word> dAk(dictAndKeyword(scopedName));
|
||||
// Dictionary name and keyword
|
||||
const dictAndKeyword dAk(scopedName);
|
||||
|
||||
IStringStream str(string(dAk.second()) + ' ' + newValue + ';');
|
||||
// The context for the action
|
||||
const dictionary& d(lookupScopedDict(dict, dAk.dict()));
|
||||
|
||||
// Create a new entry
|
||||
IStringStream str(string(dAk.key()) + ' ' + newValue + ';');
|
||||
entry* ePtr(entry::New(str).ptr());
|
||||
const dictionary& d(lookupScopedDict(dict, dAk.first()));
|
||||
|
||||
if (overwrite)
|
||||
{
|
||||
@ -390,122 +443,116 @@ int main(int argc, char *argv[])
|
||||
changed = true;
|
||||
|
||||
// Print the changed entry
|
||||
const entry* entPtr = dict.lookupScopedEntryPtr
|
||||
const auto finder = dict.csearchScoped
|
||||
(
|
||||
scopedName,
|
||||
false,
|
||||
true // Support wildcards
|
||||
true // Support wildcards
|
||||
);
|
||||
if (entPtr)
|
||||
|
||||
if (finder.found())
|
||||
{
|
||||
Info<< *entPtr;
|
||||
Info<< finder.ref();
|
||||
}
|
||||
}
|
||||
else if (args.optionFound("remove"))
|
||||
{
|
||||
// Extract dictionary name and keyword
|
||||
Pair<word> dAk(dictAndKeyword(scopedName));
|
||||
// Dictionary name and keyword
|
||||
const dictAndKeyword dAk(scopedName);
|
||||
|
||||
const dictionary& d(lookupScopedDict(dict, dAk.first()));
|
||||
const_cast<dictionary&>(d).remove(dAk.second());
|
||||
// The context for the action
|
||||
const dictionary& d(lookupScopedDict(dict, dAk.dict()));
|
||||
|
||||
const_cast<dictionary&>(d).remove(dAk.key());
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Optionally remove a second dictionary
|
||||
if (args.optionFound("diff"))
|
||||
if (optDiff)
|
||||
{
|
||||
Pair<word> dAk(dictAndKeyword(scopedName));
|
||||
// Dictionary name and keyword
|
||||
const dictAndKeyword dAk(scopedName);
|
||||
|
||||
const dictionary& d(lookupScopedDict(dict, dAk.first()));
|
||||
const dictionary& d2(lookupScopedDict(diffDict, dAk.first()));
|
||||
const dictionary& d1(lookupScopedDict(dict, dAk.dict()));
|
||||
const dictionary& d2(lookupScopedDict(diffDict, dAk.dict()));
|
||||
|
||||
const entry* ePtr =
|
||||
d.lookupEntryPtr(dAk.second(), false, true);
|
||||
const entry* e2Ptr =
|
||||
d2.lookupEntryPtr(dAk.second(), false, true);
|
||||
const entry* e1Ptr = d1.lookupEntryPtr(dAk.key(), false, true);
|
||||
const entry* e2Ptr = d2.lookupEntryPtr(dAk.key(), false, true);
|
||||
|
||||
if (ePtr && e2Ptr)
|
||||
if (e1Ptr && e2Ptr)
|
||||
{
|
||||
if (*ePtr == *e2Ptr)
|
||||
if (*e1Ptr == *e2Ptr)
|
||||
{
|
||||
const_cast<dictionary&>(d).remove(dAk.second());
|
||||
const_cast<dictionary&>(d1).remove(dAk.key());
|
||||
}
|
||||
else if (ePtr->isDict() && e2Ptr->isDict())
|
||||
else if (e1Ptr->isDict() && e2Ptr->isDict())
|
||||
{
|
||||
remove
|
||||
removeDict
|
||||
(
|
||||
const_cast<dictionary&>(ePtr->dict()),
|
||||
const_cast<dictionary&>(e1Ptr->dict()),
|
||||
e2Ptr->dict()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const entry* entPtr = dict.lookupScopedEntryPtr
|
||||
const auto finder = dict.csearchScoped
|
||||
(
|
||||
scopedName,
|
||||
false,
|
||||
true // Support wildcards
|
||||
true // Support wildcards
|
||||
);
|
||||
|
||||
if (entPtr)
|
||||
if (!finder.found())
|
||||
{
|
||||
if (args.optionFound("keywords"))
|
||||
FatalIOErrorInFunction(dictFile())
|
||||
<< "Cannot find entry " << scopedName
|
||||
<< exit(FatalIOError, 2);
|
||||
}
|
||||
else if (args.optionFound("keywords"))
|
||||
{
|
||||
for (const entry& e : finder.dict())
|
||||
{
|
||||
const dictionary& dict = entPtr->dict();
|
||||
forAllConstIter(dictionary, dict, iter)
|
||||
{
|
||||
Info<< iter().keyword() << endl;
|
||||
}
|
||||
Info<< e.keyword() << endl;
|
||||
}
|
||||
else
|
||||
}
|
||||
else if (args.optionFound("value"))
|
||||
{
|
||||
if (finder.isDict())
|
||||
{
|
||||
if (args.optionFound("value"))
|
||||
Info<< finder.dict();
|
||||
}
|
||||
else if (finder.ref().isStream())
|
||||
{
|
||||
const tokenList& tokens = finder.ref().stream();
|
||||
forAll(tokens, i)
|
||||
{
|
||||
if (entPtr->isStream())
|
||||
Info<< tokens[i];
|
||||
if (i < tokens.size() - 1)
|
||||
{
|
||||
const tokenList& tokens = entPtr->stream();
|
||||
forAll(tokens, i)
|
||||
{
|
||||
Info<< tokens[i];
|
||||
if (i < tokens.size() - 1)
|
||||
{
|
||||
Info<< token::SPACE;
|
||||
}
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
else if (entPtr->isDict())
|
||||
{
|
||||
Info<< entPtr->dict();
|
||||
Info<< token::SPACE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< *entPtr;
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(dictFile)
|
||||
<< "Cannot find entry " << entryName
|
||||
<< exit(FatalIOError, 2);
|
||||
Info<< finder.ref();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (args.optionFound("keywords"))
|
||||
{
|
||||
forAllConstIter(dictionary, dict, iter)
|
||||
for (const entry& e : dict)
|
||||
{
|
||||
Info<< iter().keyword() << endl;
|
||||
Info<< e.keyword() << endl;
|
||||
}
|
||||
}
|
||||
else if (args.optionFound("diff"))
|
||||
else if (optDiff)
|
||||
{
|
||||
remove(dict, diffDict);
|
||||
removeDict(dict, diffDict);
|
||||
dict.write(Info, false);
|
||||
}
|
||||
else
|
||||
|
||||
@ -14,8 +14,6 @@ FoamFile
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#inputMode merge;
|
||||
|
||||
surfaceConformation
|
||||
{
|
||||
pointPairDistanceCoeff 0.1;
|
||||
|
||||
@ -203,6 +203,7 @@ $(Pstreams)/PstreamBuffers.C
|
||||
dictionary = db/dictionary
|
||||
$(dictionary)/dictionary.C
|
||||
$(dictionary)/dictionaryIO.C
|
||||
$(dictionary)/dictionarySearch.C
|
||||
|
||||
entry = $(dictionary)/entry
|
||||
$(entry)/entry.C
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,6 +28,12 @@ License
|
||||
#include "token.H"
|
||||
#include <cctype>
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
// Truncate error message for readability
|
||||
static const unsigned errLen = 80;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
char Foam::ISstream::nextValid()
|
||||
@ -43,7 +49,7 @@ char Foam::ISstream::nextValid()
|
||||
// Return if stream is bad - ie, previous get() failed
|
||||
if (bad() || isspace(c))
|
||||
{
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is this the start of a C/C++ comment?
|
||||
@ -51,7 +57,7 @@ char Foam::ISstream::nextValid()
|
||||
{
|
||||
if (!get(c))
|
||||
{
|
||||
// cannot get another character - return this one
|
||||
// Cannot get another character - return this one
|
||||
return '/';
|
||||
}
|
||||
|
||||
@ -63,10 +69,10 @@ char Foam::ISstream::nextValid()
|
||||
}
|
||||
else if (c == '*')
|
||||
{
|
||||
// within a C-style comment
|
||||
// Within a C-style comment
|
||||
while (true)
|
||||
{
|
||||
// search for end of C-style comment - '*/'
|
||||
// Search for end of C-style comment - '*/'
|
||||
if (get(c) && c == '*')
|
||||
{
|
||||
if (get(c))
|
||||
@ -99,7 +105,7 @@ char Foam::ISstream::nextValid()
|
||||
}
|
||||
else
|
||||
{
|
||||
// a valid character - return it
|
||||
// A valid character - return it
|
||||
return c;
|
||||
}
|
||||
}
|
||||
@ -124,14 +130,14 @@ void Foam::ISstream::readWordToken(token& t)
|
||||
}
|
||||
else
|
||||
{
|
||||
t = wPtr;
|
||||
t = wPtr; // Token takes ownership
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::Istream& Foam::ISstream::read(token& t)
|
||||
{
|
||||
static const int maxLen = 128;
|
||||
static const unsigned maxLen = 128; // When parsing labels or scalars
|
||||
static char buf[maxLen];
|
||||
|
||||
// Return the put back token if it exists
|
||||
@ -151,7 +157,7 @@ Foam::Istream& Foam::ISstream::read(token& t)
|
||||
// Set the line number of this token to the current stream line number
|
||||
t.lineNumber() = lineNumber();
|
||||
|
||||
// return on error
|
||||
// Return on error
|
||||
if (!c)
|
||||
{
|
||||
t.setBad();
|
||||
@ -182,7 +188,6 @@ Foam::Istream& Foam::ISstream::read(token& t)
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// String: enclosed by double quotes.
|
||||
case token::BEGIN_STRING :
|
||||
{
|
||||
@ -196,24 +201,24 @@ Foam::Istream& Foam::ISstream::read(token& t)
|
||||
}
|
||||
else
|
||||
{
|
||||
t = sPtr;
|
||||
t = sPtr; // Token takes ownership
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Possible verbatim string or dictionary functionEntry
|
||||
case token::HASH :
|
||||
{
|
||||
char nextC;
|
||||
if (read(nextC).bad())
|
||||
{
|
||||
// Return hash as word
|
||||
// Return lone '#' as word
|
||||
t = token(word(c));
|
||||
return *this;
|
||||
}
|
||||
else if (nextC == token::BEGIN_BLOCK)
|
||||
{
|
||||
// Verbatim string
|
||||
// Verbatim string: #{ ... #}
|
||||
string* sPtr = new string;
|
||||
|
||||
if (readVerbatim(*sPtr).bad())
|
||||
@ -223,36 +228,34 @@ Foam::Istream& Foam::ISstream::read(token& t)
|
||||
}
|
||||
else
|
||||
{
|
||||
t = sPtr;
|
||||
t = sPtr; // Token takes ownership
|
||||
t.type() = token::tokenType::VERBATIMSTRING;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Word beginning with #
|
||||
// Word beginning with '#'. Eg, "#include"
|
||||
putback(nextC);
|
||||
putback(c);
|
||||
|
||||
readWordToken(t);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Dictionary variable (as rvalue)
|
||||
case '$':
|
||||
{
|
||||
// Look ahead
|
||||
char nextC;
|
||||
if (read(nextC).bad())
|
||||
{
|
||||
// Return $ as word
|
||||
// Return lone '$' as word
|
||||
t = token(word(c));
|
||||
return *this;
|
||||
}
|
||||
else if (nextC == token::BEGIN_BLOCK)
|
||||
{
|
||||
// Put back so that "${" is included in the variable
|
||||
putback(nextC);
|
||||
putback(c);
|
||||
|
||||
@ -265,18 +268,20 @@ Foam::Istream& Foam::ISstream::read(token& t)
|
||||
}
|
||||
else
|
||||
{
|
||||
t = sPtr;
|
||||
t = sPtr; // Token takes ownership
|
||||
t.type() = token::tokenType::VARIABLE;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Word/variable beginning with '$', but without "{}"
|
||||
|
||||
putback(nextC);
|
||||
putback(c);
|
||||
readWordToken(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Number: integer or floating point
|
||||
@ -292,7 +297,7 @@ Foam::Istream& Foam::ISstream::read(token& t)
|
||||
{
|
||||
bool asLabel = (c != '.');
|
||||
|
||||
int nChar = 0;
|
||||
unsigned nChar = 0;
|
||||
buf[nChar++] = c;
|
||||
|
||||
// get everything that could resemble a number and let
|
||||
@ -343,43 +348,26 @@ Foam::Istream& Foam::ISstream::read(token& t)
|
||||
|
||||
if (nChar == 1 && buf[0] == '-')
|
||||
{
|
||||
// a single '-' is punctuation
|
||||
// A single '-' is punctuation
|
||||
t = token::punctuationToken(token::SUBTRACT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (asLabel)
|
||||
label labelVal;
|
||||
scalar scalarVal;
|
||||
|
||||
if (asLabel && Foam::read(buf, labelVal))
|
||||
{
|
||||
label labelVal = 0;
|
||||
if (Foam::read(buf, labelVal))
|
||||
{
|
||||
t = labelVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maybe too big? Try as scalar
|
||||
scalar scalarVal;
|
||||
if (readScalar(buf, scalarVal))
|
||||
{
|
||||
t = scalarVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
t.setBad();
|
||||
}
|
||||
}
|
||||
t = labelVal;
|
||||
}
|
||||
else if (readScalar(buf, scalarVal))
|
||||
{
|
||||
// A scalar or too big to fit as a label
|
||||
t = scalarVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
scalar scalarVal;
|
||||
if (readScalar(buf, scalarVal))
|
||||
{
|
||||
t = scalarVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
t.setBad();
|
||||
}
|
||||
t.setBad();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -409,28 +397,28 @@ Foam::Istream& Foam::ISstream::read(char& c)
|
||||
|
||||
Foam::Istream& Foam::ISstream::read(word& str)
|
||||
{
|
||||
static const int maxLen = 1024;
|
||||
static const int errLen = 80; // truncate error message for readability
|
||||
static const unsigned maxLen = 1024;
|
||||
static char buf[maxLen];
|
||||
|
||||
int nChar = 0;
|
||||
int listDepth = 0;
|
||||
unsigned nChar = 0;
|
||||
unsigned depth = 0; // Track depth of "()" nesting
|
||||
char c;
|
||||
|
||||
while (get(c) && word::valid(c))
|
||||
{
|
||||
if (c == token::BEGIN_LIST)
|
||||
{
|
||||
listDepth++;
|
||||
++depth;
|
||||
}
|
||||
else if (c == token::END_LIST)
|
||||
{
|
||||
if (listDepth)
|
||||
if (depth)
|
||||
{
|
||||
listDepth--;
|
||||
--depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Had ')' without a previous '(' ... stop
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -449,10 +437,13 @@ Foam::Istream& Foam::ISstream::read(word& str)
|
||||
}
|
||||
}
|
||||
|
||||
// we could probably skip this check
|
||||
// Terminate string with nul char
|
||||
buf[nChar] = '\0';
|
||||
|
||||
// We could probably skip this check
|
||||
if (bad())
|
||||
{
|
||||
buf[errLen] = buf[nChar] = '\0';
|
||||
buf[errLen] = '\0';
|
||||
|
||||
FatalIOErrorInFunction(*this)
|
||||
<< "problem while reading word '" << buf << "...' after "
|
||||
@ -468,9 +459,14 @@ Foam::Istream& Foam::ISstream::read(word& str)
|
||||
<< "invalid first character found : " << c
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
else if (depth)
|
||||
{
|
||||
IOWarningInFunction(*this)
|
||||
<< "Missing " << depth << " closing ')' while parsing" << nl << nl
|
||||
<< buf << nl << endl;
|
||||
}
|
||||
|
||||
// done reading
|
||||
buf[nChar] = '\0';
|
||||
// Finalize
|
||||
str = buf;
|
||||
putback(c);
|
||||
|
||||
@ -480,8 +476,7 @@ Foam::Istream& Foam::ISstream::read(word& str)
|
||||
|
||||
Foam::Istream& Foam::ISstream::read(string& str)
|
||||
{
|
||||
static const int maxLen = 1024;
|
||||
static const int errLen = 80; // truncate error message for readability
|
||||
static const unsigned maxLen = 1024;
|
||||
static char buf[maxLen];
|
||||
|
||||
char c;
|
||||
@ -505,7 +500,7 @@ Foam::Istream& Foam::ISstream::read(string& str)
|
||||
return *this;
|
||||
}
|
||||
|
||||
int nChar = 0;
|
||||
unsigned nChar = 0;
|
||||
bool escaped = false;
|
||||
|
||||
while (get(c))
|
||||
@ -515,11 +510,11 @@ Foam::Istream& Foam::ISstream::read(string& str)
|
||||
if (escaped)
|
||||
{
|
||||
escaped = false;
|
||||
nChar--; // overwrite backslash
|
||||
--nChar; // Overwrite backslash
|
||||
}
|
||||
else
|
||||
{
|
||||
// done reading
|
||||
// Done reading
|
||||
buf[nChar] = '\0';
|
||||
str = buf;
|
||||
return *this;
|
||||
@ -530,7 +525,7 @@ Foam::Istream& Foam::ISstream::read(string& str)
|
||||
if (escaped)
|
||||
{
|
||||
escaped = false;
|
||||
nChar--; // overwrite backslash
|
||||
--nChar; // Overwrite backslash
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -581,12 +576,11 @@ Foam::Istream& Foam::ISstream::read(string& str)
|
||||
|
||||
Foam::Istream& Foam::ISstream::readVariable(string& str)
|
||||
{
|
||||
static const int maxLen = 1024;
|
||||
static const int errLen = 80; // truncate error message for readability
|
||||
static const unsigned maxLen = 1024;
|
||||
static char buf[maxLen];
|
||||
|
||||
int nChar = 0;
|
||||
int blockCount = 0;
|
||||
unsigned nChar = 0;
|
||||
unsigned depth = 0; // Track depth of "{}" nesting
|
||||
char c;
|
||||
|
||||
if (!get(c) || c != '$')
|
||||
@ -601,8 +595,8 @@ Foam::Istream& Foam::ISstream::readVariable(string& str)
|
||||
// Read next character to see if '{'
|
||||
if (get(c) && c == token::BEGIN_BLOCK)
|
||||
{
|
||||
// Read, counting brackets
|
||||
buf[nChar++] = c;
|
||||
++depth; // Starts with '{'
|
||||
|
||||
// Also allow '/' between ${...} blocks for slash-scoping of entries
|
||||
while
|
||||
@ -615,6 +609,23 @@ Foam::Istream& Foam::ISstream::readVariable(string& str)
|
||||
)
|
||||
)
|
||||
{
|
||||
if (c == token::BEGIN_BLOCK)
|
||||
{
|
||||
++depth;
|
||||
}
|
||||
else if (c == token::END_BLOCK)
|
||||
{
|
||||
if (depth)
|
||||
{
|
||||
--depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Had '}' without a previous '{' ... stop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buf[nChar++] = c;
|
||||
if (nChar == maxLen)
|
||||
{
|
||||
@ -627,22 +638,6 @@ Foam::Istream& Foam::ISstream::readVariable(string& str)
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (c == token::BEGIN_BLOCK)
|
||||
{
|
||||
blockCount++;
|
||||
}
|
||||
else if (c == token::END_BLOCK)
|
||||
{
|
||||
if (blockCount)
|
||||
{
|
||||
blockCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -666,10 +661,13 @@ Foam::Istream& Foam::ISstream::readVariable(string& str)
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate string with nul char
|
||||
buf[nChar] = '\0';
|
||||
|
||||
// we could probably skip this check
|
||||
if (bad())
|
||||
{
|
||||
buf[errLen] = buf[nChar] = '\0';
|
||||
buf[errLen] = '\0';
|
||||
|
||||
FatalIOErrorInFunction(*this)
|
||||
<< "problem while reading string '" << buf << "...' after "
|
||||
@ -685,31 +683,29 @@ Foam::Istream& Foam::ISstream::readVariable(string& str)
|
||||
<< "invalid first character found : " << c
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
// done reading
|
||||
buf[nChar] = '\0';
|
||||
str = buf;
|
||||
|
||||
// Note: check if we exited due to '}' or just !word::valid.
|
||||
if (c != token::END_BLOCK)
|
||||
else if (depth)
|
||||
{
|
||||
putback(c);
|
||||
IOWarningInFunction(*this)
|
||||
<< "Missing " << depth << " closing '}' while parsing" << nl << nl
|
||||
<< buf << nl << endl;
|
||||
}
|
||||
|
||||
// Finalize
|
||||
str = buf;
|
||||
putback(c);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Foam::Istream& Foam::ISstream::readVerbatim(string& str)
|
||||
{
|
||||
static const int maxLen = 8000;
|
||||
static const int errLen = 80; // truncate error message for readability
|
||||
static const unsigned maxLen = 8000;
|
||||
static char buf[maxLen];
|
||||
|
||||
unsigned nChar = 0;
|
||||
char c;
|
||||
|
||||
int nChar = 0;
|
||||
|
||||
while (get(c))
|
||||
{
|
||||
if (c == token::HASH)
|
||||
@ -718,6 +714,7 @@ Foam::Istream& Foam::ISstream::readVerbatim(string& str)
|
||||
get(nextC);
|
||||
if (nextC == token::END_BLOCK)
|
||||
{
|
||||
// The closing "#}" found
|
||||
buf[nChar] = '\0';
|
||||
str = buf;
|
||||
return *this;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -69,9 +69,12 @@ class ISstream
|
||||
|
||||
|
||||
//- Read a verbatim string (excluding block delimiters).
|
||||
// The leading "#{" has been removed prior to calling,
|
||||
// continues until the closing "#}" has been found.
|
||||
Istream& readVerbatim(string& str);
|
||||
|
||||
//- Read a variable name (includes '{')
|
||||
//- Read a variable name starting with '$'.
|
||||
// Handles both "$var" and "${var}" forms.
|
||||
Istream& readVariable(string& str);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
|
||||
@ -102,7 +102,7 @@ Foam::Ostream& Foam::prefixOSstream::write(const char* str)
|
||||
checkWritePrefix();
|
||||
OSstream::write(str);
|
||||
|
||||
size_t len = strlen(str);
|
||||
const size_t len = strlen(str);
|
||||
if (len && str[len-1] == token::NL)
|
||||
{
|
||||
printPrefix_ = true;
|
||||
|
||||
@ -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 * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::dictionary::dictionary()
|
||||
@ -322,10 +171,8 @@ const Foam::dictionary& Foam::dictionary::topDict() const
|
||||
{
|
||||
return p.topDict();
|
||||
}
|
||||
else
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -335,10 +182,8 @@ Foam::label Foam::dictionary::startLineNumber() const
|
||||
{
|
||||
return first()->startLineNumber();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -348,10 +193,8 @@ Foam::label Foam::dictionary::endLineNumber() const
|
||||
{
|
||||
return last()->endLineNumber();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -395,29 +238,7 @@ bool Foam::dictionary::found
|
||||
bool patternMatch
|
||||
) const
|
||||
{
|
||||
if (hashedEntries_.found(keyword))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (patternMatch && patterns_.size())
|
||||
{
|
||||
pattern_const_iterator wcLink = patterns_.begin();
|
||||
regexp_const_iterator reLink = regexps_.begin();
|
||||
|
||||
// Find in patterns using regular expressions only
|
||||
if (findInPatterns(patternMatch, keyword, wcLink, reLink))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (recursive && &parent_ != &dictionary::null)
|
||||
{
|
||||
return parent_.found(keyword, recursive, patternMatch);
|
||||
}
|
||||
|
||||
return false;
|
||||
return csearch(keyword, recursive, patternMatch).found();
|
||||
}
|
||||
|
||||
|
||||
@ -428,31 +249,7 @@ const Foam::entry* Foam::dictionary::lookupEntryPtr
|
||||
bool patternMatch
|
||||
) const
|
||||
{
|
||||
auto iter = hashedEntries_.cfind(keyword);
|
||||
|
||||
if (iter.found())
|
||||
{
|
||||
return iter();
|
||||
}
|
||||
|
||||
if (patternMatch && patterns_.size())
|
||||
{
|
||||
pattern_const_iterator wcLink = patterns_.begin();
|
||||
regexp_const_iterator reLink = regexps_.begin();
|
||||
|
||||
// Find in patterns using regular expressions only
|
||||
if (findInPatterns(patternMatch, keyword, wcLink, reLink))
|
||||
{
|
||||
return wcLink();
|
||||
}
|
||||
}
|
||||
|
||||
if (recursive && &parent_ != &dictionary::null)
|
||||
{
|
||||
return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return csearch(keyword, recursive, patternMatch).ptr();
|
||||
}
|
||||
|
||||
|
||||
@ -463,36 +260,7 @@ Foam::entry* Foam::dictionary::lookupEntryPtr
|
||||
bool patternMatch
|
||||
)
|
||||
{
|
||||
auto iter = hashedEntries_.find(keyword);
|
||||
|
||||
if (iter.found())
|
||||
{
|
||||
return iter();
|
||||
}
|
||||
|
||||
if (patternMatch && patterns_.size())
|
||||
{
|
||||
pattern_iterator wcLink = patterns_.begin();
|
||||
regexp_iterator reLink = regexps_.begin();
|
||||
|
||||
// Find in patterns using regular expressions only
|
||||
if (findInPatterns(patternMatch, keyword, wcLink, reLink))
|
||||
{
|
||||
return wcLink();
|
||||
}
|
||||
}
|
||||
|
||||
if (recursive && &parent_ != &dictionary::null)
|
||||
{
|
||||
return const_cast<dictionary&>(parent_).lookupEntryPtr
|
||||
(
|
||||
keyword,
|
||||
recursive,
|
||||
patternMatch
|
||||
);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return search(keyword, recursive, patternMatch).ptr();
|
||||
}
|
||||
|
||||
|
||||
@ -503,9 +271,9 @@ const Foam::entry& Foam::dictionary::lookupEntry
|
||||
bool patternMatch
|
||||
) const
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
||||
auto finder = csearch(keyword, recursive, patternMatch);
|
||||
|
||||
if (entryPtr == nullptr)
|
||||
if (!finder.found())
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
@ -515,7 +283,7 @@ const Foam::entry& Foam::dictionary::lookupEntry
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
return *entryPtr;
|
||||
return finder.ref();
|
||||
}
|
||||
|
||||
|
||||
@ -537,29 +305,37 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr
|
||||
bool patternMatch
|
||||
) const
|
||||
{
|
||||
if ((keyword[0] == ':' || keyword[0] == '^'))
|
||||
{
|
||||
// Go up to top level
|
||||
const dictionary* dictPtr = this;
|
||||
while (&dictPtr->parent_ != &dictionary::null)
|
||||
{
|
||||
dictPtr = &dictPtr->parent_;
|
||||
}
|
||||
return csearchScoped(keyword, recursive, patternMatch).ptr();
|
||||
}
|
||||
|
||||
return dictPtr->lookupScopedSubEntryPtr
|
||||
(
|
||||
keyword.substr(1),
|
||||
false,
|
||||
patternMatch
|
||||
);
|
||||
|
||||
bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry)
|
||||
{
|
||||
if (keyword.size() < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return lookupScopedSubEntryPtr
|
||||
(
|
||||
keyword,
|
||||
recursive,
|
||||
patternMatch
|
||||
);
|
||||
// Drop leading '$' to get the var-name, already validated as word.
|
||||
const word varName(keyword.substr(1), false);
|
||||
|
||||
// Lookup the variable name in the given dictionary
|
||||
const_searcher finder = csearch(varName, true, true);
|
||||
|
||||
// If defined insert its entries into this dictionary
|
||||
if (finder.found())
|
||||
{
|
||||
const dictionary& addDict = finder.dict();
|
||||
|
||||
forAllConstIters(addDict, iter)
|
||||
{
|
||||
add(iter(), mergeEntry);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -569,16 +345,21 @@ bool Foam::dictionary::substituteScopedKeyword
|
||||
bool mergeEntry
|
||||
)
|
||||
{
|
||||
// Drop first character of keyword to get the var-name, already validated.
|
||||
if (keyword.size() < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Drop leading '$' to get the var-name, already validated as word.
|
||||
const word varName(keyword.substr(1), false);
|
||||
|
||||
// Lookup the variable name in the given dictionary
|
||||
const entry* ePtr = lookupScopedEntryPtr(varName, true, true);
|
||||
const_searcher finder = csearchScoped(varName, true, true);
|
||||
|
||||
// If defined insert its entries into this dictionary
|
||||
if (ePtr != nullptr)
|
||||
if (finder.found())
|
||||
{
|
||||
const dictionary& addDict = ePtr->dict();
|
||||
const dictionary& addDict = finder.dict();
|
||||
|
||||
forAllConstIter(parent_type, addDict, iter)
|
||||
{
|
||||
@ -595,54 +376,30 @@ bool Foam::dictionary::substituteScopedKeyword
|
||||
bool Foam::dictionary::isDict(const word& keyword) const
|
||||
{
|
||||
// Find non-recursive with patterns
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
||||
|
||||
if (entryPtr)
|
||||
{
|
||||
return entryPtr->isDict();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return csearch(keyword, false, true).isDict();
|
||||
}
|
||||
|
||||
|
||||
const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
||||
|
||||
if (entryPtr)
|
||||
{
|
||||
return &entryPtr->dict();
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
// Find non-recursive with patterns
|
||||
return csearch(keyword, false, true).dictPtr();
|
||||
}
|
||||
|
||||
|
||||
Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword)
|
||||
{
|
||||
entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
||||
|
||||
if (entryPtr)
|
||||
{
|
||||
return &entryPtr->dict();
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
// Find non-recursive with patterns
|
||||
return search(keyword, false, true).dictPtr();
|
||||
}
|
||||
|
||||
|
||||
const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
||||
// Find non-recursive with patterns
|
||||
auto finder = csearch(keyword, false, true);
|
||||
|
||||
if (entryPtr == nullptr)
|
||||
if (!finder.found())
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
@ -651,15 +408,17 @@ const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
|
||||
<< name()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
return entryPtr->dict();
|
||||
|
||||
return finder.dict();
|
||||
}
|
||||
|
||||
|
||||
Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
|
||||
{
|
||||
entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
||||
// Find non-recursive with patterns
|
||||
auto finder = search(keyword, false, true);
|
||||
|
||||
if (entryPtr == nullptr)
|
||||
if (!finder.found())
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
@ -668,7 +427,8 @@ Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
|
||||
<< name()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
return entryPtr->dict();
|
||||
|
||||
return finder.dict();
|
||||
}
|
||||
|
||||
|
||||
@ -678,29 +438,35 @@ Foam::dictionary Foam::dictionary::subOrEmptyDict
|
||||
const bool mustRead
|
||||
) const
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
||||
// Find non-recursive with patterns
|
||||
auto finder = csearch(keyword, false, true);
|
||||
|
||||
if (entryPtr == nullptr)
|
||||
if (finder.isDict())
|
||||
{
|
||||
if (mustRead)
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
*this
|
||||
) << "keyword " << keyword << " is undefined in dictionary "
|
||||
<< name()
|
||||
<< exit(FatalIOError);
|
||||
return entryPtr->dict();
|
||||
}
|
||||
else
|
||||
{
|
||||
return dictionary(*this, dictionary(name() + '.' + keyword));
|
||||
}
|
||||
// Found and a sub-dictionary
|
||||
return finder.dict();
|
||||
}
|
||||
else
|
||||
|
||||
if (mustRead)
|
||||
{
|
||||
return entryPtr->dict();
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
*this
|
||||
) << "keyword " << keyword
|
||||
<< " is not a sub-dictionary in dictionary "
|
||||
<< name()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
if (finder.found())
|
||||
{
|
||||
IOWarningInFunction((*this))
|
||||
<< "keyword " << keyword
|
||||
<< " found but not a sub-dictionary in dictionary "
|
||||
<< name() << endl;
|
||||
}
|
||||
|
||||
return dictionary(*this, dictionary(name() + '.' + keyword));
|
||||
}
|
||||
|
||||
|
||||
@ -709,16 +475,23 @@ const Foam::dictionary& Foam::dictionary::optionalSubDict
|
||||
const word& keyword
|
||||
) const
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, false, true);
|
||||
auto finder = csearch(keyword, false, true);
|
||||
|
||||
if (entryPtr)
|
||||
if (finder.isDict())
|
||||
{
|
||||
return entryPtr->dict();
|
||||
// Found and a sub-dictionary
|
||||
return finder.dict();
|
||||
}
|
||||
else
|
||||
|
||||
if (finder.found())
|
||||
{
|
||||
return *this;
|
||||
IOWarningInFunction((*this))
|
||||
<< "keyword " << keyword
|
||||
<< " found but not a sub-dictionary in dictionary "
|
||||
<< name() << endl;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -726,10 +499,10 @@ Foam::wordList Foam::dictionary::toc() const
|
||||
{
|
||||
wordList keys(size());
|
||||
|
||||
label nKeys = 0;
|
||||
forAllConstIter(parent_type, *this, iter)
|
||||
label n = 0;
|
||||
forAllConstIters(*this, iter)
|
||||
{
|
||||
keys[nKeys++] = iter().keyword();
|
||||
keys[n++] = iter().keyword();
|
||||
}
|
||||
|
||||
return keys;
|
||||
@ -746,15 +519,15 @@ Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns) const
|
||||
{
|
||||
List<keyType> keys(size());
|
||||
|
||||
label nKeys = 0;
|
||||
forAllConstIter(parent_type, *this, iter)
|
||||
label n = 0;
|
||||
forAllConstIters(*this, iter)
|
||||
{
|
||||
if (iter().keyword().isPattern() ? patterns : !patterns)
|
||||
{
|
||||
keys[nKeys++] = iter().keyword();
|
||||
keys[n++] = iter().keyword();
|
||||
}
|
||||
}
|
||||
keys.setSize(nKeys);
|
||||
keys.setSize(n);
|
||||
|
||||
return keys;
|
||||
}
|
||||
@ -796,16 +569,15 @@ bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IOWarningInFunction((*this))
|
||||
<< "problem replacing entry "<< entryPtr->keyword()
|
||||
<< " in dictionary " << name() << endl;
|
||||
|
||||
parent_type::remove(entryPtr);
|
||||
delete entryPtr;
|
||||
return false;
|
||||
}
|
||||
|
||||
IOWarningInFunction((*this))
|
||||
<< "problem replacing entry "<< entryPtr->keyword()
|
||||
<< " in dictionary " << name() << endl;
|
||||
|
||||
parent_type::remove(entryPtr);
|
||||
delete entryPtr;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -825,16 +597,15 @@ bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IOWarningInFunction((*this))
|
||||
<< "attempt to add entry "<< entryPtr->keyword()
|
||||
<< " which already exists in dictionary " << name()
|
||||
<< endl;
|
||||
|
||||
delete entryPtr;
|
||||
return false;
|
||||
}
|
||||
|
||||
IOWarningInFunction((*this))
|
||||
<< "attempt to add entry "<< entryPtr->keyword()
|
||||
<< " which already exists in dictionary " << name()
|
||||
<< endl;
|
||||
|
||||
delete entryPtr;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -844,55 +615,55 @@ void Foam::dictionary::add(const entry& e, bool mergeEntry)
|
||||
}
|
||||
|
||||
|
||||
void Foam::dictionary::add(const keyType& k, const word& w, bool overwrite)
|
||||
void Foam::dictionary::add(const keyType& k, const word& v, bool overwrite)
|
||||
{
|
||||
add(new primitiveEntry(k, token(w)), overwrite);
|
||||
add(new primitiveEntry(k, token(v)), overwrite);
|
||||
}
|
||||
|
||||
|
||||
void Foam::dictionary::add
|
||||
(
|
||||
const keyType& k,
|
||||
const Foam::string& s,
|
||||
const Foam::string& v,
|
||||
bool overwrite
|
||||
)
|
||||
{
|
||||
add(new primitiveEntry(k, token(s)), overwrite);
|
||||
add(new primitiveEntry(k, token(v)), overwrite);
|
||||
}
|
||||
|
||||
|
||||
void Foam::dictionary::add(const keyType& k, const label l, bool overwrite)
|
||||
void Foam::dictionary::add(const keyType& k, const label v, bool overwrite)
|
||||
{
|
||||
add(new primitiveEntry(k, token(l)), overwrite);
|
||||
add(new primitiveEntry(k, token(v)), overwrite);
|
||||
}
|
||||
|
||||
|
||||
void Foam::dictionary::add(const keyType& k, const scalar s, bool overwrite)
|
||||
void Foam::dictionary::add(const keyType& k, const scalar v, bool overwrite)
|
||||
{
|
||||
add(new primitiveEntry(k, token(s)), overwrite);
|
||||
add(new primitiveEntry(k, token(v)), overwrite);
|
||||
}
|
||||
|
||||
|
||||
void Foam::dictionary::add
|
||||
(
|
||||
const keyType& k,
|
||||
const dictionary& d,
|
||||
const dictionary& v,
|
||||
bool mergeEntry
|
||||
)
|
||||
{
|
||||
add(new dictionaryEntry(k, *this, d), mergeEntry);
|
||||
add(new dictionaryEntry(k, *this, v), mergeEntry);
|
||||
}
|
||||
|
||||
|
||||
void Foam::dictionary::set(entry* entryPtr)
|
||||
{
|
||||
// Find non-recursive with patterns
|
||||
entry* existingPtr = lookupEntryPtr(entryPtr->keyword(), false, true);
|
||||
auto finder = search(entryPtr->keyword(), false, true);
|
||||
|
||||
// Clear dictionary so merge acts like overwrite
|
||||
if (existingPtr && existingPtr->isDict())
|
||||
if (finder.isDict())
|
||||
{
|
||||
existingPtr->dict().clear();
|
||||
finder.dict().clear();
|
||||
}
|
||||
add(entryPtr, true);
|
||||
}
|
||||
@ -904,134 +675,14 @@ void Foam::dictionary::set(const entry& e)
|
||||
}
|
||||
|
||||
|
||||
void Foam::dictionary::set(const keyType& k, const dictionary& d)
|
||||
void Foam::dictionary::set(const keyType& k, const dictionary& v)
|
||||
{
|
||||
set(new dictionaryEntry(k, *this, d));
|
||||
}
|
||||
|
||||
|
||||
bool Foam::dictionary::remove(const word& keyword)
|
||||
{
|
||||
auto iter = hashedEntries_.find(keyword);
|
||||
|
||||
if (iter.found())
|
||||
{
|
||||
// Delete from patterns
|
||||
pattern_iterator wcLink = patterns_.begin();
|
||||
regexp_iterator reLink = regexps_.begin();
|
||||
|
||||
// Find in pattern using exact match only
|
||||
if (findInPatterns(false, keyword, wcLink, reLink))
|
||||
{
|
||||
patterns_.remove(wcLink);
|
||||
regexps_.remove(reLink);
|
||||
}
|
||||
|
||||
parent_type::remove(iter());
|
||||
delete iter();
|
||||
hashedEntries_.erase(iter);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::dictionary::changeKeyword
|
||||
(
|
||||
const keyType& oldKeyword,
|
||||
const keyType& newKeyword,
|
||||
bool forceOverwrite
|
||||
)
|
||||
{
|
||||
// No change
|
||||
if (oldKeyword == newKeyword)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that oldKeyword exists and can be changed
|
||||
auto iter = hashedEntries_.find(oldKeyword);
|
||||
|
||||
if (!iter.found())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iter()->keyword().isPattern())
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
*this
|
||||
) << "Old keyword "<< oldKeyword
|
||||
<< " is a pattern."
|
||||
<< "Pattern replacement not yet implemented."
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
|
||||
auto iter2 = hashedEntries_.find(newKeyword);
|
||||
|
||||
// newKeyword already exists
|
||||
if (iter2.found())
|
||||
{
|
||||
if (forceOverwrite)
|
||||
{
|
||||
if (iter2()->keyword().isPattern())
|
||||
{
|
||||
// Delete from patterns
|
||||
pattern_iterator wcLink = patterns_.begin();
|
||||
regexp_iterator reLink = regexps_.begin();
|
||||
|
||||
// Find in patterns using exact match only
|
||||
if (findInPatterns(false, iter2()->keyword(), wcLink, reLink))
|
||||
{
|
||||
patterns_.remove(wcLink);
|
||||
regexps_.remove(reLink);
|
||||
}
|
||||
}
|
||||
|
||||
parent_type::replace(iter2(), iter());
|
||||
delete iter2();
|
||||
hashedEntries_.erase(iter2);
|
||||
}
|
||||
else
|
||||
{
|
||||
IOWarningInFunction
|
||||
(
|
||||
*this
|
||||
) << "cannot rename keyword "<< oldKeyword
|
||||
<< " to existing keyword " << newKeyword
|
||||
<< " in dictionary " << name() << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Change name and HashTable, but leave DL-List untouched
|
||||
iter()->keyword() = newKeyword;
|
||||
iter()->name() = name() + '.' + newKeyword;
|
||||
hashedEntries_.erase(oldKeyword);
|
||||
hashedEntries_.insert(newKeyword, iter());
|
||||
|
||||
if (newKeyword.isPattern())
|
||||
{
|
||||
patterns_.insert(iter());
|
||||
regexps_.insert
|
||||
(
|
||||
autoPtr<regExp>(new regExp(newKeyword))
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
set(new dictionaryEntry(k, *this, v));
|
||||
}
|
||||
|
||||
|
||||
bool Foam::dictionary::merge(const dictionary& dict)
|
||||
{
|
||||
// Check for assignment to self
|
||||
if (this == &dict)
|
||||
{
|
||||
FatalIOErrorInFunction(*this)
|
||||
@ -1041,7 +692,7 @@ bool Foam::dictionary::merge(const dictionary& dict)
|
||||
|
||||
bool changed = false;
|
||||
|
||||
forAllConstIter(parent_type, dict, iter)
|
||||
forAllConstIters(dict, iter)
|
||||
{
|
||||
auto fnd = hashedEntries_.find(iter().keyword());
|
||||
|
||||
@ -1112,7 +763,6 @@ Foam::ITstream& Foam::dictionary::operator[](const word& keyword) const
|
||||
|
||||
void Foam::dictionary::operator=(const dictionary& rhs)
|
||||
{
|
||||
// Check for assignment to self
|
||||
if (this == &rhs)
|
||||
{
|
||||
FatalIOErrorInFunction(*this)
|
||||
@ -1126,7 +776,7 @@ void Foam::dictionary::operator=(const dictionary& rhs)
|
||||
// Create clones of the entries in the given dictionary
|
||||
// resetting the parentDict to this dictionary
|
||||
|
||||
forAllConstIter(parent_type, rhs, iter)
|
||||
forAllConstIters(rhs, iter)
|
||||
{
|
||||
add(iter().clone(*this).ptr());
|
||||
}
|
||||
@ -1135,15 +785,15 @@ void Foam::dictionary::operator=(const dictionary& rhs)
|
||||
|
||||
void Foam::dictionary::operator+=(const dictionary& rhs)
|
||||
{
|
||||
// Check for assignment to self
|
||||
if (this == &rhs)
|
||||
{
|
||||
FatalIOErrorInFunction(*this)
|
||||
<< "attempted addition assignment to self for dictionary " << name()
|
||||
<< "attempted addition assignment to self for dictionary "
|
||||
<< name()
|
||||
<< abort(FatalIOError);
|
||||
}
|
||||
|
||||
forAllConstIter(parent_type, rhs, iter)
|
||||
forAllConstIters(rhs, iter)
|
||||
{
|
||||
add(iter().clone(*this).ptr());
|
||||
}
|
||||
@ -1152,15 +802,15 @@ void Foam::dictionary::operator+=(const dictionary& rhs)
|
||||
|
||||
void Foam::dictionary::operator|=(const dictionary& rhs)
|
||||
{
|
||||
// Check for assignment to self
|
||||
if (this == &rhs)
|
||||
{
|
||||
FatalIOErrorInFunction(*this)
|
||||
<< "attempted assignment to self for dictionary " << name()
|
||||
<< "attempted assignment to self for dictionary "
|
||||
<< name()
|
||||
<< abort(FatalIOError);
|
||||
}
|
||||
|
||||
forAllConstIter(parent_type, rhs, iter)
|
||||
forAllConstIters(rhs, iter)
|
||||
{
|
||||
if (!found(iter().keyword()))
|
||||
{
|
||||
@ -1172,15 +822,15 @@ void Foam::dictionary::operator|=(const dictionary& rhs)
|
||||
|
||||
void Foam::dictionary::operator<<=(const dictionary& rhs)
|
||||
{
|
||||
// Check for assignment to self
|
||||
if (this == &rhs)
|
||||
{
|
||||
FatalIOErrorInFunction(*this)
|
||||
<< "attempted assignment to self for dictionary " << name()
|
||||
<< "attempted assignment to self for dictionary "
|
||||
<< name()
|
||||
<< abort(FatalIOError);
|
||||
}
|
||||
|
||||
forAllConstIter(parent_type, rhs, iter)
|
||||
forAllConstIters(rhs, iter)
|
||||
{
|
||||
set(iter().clone(*this).ptr());
|
||||
}
|
||||
|
||||
@ -41,10 +41,13 @@ Description
|
||||
|
||||
Note
|
||||
Within dictionaries, entries can be referenced by using the '$' syntax
|
||||
familiar from shell programming. A '.' separator is used when referencing
|
||||
sub-dictionary entries. Leading '.' prefixes can be used to specify
|
||||
an entry from a parent directory. A leading ':' or '^' prefix specifies
|
||||
starting from the top-level entry. For example,
|
||||
familiar from shell programming.
|
||||
A '.' separator is used when referencing sub-dictionary entries.
|
||||
Leading '.' prefixes can be used to specify an entry from a parent
|
||||
dictionary.
|
||||
An initial '^' anchor (or ':' for backward compatibility) specifies
|
||||
starting from the top-level entry.
|
||||
For example,
|
||||
|
||||
\verbatim
|
||||
key1 val1;
|
||||
@ -70,6 +73,7 @@ Note
|
||||
SourceFiles
|
||||
dictionary.C
|
||||
dictionaryIO.C
|
||||
dictionarySearch.C
|
||||
|
||||
SeeAlso
|
||||
- Foam::entry
|
||||
@ -89,6 +93,7 @@ SeeAlso
|
||||
#include "HashTable.H"
|
||||
#include "wordList.H"
|
||||
#include "className.H"
|
||||
#include <type_traits>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -148,22 +153,20 @@ public:
|
||||
const word dictName() const
|
||||
{
|
||||
const word scopedName = name_.name();
|
||||
const std::string::size_type i = scopedName.rfind('.');
|
||||
const auto i = scopedName.rfind('.');
|
||||
|
||||
if (i == std::string::npos)
|
||||
{
|
||||
return scopedName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return scopedName.substr(i+1);
|
||||
}
|
||||
|
||||
return scopedName.substr(i+1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class dictionary Declaration
|
||||
Class dictionary Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class dictionary
|
||||
@ -171,15 +174,157 @@ class dictionary
|
||||
public dictionaryName,
|
||||
public IDLList<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
|
||||
|
||||
//- Report optional keywords and values if not present in dictionary
|
||||
// Set/unset via an InfoSwitch
|
||||
static bool writeOptionalEntries;
|
||||
|
||||
//- Parent dictionary
|
||||
const dictionary& parent_;
|
||||
|
||||
//- HashTable of the entries held on the IDLList for quick lookup
|
||||
//- Quick lookup of the entries held on the IDLList
|
||||
HashTable<entry*> hashedEntries_;
|
||||
|
||||
//- Entries of matching patterns
|
||||
@ -196,28 +341,49 @@ class dictionary
|
||||
|
||||
typedef DLList<entry*>::iterator pattern_iterator;
|
||||
typedef DLList<entry*>::const_iterator pattern_const_iterator;
|
||||
|
||||
typedef DLList<autoPtr<regExp>>::iterator regexp_iterator;
|
||||
typedef DLList<autoPtr<regExp>>::const_iterator regexp_const_iterator;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Find and return an entry data stream pointer if present
|
||||
// otherwise return nullptr. Allows scoping using '.'
|
||||
const entry* lookupScopedSubEntryPtr
|
||||
//- Search using a '.' for scoping.
|
||||
// A leading dot means to use the parent dictionary.
|
||||
// An intermediate dot separates a sub-dictionary or sub-entry.
|
||||
// However, the use of dots is unfortunately ambiguous.
|
||||
// The value "a.b.c.d" could be a first-level entry, a second-level
|
||||
// entry (eg, "a" with "b.c.d", "a.b" with "c.d" etc),
|
||||
// or just about any other combination.
|
||||
// The heuristic tries sucessively longer top-level entries
|
||||
// until there is a suitable match.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
const_searcher csearchDotScoped
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
|
||||
//- Search using a '/' for scoping.
|
||||
// Semantics as per normal files: an intermediate "." is the current
|
||||
// dictionary level, an intermediate ".." is the parent dictionary.
|
||||
// Note that since a slash is not a valid word character, there is no
|
||||
// ambiguity between separator and content.
|
||||
// No possibility or need for recursion.
|
||||
//
|
||||
// \param patternMatch use regular expressions
|
||||
const_searcher csearchSlashScoped
|
||||
(
|
||||
const word& keyword,
|
||||
bool patternMatch
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Declare friendship with the entry class for IO
|
||||
friend class entry;
|
||||
|
||||
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("dictionary");
|
||||
|
||||
@ -234,7 +400,7 @@ public:
|
||||
explicit dictionary(const fileName& name);
|
||||
|
||||
//- Construct given the entry name, parent dictionary and Istream,
|
||||
// reading entries until lastEntry or EOF
|
||||
// reading entries until EOF
|
||||
dictionary
|
||||
(
|
||||
const fileName& name,
|
||||
@ -248,10 +414,10 @@ public:
|
||||
|
||||
//- Construct top-level dictionary from Istream,
|
||||
// reading entries until EOF, optionally keeping the header
|
||||
dictionary(Istream& is, const bool keepHeader);
|
||||
dictionary(Istream& is, bool keepHeader);
|
||||
|
||||
//- Construct as copy given the parent dictionary
|
||||
dictionary(const dictionary& parentDict, const dictionary&);
|
||||
dictionary(const dictionary& parentDict, const dictionary& dict);
|
||||
|
||||
//- Construct top-level dictionary as copy
|
||||
dictionary(const dictionary& dict);
|
||||
@ -303,284 +469,436 @@ public:
|
||||
tokenList tokens() const;
|
||||
|
||||
|
||||
// Search and lookup
|
||||
// Search and lookup
|
||||
|
||||
//- Search dictionary for given keyword
|
||||
// If recursive, search parent dictionaries
|
||||
// If patternMatch, use regular expressions
|
||||
bool found
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
//- Search dictionary for given keyword.
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
bool found
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Find and return an entry data stream pointer if present
|
||||
// otherwise return nullptr.
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions
|
||||
const entry* lookupEntryPtr
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
//- Find and return an entry pointer if present, or return a nullptr.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
const entry* lookupEntryPtr
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
|
||||
//- Find and return an entry data stream pointer for manipulation
|
||||
// if present otherwise return nullptr.
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions.
|
||||
entry* lookupEntryPtr
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
);
|
||||
//- Find and return an entry pointer for manipulation if present,
|
||||
// or return a nullptr.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
entry* lookupEntryPtr
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
);
|
||||
|
||||
//- Find and return an entry data stream if present otherwise error.
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions.
|
||||
const entry& lookupEntry
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
//- Find and return an entry if present otherwise error.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
const entry& lookupEntry
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
|
||||
//- Find and return an entry data stream
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions.
|
||||
ITstream& lookup
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
//- Find and return an entry data stream.
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
ITstream& lookup
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Find and return a T,
|
||||
// if not found throw a fatal error.
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions.
|
||||
template<class T>
|
||||
T lookupType
|
||||
(
|
||||
const word&,
|
||||
bool recursive=false,
|
||||
bool patternMatch=true
|
||||
) const;
|
||||
//- Find and return a T. FatalError if not found.
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
template<class T>
|
||||
T lookupType
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Find and return a T, or return the given default value
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions.
|
||||
template<class T>
|
||||
T lookupOrDefault
|
||||
(
|
||||
const word& keyword,
|
||||
const T& deflt,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
//- Find and return a T, or return the given default value
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
template<class T>
|
||||
T lookupOrDefault
|
||||
(
|
||||
const word& keyword,
|
||||
const T& deflt,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Find and return a T, if not found return the given
|
||||
// default value, and add to dictionary.
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions.
|
||||
template<class T>
|
||||
T lookupOrAddDefault
|
||||
(
|
||||
const word& keyword,
|
||||
const T& deflt,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
);
|
||||
//- Find and return a T, if not found return the default value
|
||||
// and add it to dictionary.
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
template<class T>
|
||||
T lookupOrAddDefault
|
||||
(
|
||||
const word& keyword,
|
||||
const T& deflt,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
);
|
||||
|
||||
//- Find an entry if present, and assign to T
|
||||
// Returns true if the entry was found.
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions.
|
||||
template<class T>
|
||||
bool readIfPresent
|
||||
(
|
||||
const word& keyword,
|
||||
T& val,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
//- Find an entry if present, and assign to T val.
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param val the value to read
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
//
|
||||
// \return true if the entry was found.
|
||||
template<class T>
|
||||
bool readIfPresent
|
||||
(
|
||||
const word& keyword,
|
||||
T& val,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Find and return an entry data stream pointer if present
|
||||
// otherwise return nullptr. Allows scoping using '.'.
|
||||
// Special handling for ':' at start of keyword and '..'.
|
||||
const entry* lookupScopedEntryPtr
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
//- Find and return an entry pointer if present, or return a nullptr.
|
||||
// Allows scoping using '.'.
|
||||
// Special handling for an absolute anchor (^) at start of the keyword
|
||||
// and for '..' to ascend into the parent dictionaries.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
const entry* lookupScopedEntryPtr
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
|
||||
//- Check if entry is a sub-dictionary
|
||||
bool isDict(const word& keyword) const;
|
||||
//- Check if entry exists and is a sub-dictionary.
|
||||
//
|
||||
// Search type: non-recursive with patterns.
|
||||
bool isDict(const word& keyword) const;
|
||||
|
||||
//- Find and return a sub-dictionary pointer if present
|
||||
// otherwise return nullptr.
|
||||
const dictionary* subDictPtr(const word& keyword) const;
|
||||
//- Find and return a sub-dictionary pointer if present
|
||||
// (and a sub-dictionary) otherwise return nullptr.
|
||||
//
|
||||
// Search type: non-recursive with patterns.
|
||||
const dictionary* subDictPtr(const word& keyword) const;
|
||||
|
||||
//- Find and return a sub-dictionary pointer if present
|
||||
// otherwise return nullptr.
|
||||
dictionary* subDictPtr(const word& keyword);
|
||||
//- Find and return a sub-dictionary pointer if present
|
||||
// (and a sub-dictionary) otherwise return nullptr.
|
||||
//
|
||||
// Search type: non-recursive with patterns.
|
||||
dictionary* subDictPtr(const word& keyword);
|
||||
|
||||
//- Find and return a sub-dictionary
|
||||
const dictionary& subDict(const word& keyword) const;
|
||||
//- Find and return a sub-dictionary.
|
||||
// Fatal if the entry does not exist or is not a sub-dictionary.
|
||||
//
|
||||
// Search type: non-recursive with patterns.
|
||||
const dictionary& subDict(const word& keyword) const;
|
||||
|
||||
//- Find and return a sub-dictionary for manipulation
|
||||
dictionary& subDict(const word& keyword);
|
||||
//- Find and return a sub-dictionary for manipulation.
|
||||
// Fatal if the entry does not exist or is not a sub-dictionary.
|
||||
//
|
||||
// Search type: non-recursive with patterns.
|
||||
dictionary& subDict(const word& keyword);
|
||||
|
||||
//- Find and return a sub-dictionary as a copy, or
|
||||
// return an empty dictionary if the sub-dictionary does not exist
|
||||
dictionary subOrEmptyDict
|
||||
(
|
||||
const word& keyword,
|
||||
const bool mustRead = false
|
||||
) const;
|
||||
//- Find and return a sub-dictionary as a copy, otherwise return
|
||||
// an empty dictionary.
|
||||
// Warn if the entry exists but is not a sub-dictionary.
|
||||
//
|
||||
// Search type: non-recursive with patterns.
|
||||
dictionary subOrEmptyDict
|
||||
(
|
||||
const word& keyword,
|
||||
const bool mustRead = false
|
||||
) const;
|
||||
|
||||
//- Find and return a sub-dictionary if found
|
||||
// otherwise return this dictionary
|
||||
const dictionary& optionalSubDict(const word&) const;
|
||||
//- Find and return a sub-dictionary, otherwise return this dictionary.
|
||||
// Warn if the entry exists but is not a sub-dictionary.
|
||||
//
|
||||
// Search type: non-recursive with patterns.
|
||||
const dictionary& optionalSubDict(const word& keyword) const;
|
||||
|
||||
//- Return the table of contents
|
||||
wordList toc() const;
|
||||
//- Return the table of contents
|
||||
wordList toc() const;
|
||||
|
||||
//- Return the sorted table of contents
|
||||
wordList sortedToc() const;
|
||||
//- Return the sorted table of contents
|
||||
wordList sortedToc() const;
|
||||
|
||||
//- Return table of contents sorted using the specified comparator
|
||||
template<class Compare>
|
||||
wordList sortedToc(const Compare& comp) const;
|
||||
//- Return table of contents sorted using the specified comparator
|
||||
template<class Compare>
|
||||
wordList sortedToc(const Compare& comp) const;
|
||||
|
||||
//- Return the list of available keys or patterns
|
||||
List<keyType> keys(bool patterns = false) const;
|
||||
//- Return the list of available keys or patterns
|
||||
List<keyType> keys(bool patterns = false) const;
|
||||
|
||||
|
||||
// Editing
|
||||
// Editing
|
||||
|
||||
//- Substitute the given keyword prepended by '$' with the
|
||||
// corresponding sub-dictionary entries
|
||||
bool substituteKeyword(const word& keyword, bool mergeEntry=false);
|
||||
//- Substitute the given keyword (which is prefixed by '$')
|
||||
// with the corresponding sub-dictionary entries
|
||||
bool substituteKeyword
|
||||
(
|
||||
const word& keyword,
|
||||
bool mergeEntry = false
|
||||
);
|
||||
|
||||
//- Substitute the given scoped keyword prepended by '$' with the
|
||||
// corresponding sub-dictionary entries
|
||||
bool substituteScopedKeyword
|
||||
(
|
||||
const word& keyword,
|
||||
bool mergeEntry=false
|
||||
);
|
||||
//- Substitute the given scoped keyword (which is prefixed by '$')
|
||||
// with the corresponding sub-dictionary entries
|
||||
bool substituteScopedKeyword
|
||||
(
|
||||
const word& keyword,
|
||||
bool mergeEntry = false
|
||||
);
|
||||
|
||||
//- Add a new entry
|
||||
// With the merge option, dictionaries are interwoven and
|
||||
// primitive entries are overwritten
|
||||
bool add(entry* entryPtr, bool mergeEntry=false);
|
||||
//- Add a new entry.
|
||||
// \param mergeEntry dictionaries are interwoven and primitive
|
||||
// entries are overwritten
|
||||
bool add(entry* entryPtr, bool mergeEntry=false);
|
||||
|
||||
//- Add an entry
|
||||
// With the merge option, dictionaries are interwoven and
|
||||
// primitive entries are overwritten
|
||||
void add(const entry& e, bool mergeEntry=false);
|
||||
//- Add an entry.
|
||||
// \param mergeEntry dictionaries are interwoven and primitive
|
||||
// entries are overwritten
|
||||
void add(const entry& e, bool mergeEntry=false);
|
||||
|
||||
//- Add a word entry
|
||||
// optionally overwrite an existing entry
|
||||
void add(const keyType& k, const word& w, bool overwrite=false);
|
||||
//- Add a word entry.
|
||||
// \param overwrite force overwrite of an existing entry.
|
||||
void add(const keyType& k, const word& v, bool overwrite=false);
|
||||
|
||||
//- Add a string entry
|
||||
// optionally overwrite an existing entry
|
||||
void add(const keyType& k, const string& s, bool overwrite=false);
|
||||
//- Add a string entry.
|
||||
// \param overwrite force overwrite of an existing entry.
|
||||
void add(const keyType& k, const string& v, bool overwrite=false);
|
||||
|
||||
//- Add a label entry
|
||||
// optionally overwrite an existing entry
|
||||
void add(const keyType&, const label l, bool overwrite=false);
|
||||
//- Add a label entry.
|
||||
// \param overwrite force overwrite of an existing entry.
|
||||
void add(const keyType& k, const label v, bool overwrite=false);
|
||||
|
||||
//- Add a scalar entry
|
||||
// optionally overwrite an existing entry
|
||||
void add(const keyType&, const scalar s, bool overwrite=false);
|
||||
//- Add a scalar entry.
|
||||
// \param overwrite force overwrite of an existing entry.
|
||||
void add(const keyType& k, const scalar v, bool overwrite=false);
|
||||
|
||||
//- Add a dictionary entry
|
||||
// optionally merge with an existing sub-dictionary
|
||||
void add
|
||||
(
|
||||
const keyType& k,
|
||||
const dictionary& d,
|
||||
bool mergeEntry = false
|
||||
);
|
||||
//- Add a dictionary entry.
|
||||
// \param mergeEntry merge into an existing sub-dictionary
|
||||
void add
|
||||
(
|
||||
const keyType& k,
|
||||
const dictionary& d,
|
||||
bool mergeEntry = false
|
||||
);
|
||||
|
||||
//- Add a T entry
|
||||
// optionally overwrite an existing entry
|
||||
template<class T>
|
||||
void add(const keyType& k, const T& t, bool overwrite=false);
|
||||
//- Add a T entry
|
||||
// \param overwrite force overwrite of existing entry
|
||||
template<class T>
|
||||
void add(const keyType& k, const T& v, bool overwrite=false);
|
||||
|
||||
//- Assign a new entry, overwrite any existing entry
|
||||
void set(entry* entryPtr);
|
||||
//- Assign a new entry, overwriting any existing entry.
|
||||
void set(entry* entryPtr);
|
||||
|
||||
//- Assign a new entry, overwrite any existing entry
|
||||
void set(const entry& e);
|
||||
//- Assign a new entry, overwriting any existing entry.
|
||||
void set(const entry& e);
|
||||
|
||||
//- Assign a dictionary entry, overwrite any existing entry
|
||||
void set(const keyType& k, const dictionary& d);
|
||||
//- Assign a dictionary entry, overwriting any existing entry.
|
||||
void set(const keyType& k, const dictionary& v);
|
||||
|
||||
//- Assign a T entry, overwrite any existing entry
|
||||
template<class T>
|
||||
void set(const keyType& k, const T& t);
|
||||
//- Assign a T entry, overwriting any existing entry.
|
||||
template<class T>
|
||||
void set(const keyType& k, const T& v);
|
||||
|
||||
//- Remove an entry specified by keyword
|
||||
bool remove(const word& Keyword);
|
||||
//- Remove an entry specified by keyword
|
||||
bool remove(const word& keyword);
|
||||
|
||||
//- Change the keyword for an entry,
|
||||
// optionally forcing overwrite of an existing entry
|
||||
bool changeKeyword
|
||||
(
|
||||
const keyType& oldKeyword,
|
||||
const keyType& newKeyword,
|
||||
bool forceOverwrite=false
|
||||
);
|
||||
//- Change the keyword for an entry,
|
||||
// \param overwrite force overwrite of an existing entry.
|
||||
bool changeKeyword
|
||||
(
|
||||
const keyType& oldKeyword,
|
||||
const keyType& newKeyword,
|
||||
bool overwrite=false
|
||||
);
|
||||
|
||||
//- Merge entries from the given dictionary.
|
||||
// Also merge sub-dictionaries as required.
|
||||
bool merge(const dictionary& dict);
|
||||
//- Merge entries from the given dictionary.
|
||||
// Also merge sub-dictionaries as required.
|
||||
bool merge(const dictionary& dict);
|
||||
|
||||
//- Clear the dictionary
|
||||
void clear();
|
||||
//- Clear the dictionary
|
||||
void clear();
|
||||
|
||||
//- Transfer the contents of the argument and annul the argument.
|
||||
void transfer(dictionary& dict);
|
||||
//- Transfer the contents of the argument and annul the argument.
|
||||
void transfer(dictionary& dict);
|
||||
|
||||
//- Transfer contents to the Xfer container
|
||||
Xfer<dictionary> xfer();
|
||||
//- Transfer contents to the Xfer container
|
||||
Xfer<dictionary> xfer();
|
||||
|
||||
|
||||
// Read
|
||||
// Read
|
||||
|
||||
//- Read dictionary from Istream
|
||||
bool read(Istream& is);
|
||||
//- Read dictionary from Istream
|
||||
bool read(Istream& is);
|
||||
|
||||
//- Read dictionary from Istream, optionally keeping the header
|
||||
bool read(Istream& is, const bool keepHeader);
|
||||
//- Read dictionary from Istream, optionally keeping the header
|
||||
bool read(Istream& is, bool keepHeader);
|
||||
|
||||
|
||||
// Write
|
||||
// Write
|
||||
|
||||
//- Write sub-dictionary with the keyword as its header
|
||||
void writeEntry(const keyType& keyword, Ostream& os) const;
|
||||
//- Write sub-dictionary with the keyword as its header
|
||||
void writeEntry(const keyType& keyword, Ostream& os) const;
|
||||
|
||||
//- Write dictionary entries.
|
||||
// Optionally with extra new line between entries for
|
||||
// "top-level" dictionaries
|
||||
void writeEntries(Ostream& os, const bool extraNewLine=false) const;
|
||||
//- Write dictionary entries.
|
||||
// \param extraNewLine adds additional newline\n between entries
|
||||
// for "top-level" dictionaries
|
||||
void writeEntries(Ostream& os, const bool extraNewLine=false) const;
|
||||
|
||||
//- Write dictionary, normally with sub-dictionary formatting
|
||||
void write(Ostream& os, const bool subDict=true) const;
|
||||
//- Write dictionary, normally with sub-dictionary formatting
|
||||
void write(Ostream& os, const bool subDict=true) const;
|
||||
|
||||
|
||||
// Searching
|
||||
|
||||
//- Search dictionary for given keyword
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
const_searcher csearch
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Search dictionary for given keyword
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
const_searcher search
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Search dictionary for given keyword
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
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.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
const_searcher csearchScoped
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
|
||||
//- Search using dot or slash scoping.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
const_searcher searchScoped
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
|
||||
//- Search using dot or slash scoping.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
searcher searchScoped
|
||||
(
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
);
|
||||
|
||||
//- Locate a sub-dictionary using slash-scoping
|
||||
// \return nullptr if the dictionary path does not exist
|
||||
const dictionary* cfindScopedDictPtr(const fileName& dictPath) const;
|
||||
|
||||
//- Locate a sub-dictionary using slash-scoping
|
||||
// \return nullptr if the dictionary path does not exist
|
||||
const dictionary* findScopedDictPtr(const fileName& dictPath) const;
|
||||
|
||||
//- Locate a sub-dictionary using slash-scoping
|
||||
// \return nullptr if the dictionary path does not exist
|
||||
dictionary* findScopedDictPtr(const fileName& dictPath);
|
||||
|
||||
//- Locate existing or create sub-dictionary using slash-scoping
|
||||
// \return nullptr if the dictionary path could not be created
|
||||
dictionary* makeScopedDictPtr(const fileName& dictPath);
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Find and return entry
|
||||
//- Find and return an entry data stream (identical to #lookup method).
|
||||
// Default search: non-recursive with patterns.
|
||||
//
|
||||
// \param recursive search parent dictionaries
|
||||
// \param patternMatch use regular expressions
|
||||
ITstream& operator[](const word& keyword) const;
|
||||
|
||||
//- Copy assignment
|
||||
void operator=(const dictionary& rhs);
|
||||
|
||||
//- Include entries from the given dictionary.
|
||||
|
||||
@ -55,7 +55,7 @@ Foam::dictionary::dictionary(Istream& is)
|
||||
}
|
||||
|
||||
|
||||
Foam::dictionary::dictionary(Istream& is, const bool keepHeader)
|
||||
Foam::dictionary::dictionary(Istream& is, bool keepHeader)
|
||||
:
|
||||
dictionaryName(is.name()),
|
||||
parent_(dictionary::null)
|
||||
@ -77,8 +77,14 @@ Foam::autoPtr<Foam::dictionary> Foam::dictionary::New(Istream& is)
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::dictionary::read(Istream& is, const bool keepHeader)
|
||||
bool Foam::dictionary::read(Istream& is, bool keepHeader)
|
||||
{
|
||||
// Normally remove FoamFile header when read, but avoid this if it already
|
||||
// existed prior to the current read.
|
||||
// We would otherwise lose it with every top-level '#include ...'
|
||||
|
||||
keepHeader = keepHeader || hashedEntries_.found("FoamFile");
|
||||
|
||||
// Check for empty dictionary
|
||||
if (is.eof())
|
||||
{
|
||||
@ -103,7 +109,6 @@ bool Foam::dictionary::read(Istream& is, const bool keepHeader)
|
||||
while (!is.eof() && entry::New(*this, is))
|
||||
{}
|
||||
|
||||
// Normally remove the FoamFile header entry if it exists
|
||||
if (!keepHeader)
|
||||
{
|
||||
remove("FoamFile");
|
||||
@ -128,30 +133,6 @@ bool Foam::dictionary::read(Istream& is)
|
||||
}
|
||||
|
||||
|
||||
bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry)
|
||||
{
|
||||
const word varName = keyword.substr(1);
|
||||
|
||||
// Lookup the variable name in the given dictionary
|
||||
const entry* ePtr = lookupEntryPtr(varName, true, true);
|
||||
|
||||
// If defined insert its entries into this dictionary
|
||||
if (ePtr != nullptr)
|
||||
{
|
||||
const dictionary& addDict = ePtr->dict();
|
||||
|
||||
forAllConstIter(parent_type, addDict, iter)
|
||||
{
|
||||
add(iter(), mergeEntry);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Istream Operator * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::Istream& Foam::operator>>(Istream& is, dictionary& dict)
|
||||
|
||||
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 overwrite
|
||||
)
|
||||
{
|
||||
// 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 (overwrite)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -43,9 +43,9 @@ T Foam::dictionary::lookupType
|
||||
bool patternMatch
|
||||
) const
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
||||
auto finder = csearch(keyword, recursive, patternMatch);
|
||||
|
||||
if (entryPtr == nullptr)
|
||||
if (!finder.found())
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
@ -55,7 +55,7 @@ T Foam::dictionary::lookupType
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
return pTraits<T>(entryPtr->stream());
|
||||
return pTraits<T>(finder.ptr()->stream());
|
||||
}
|
||||
|
||||
|
||||
@ -68,24 +68,22 @@ T Foam::dictionary::lookupOrDefault
|
||||
bool patternMatch
|
||||
) const
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
||||
auto finder = csearch(keyword, recursive, patternMatch);
|
||||
|
||||
if (entryPtr)
|
||||
if (finder.found())
|
||||
{
|
||||
return pTraits<T>(entryPtr->stream());
|
||||
return pTraits<T>(finder.ptr()->stream());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (writeOptionalEntries)
|
||||
{
|
||||
IOInfoInFunction(*this)
|
||||
<< "Optional entry '" << keyword << "' is not present,"
|
||||
<< " returning the default value '" << deflt << "'"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return deflt;
|
||||
if (writeOptionalEntries)
|
||||
{
|
||||
IOInfoInFunction(*this)
|
||||
<< "Optional entry '" << keyword << "' is not present,"
|
||||
<< " returning the default value '" << deflt << "'"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return deflt;
|
||||
}
|
||||
|
||||
|
||||
@ -98,25 +96,23 @@ T Foam::dictionary::lookupOrAddDefault
|
||||
bool patternMatch
|
||||
)
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
||||
auto finder = csearch(keyword, recursive, patternMatch);
|
||||
|
||||
if (entryPtr)
|
||||
if (finder.found())
|
||||
{
|
||||
return pTraits<T>(entryPtr->stream());
|
||||
return pTraits<T>(finder.ptr()->stream());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (writeOptionalEntries)
|
||||
{
|
||||
IOInfoInFunction(*this)
|
||||
<< "Optional entry '" << keyword << "' is not present,"
|
||||
<< " adding and returning the default value '" << deflt << "'"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
add(new primitiveEntry(keyword, deflt));
|
||||
return deflt;
|
||||
if (writeOptionalEntries)
|
||||
{
|
||||
IOInfoInFunction(*this)
|
||||
<< "Optional entry '" << keyword << "' is not present,"
|
||||
<< " adding and returning the default value '" << deflt << "'"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
add(new primitiveEntry(keyword, deflt));
|
||||
return deflt;
|
||||
}
|
||||
|
||||
|
||||
@ -129,39 +125,37 @@ bool Foam::dictionary::readIfPresent
|
||||
bool patternMatch
|
||||
) const
|
||||
{
|
||||
const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
|
||||
auto finder = csearch(keyword, recursive, patternMatch);
|
||||
|
||||
if (entryPtr)
|
||||
if (finder.found())
|
||||
{
|
||||
entryPtr->stream() >> val;
|
||||
finder.ptr()->stream() >> val;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
if (writeOptionalEntries)
|
||||
{
|
||||
if (writeOptionalEntries)
|
||||
{
|
||||
IOInfoInFunction(*this)
|
||||
<< "Optional entry '" << keyword << "' is not present,"
|
||||
<< " the default value '" << val << "' will be used."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
IOInfoInFunction(*this)
|
||||
<< "Optional entry '" << keyword << "' is not present,"
|
||||
<< " the default value '" << val << "' will be used."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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>
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -62,10 +62,8 @@ bool Foam::entry::getKeyword(keyType& keyword, token& keyToken, Istream& is)
|
||||
keyword = keyToken.stringToken();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -84,20 +82,17 @@ bool Foam::entry::getKeyword(keyType& keyword, Istream& is)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise the token is invalid
|
||||
cerr<< "--> FOAM Warning :" << nl
|
||||
<< " From function "
|
||||
<< FUNCTION_NAME << nl
|
||||
<< " in file " << __FILE__
|
||||
<< " at line " << __LINE__ << nl
|
||||
<< " Reading " << is.name().c_str() << nl
|
||||
<< " found " << keyToken << nl
|
||||
<< " expected either " << token::END_BLOCK << " or EOF"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise the token is invalid
|
||||
std::cerr
|
||||
<< "--> FOAM Warning :" << nl
|
||||
<< " From function " << FUNCTION_NAME << nl
|
||||
<< " in file " << __FILE__ << " at line " << __LINE__ << nl
|
||||
<< " Reading " << is.name().c_str() << nl
|
||||
<< " found " << keyToken << nl
|
||||
<< " expected either " << token::END_BLOCK << " or EOF"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -154,22 +149,20 @@ bool Foam::entry::New
|
||||
false
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise the token is invalid
|
||||
cerr<< "--> FOAM Warning :" << nl
|
||||
<< " From function "
|
||||
<< FUNCTION_NAME << nl
|
||||
<< " in file " << __FILE__
|
||||
<< " at line " << __LINE__ << nl
|
||||
<< " Reading " << is.name().c_str() << nl
|
||||
<< " found " << keyToken << nl
|
||||
<< " expected either " << token::END_BLOCK << " or EOF"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise the token is invalid
|
||||
std::cerr
|
||||
<< "--> FOAM Warning :" << nl
|
||||
<< " From function " << FUNCTION_NAME << nl
|
||||
<< " in file " << __FILE__ << " at line " << __LINE__ << nl
|
||||
<< " Reading " << is.name().c_str() << nl
|
||||
<< " found " << keyToken << nl
|
||||
<< " expected either " << token::END_BLOCK << " or EOF"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
else if (keyword[0] == '#')
|
||||
|
||||
if (keyword[0] == '#')
|
||||
{
|
||||
// Function entry
|
||||
|
||||
@ -186,17 +179,11 @@ bool Foam::entry::New
|
||||
false
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
const word functionName(keyword.substr(1), false);
|
||||
return functionEntry::execute(functionName, parentDict, is);
|
||||
}
|
||||
|
||||
const word functionName(keyword.substr(1), false);
|
||||
return functionEntry::execute(functionName, parentDict, is);
|
||||
}
|
||||
else if
|
||||
(
|
||||
!disableFunctionEntries
|
||||
&& keyword[0] == '$'
|
||||
)
|
||||
else if (!disableFunctionEntries && keyword[0] == '$')
|
||||
{
|
||||
// Substitution entry
|
||||
|
||||
@ -224,17 +211,12 @@ bool Foam::entry::New
|
||||
const word varName = keyword.substr(1);
|
||||
|
||||
// Lookup the variable name in the given dictionary
|
||||
const entry* ePtr = parentDict.lookupScopedEntryPtr
|
||||
(
|
||||
varName,
|
||||
true,
|
||||
true
|
||||
);
|
||||
const auto finder = parentDict.csearchScoped(varName, true, true);
|
||||
|
||||
if (ePtr)
|
||||
if (finder.found())
|
||||
{
|
||||
// Read as primitiveEntry
|
||||
const keyType newKeyword(ePtr->stream());
|
||||
const keyType newKeyword(finder.ptr()->stream());
|
||||
|
||||
return parentDict.add
|
||||
(
|
||||
@ -242,14 +224,12 @@ bool Foam::entry::New
|
||||
false
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "Attempt to use undefined variable " << varName
|
||||
<< " as keyword"
|
||||
<< exit(FatalIOError);
|
||||
return false;
|
||||
}
|
||||
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "Attempt to use undefined variable " << varName
|
||||
<< " as keyword"
|
||||
<< exit(FatalIOError);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -267,7 +247,7 @@ bool Foam::entry::New
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal entry
|
||||
// Normal or scoped entry
|
||||
|
||||
token nextToken(is);
|
||||
is.putBack(nextToken);
|
||||
@ -281,19 +261,59 @@ bool Foam::entry::New
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool scoped =
|
||||
(
|
||||
!disableFunctionEntries
|
||||
&& (keyword.find('/') != string::npos)
|
||||
);
|
||||
|
||||
// See (using exact match) if entry already present
|
||||
auto finder =
|
||||
(
|
||||
scoped
|
||||
? parentDict.searchScoped(keyword, false, false)
|
||||
: parentDict.search(keyword, false, false)
|
||||
);
|
||||
|
||||
// How to manage duplicate entries
|
||||
bool mergeEntry = false;
|
||||
|
||||
// See (using exact match) if entry already present
|
||||
entry* existingPtr = parentDict.lookupEntryPtr
|
||||
(
|
||||
keyword,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
if (existingPtr)
|
||||
if (finder.found())
|
||||
{
|
||||
// Use keyword from the found entry (ie, eliminate scoping chars)
|
||||
const keyType key = finder.ref().keyword();
|
||||
|
||||
if (mode == inputMode::PROTECT || keyword == "FoamFile")
|
||||
{
|
||||
// Read and discard if existing element should be protected,
|
||||
// or would potentially alter the "FoamFile" header.
|
||||
|
||||
// Disable function/variable expansion to avoid side-effects
|
||||
const int oldFlag = entry::disableFunctionEntries;
|
||||
entry::disableFunctionEntries = 1;
|
||||
|
||||
if (nextToken == token::BEGIN_BLOCK)
|
||||
{
|
||||
dictionaryEntry dummy("dummy", finder.context(), is);
|
||||
}
|
||||
else
|
||||
{
|
||||
primitiveEntry dummy("dummy", finder.context(), is);
|
||||
}
|
||||
|
||||
entry::disableFunctionEntries = oldFlag;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mode == inputMode::ERROR)
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "duplicate entry: " << key
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == inputMode::MERGE)
|
||||
{
|
||||
mergeEntry = true;
|
||||
@ -301,57 +321,110 @@ bool Foam::entry::New
|
||||
else if (mode == inputMode::OVERWRITE)
|
||||
{
|
||||
// Clear existing dictionary so merge acts like overwrite
|
||||
if (existingPtr->isDict())
|
||||
if (finder.isDict())
|
||||
{
|
||||
existingPtr->dict().clear();
|
||||
finder.dict().clear();
|
||||
}
|
||||
mergeEntry = true;
|
||||
}
|
||||
else if (mode == inputMode::PROTECT)
|
||||
{
|
||||
// Read and discard the entry.
|
||||
// Disable function/variable expansion to avoid side-effects
|
||||
const int oldFlag = entry::disableFunctionEntries;
|
||||
entry::disableFunctionEntries = 1;
|
||||
|
||||
if (nextToken == token::BEGIN_BLOCK)
|
||||
// Merge/overwrite data entry
|
||||
|
||||
if (nextToken == token::BEGIN_BLOCK)
|
||||
{
|
||||
return finder.context().add
|
||||
(
|
||||
new dictionaryEntry(key, finder.context(), is),
|
||||
mergeEntry
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return finder.context().add
|
||||
(
|
||||
new primitiveEntry(key, finder.context(), is),
|
||||
mergeEntry
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (scoped)
|
||||
{
|
||||
// A slash-scoped entry - did not previously exist
|
||||
|
||||
string fullPath(keyword);
|
||||
fileName::clean(fullPath);
|
||||
|
||||
// Get or create the dictionary-path.
|
||||
// fileName::path == dictionary-path
|
||||
dictionary* subDictPtr =
|
||||
parentDict.makeScopedDictPtr
|
||||
(
|
||||
fileName::path(fullPath)
|
||||
);
|
||||
|
||||
if (subDictPtr)
|
||||
{
|
||||
// fileName::name == keyword-name
|
||||
string keyName = fileName::name(fullPath);
|
||||
keyType key;
|
||||
|
||||
// Patterns allowed for the final element.
|
||||
// - use if key name begins with a (single|double) quote
|
||||
|
||||
if (keyName.find_first_of("\"'") == 0)
|
||||
{
|
||||
dictionaryEntry dummy("dummy", parentDict, is);
|
||||
// Begins with a quote - treat as pattern
|
||||
key = keyType(string::validate<keyType>(keyName), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
primitiveEntry dummy("dummy", parentDict, is);
|
||||
// Treat as a word
|
||||
key = word::validate(keyName, false);
|
||||
}
|
||||
|
||||
entry::disableFunctionEntries = oldFlag;
|
||||
return true;
|
||||
if (nextToken == token::BEGIN_BLOCK)
|
||||
{
|
||||
return subDictPtr->add
|
||||
(
|
||||
new dictionaryEntry(key, *subDictPtr, is),
|
||||
mergeEntry
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return subDictPtr->add
|
||||
(
|
||||
new primitiveEntry(key, *subDictPtr, is),
|
||||
mergeEntry
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (mode == inputMode::ERROR)
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "duplicate entry: " << keyword
|
||||
<< exit(FatalIOError);
|
||||
|
||||
// Some error finding/creating intermediate dictionaries
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (nextToken == token::BEGIN_BLOCK)
|
||||
{
|
||||
return parentDict.add
|
||||
(
|
||||
new dictionaryEntry(keyword, parentDict, is),
|
||||
mergeEntry
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return parentDict.add
|
||||
(
|
||||
new primitiveEntry(keyword, parentDict, is),
|
||||
mergeEntry
|
||||
);
|
||||
// A non-scoped entry - did not previously exist
|
||||
|
||||
if (nextToken == token::BEGIN_BLOCK)
|
||||
{
|
||||
return parentDict.add
|
||||
(
|
||||
new dictionaryEntry(keyword, parentDict, is),
|
||||
mergeEntry
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return parentDict.add
|
||||
(
|
||||
new primitiveEntry(keyword, parentDict, is),
|
||||
mergeEntry
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,11 +24,11 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "includeEntry.H"
|
||||
#include "IFstream.H"
|
||||
#include "addToMemberFunctionSelectionTable.H"
|
||||
#include "stringOps.H"
|
||||
#include "Time.H"
|
||||
#include "IFstream.H"
|
||||
#include "IOstreams.H"
|
||||
#include "Time.H"
|
||||
#include "fileOperation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
@ -62,27 +62,6 @@ namespace functionEntries
|
||||
|
||||
// * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileName Foam::functionEntries::includeEntry::resolveFile
|
||||
(
|
||||
Istream& is,
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
fileName fName(is);
|
||||
// Substitute dictionary and environment variables.
|
||||
// Allow empty substitutions.
|
||||
stringOps::inplaceExpand(fName, dict, true, true);
|
||||
|
||||
if (fName.empty() || fName.isAbsolute())
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
// Relative name
|
||||
return fileName(is.name()).path()/fName;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::functionEntries::includeEntry::resolveFile
|
||||
(
|
||||
const fileName& dir,
|
||||
@ -91,6 +70,7 @@ Foam::fileName Foam::functionEntries::includeEntry::resolveFile
|
||||
)
|
||||
{
|
||||
fileName fName(f);
|
||||
|
||||
// Substitute dictionary and environment variables.
|
||||
// Allow empty substitutions.
|
||||
stringOps::inplaceExpand(fName, dict, true, true);
|
||||
@ -114,7 +94,8 @@ bool Foam::functionEntries::includeEntry::execute
|
||||
)
|
||||
{
|
||||
const fileName rawName(is);
|
||||
const fileName fName = resolveFile(is.name().path(), rawName, parentDict);
|
||||
const fileName fName(resolveFile(is.name().path(), rawName, parentDict));
|
||||
|
||||
autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
|
||||
ISstream& ifs = ifsPtr();
|
||||
|
||||
@ -133,27 +114,22 @@ bool Foam::functionEntries::includeEntry::execute
|
||||
(
|
||||
dynamic_cast<const regIOobject&>(top)
|
||||
);
|
||||
//Info<< rio.name() << " : adding dependency on included file "
|
||||
// << fName << endl;
|
||||
|
||||
rio.addWatch(fName);
|
||||
}
|
||||
|
||||
parentDict.read(ifs);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "Cannot open include file "
|
||||
<< (ifs.name().size() ? ifs.name() : rawName)
|
||||
<< " while reading dictionary " << parentDict.name()
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "Cannot open include file "
|
||||
<< (ifs.name().size() ? ifs.name() : rawName)
|
||||
<< " while reading dictionary " << parentDict.name()
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -165,7 +141,8 @@ bool Foam::functionEntries::includeEntry::execute
|
||||
)
|
||||
{
|
||||
const fileName rawName(is);
|
||||
const fileName fName = resolveFile(is.name().path(), rawName, parentDict);
|
||||
const fileName fName(resolveFile(is.name().path(), rawName, parentDict));
|
||||
|
||||
autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
|
||||
ISstream& ifs = ifsPtr();
|
||||
|
||||
@ -184,27 +161,23 @@ bool Foam::functionEntries::includeEntry::execute
|
||||
(
|
||||
dynamic_cast<const regIOobject&>(top)
|
||||
);
|
||||
//Info<< rio.name() << " : adding dependency on included file "
|
||||
// << fName << endl;
|
||||
|
||||
rio.addWatch(fName);
|
||||
}
|
||||
|
||||
entry.read(parentDict, ifs);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "Cannot open include file "
|
||||
<< (ifs.name().size() ? ifs.name() : rawName)
|
||||
<< " while reading dictionary " << parentDict.name()
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "Cannot open include file "
|
||||
<< (ifs.name().size() ? ifs.name() : rawName)
|
||||
<< " while reading dictionary " << parentDict.name()
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -68,9 +68,6 @@ protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Read the include fileName from Istream, expand and return
|
||||
static fileName resolveFile(Istream& is, const dictionary& dict);
|
||||
|
||||
//- Expand include fileName and return
|
||||
static fileName resolveFile
|
||||
(
|
||||
@ -79,6 +76,7 @@ protected:
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Static data members
|
||||
|
||||
@ -24,9 +24,10 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "includeEtcEntry.H"
|
||||
#include "addToMemberFunctionSelectionTable.H"
|
||||
#include "etcFiles.H"
|
||||
#include "stringOps.H"
|
||||
#include "addToMemberFunctionSelectionTable.H"
|
||||
#include "IFstream.H"
|
||||
#include "IOstreams.H"
|
||||
#include "fileOperation.H"
|
||||
|
||||
@ -61,7 +62,7 @@ namespace functionEntries
|
||||
|
||||
// * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileName Foam::functionEntries::includeEtcEntry::resolveFile
|
||||
Foam::fileName Foam::functionEntries::includeEtcEntry::resolveEtcFile
|
||||
(
|
||||
const fileName& f,
|
||||
const dictionary& dict
|
||||
@ -78,7 +79,7 @@ Foam::fileName Foam::functionEntries::includeEtcEntry::resolveFile
|
||||
return fName;
|
||||
}
|
||||
|
||||
// Search the etc directories for the file
|
||||
// Search etc directories for the file
|
||||
return Foam::findEtcFile(fName);
|
||||
}
|
||||
|
||||
@ -92,9 +93,8 @@ bool Foam::functionEntries::includeEtcEntry::execute
|
||||
)
|
||||
{
|
||||
const fileName rawName(is);
|
||||
const fileName fName(resolveFile(rawName, parentDict));
|
||||
const fileName fName(resolveEtcFile(rawName, parentDict));
|
||||
|
||||
//IFstream ifs(fName);
|
||||
autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
|
||||
ISstream& ifs = ifsPtr();
|
||||
|
||||
@ -107,18 +107,16 @@ bool Foam::functionEntries::includeEtcEntry::execute
|
||||
parentDict.read(ifs);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "Cannot open etc file "
|
||||
<< (ifs.name().size() ? ifs.name() : rawName)
|
||||
<< " while reading dictionary " << parentDict.name()
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "Cannot open etc file "
|
||||
<< (ifs.name().size() ? ifs.name() : rawName)
|
||||
<< " while reading dictionary " << parentDict.name()
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -130,9 +128,8 @@ bool Foam::functionEntries::includeEtcEntry::execute
|
||||
)
|
||||
{
|
||||
const fileName rawName(is);
|
||||
const fileName fName(resolveFile(rawName, parentDict));
|
||||
const fileName fName(resolveEtcFile(rawName, parentDict));
|
||||
|
||||
//IFstream ifs(fName);
|
||||
autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
|
||||
ISstream& ifs = ifsPtr();
|
||||
|
||||
@ -145,18 +142,16 @@ bool Foam::functionEntries::includeEtcEntry::execute
|
||||
entry.read(parentDict, ifs);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "Cannot open etc file "
|
||||
<< (ifs.name().size() ? ifs.name() : rawName)
|
||||
<< " while reading dictionary " << parentDict.name()
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
is
|
||||
) << "Cannot open etc file "
|
||||
<< (ifs.name().size() ? ifs.name() : rawName)
|
||||
<< " while reading dictionary " << parentDict.name()
|
||||
<< exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -79,9 +79,16 @@ class includeEtcEntry
|
||||
:
|
||||
public functionEntry
|
||||
{
|
||||
//- Expand include fileName and return
|
||||
static fileName resolveFile(const fileName& f, const dictionary& dict);
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Expand include fileName and search etc directories for the file
|
||||
static fileName resolveEtcFile
|
||||
(
|
||||
const fileName& f,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -64,7 +64,9 @@ bool Foam::functionEntries::includeIfPresentEntry::execute
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
const fileName fName(resolveFile(is, parentDict));
|
||||
const fileName rawName(is);
|
||||
const fileName fName(resolveFile(is.name().path(), rawName, parentDict));
|
||||
|
||||
autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
|
||||
ISstream& ifs = ifsPtr();
|
||||
|
||||
@ -100,7 +102,9 @@ bool Foam::functionEntries::includeIfPresentEntry::execute
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
const fileName fName(resolveFile(is, parentDict));
|
||||
const fileName rawName(is);
|
||||
const fileName fName(resolveFile(is.name().path(), rawName, parentDict));
|
||||
|
||||
autoPtr<ISstream> ifsPtr(fileHandler().NewIFstream(fName));
|
||||
ISstream& ifs = ifsPtr();
|
||||
|
||||
|
||||
@ -41,6 +41,51 @@ namespace functionEntries
|
||||
dictionaryIstream,
|
||||
inputMode
|
||||
);
|
||||
|
||||
addNamedToMemberFunctionSelectionTable
|
||||
(
|
||||
functionEntry,
|
||||
inputModeDefault,
|
||||
execute,
|
||||
dictionaryIstream,
|
||||
default
|
||||
);
|
||||
|
||||
addNamedToMemberFunctionSelectionTable
|
||||
(
|
||||
functionEntry,
|
||||
inputModeMerge,
|
||||
execute,
|
||||
dictionaryIstream,
|
||||
merge
|
||||
);
|
||||
|
||||
addNamedToMemberFunctionSelectionTable
|
||||
(
|
||||
functionEntry,
|
||||
inputModeOverwrite,
|
||||
execute,
|
||||
dictionaryIstream,
|
||||
overwrite
|
||||
);
|
||||
|
||||
addNamedToMemberFunctionSelectionTable
|
||||
(
|
||||
functionEntry,
|
||||
inputModeWarn,
|
||||
execute,
|
||||
dictionaryIstream,
|
||||
warn
|
||||
);
|
||||
|
||||
addNamedToMemberFunctionSelectionTable
|
||||
(
|
||||
functionEntry,
|
||||
inputModeError,
|
||||
execute,
|
||||
dictionaryIstream,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,4 +135,54 @@ bool Foam::functionEntries::inputMode::execute
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionEntries::inputModeDefault::execute
|
||||
(
|
||||
dictionary& parentDict,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
return entry::New(parentDict, is, entry::inputMode::PROTECT);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionEntries::inputModeMerge::execute
|
||||
(
|
||||
dictionary& parentDict,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
return entry::New(parentDict, is, entry::inputMode::MERGE);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionEntries::inputModeOverwrite::execute
|
||||
(
|
||||
dictionary& parentDict,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
return entry::New(parentDict, is, entry::inputMode::OVERWRITE);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionEntries::inputModeWarn::execute
|
||||
(
|
||||
dictionary& parentDict,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
return entry::New(parentDict, is, entry::inputMode::WARN);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionEntries::inputModeError::execute
|
||||
(
|
||||
dictionary& parentDict,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
return entry::New(parentDict, is, entry::inputMode::ERROR);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -84,6 +84,86 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class inputModeDefault Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- Temporarily change inputMode to %protect for the following entry
|
||||
class inputModeDefault
|
||||
:
|
||||
public functionEntry
|
||||
{
|
||||
public:
|
||||
|
||||
//- Execute in a sub-dict context
|
||||
static bool execute(dictionary& parentDict, Istream& is);
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class inputModeMerge Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- Temporarily change inputMode to %merge for the following entry
|
||||
class inputModeMerge
|
||||
:
|
||||
public functionEntry
|
||||
{
|
||||
public:
|
||||
|
||||
//- Execute in a sub-dict context
|
||||
static bool execute(dictionary& parentDict, Istream& is);
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class inputModeOverwrite Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- Temporarily change inputMode to %overwrite for the following entry
|
||||
class inputModeOverwrite
|
||||
:
|
||||
public functionEntry
|
||||
{
|
||||
public:
|
||||
|
||||
//- Execute in a sub-dict context
|
||||
static bool execute(dictionary& parentDict, Istream& is);
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class inputModeWarn Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- Temporarily change inputMode to %warn for the following entry
|
||||
class inputModeWarn
|
||||
:
|
||||
public functionEntry
|
||||
{
|
||||
public:
|
||||
|
||||
//- Execute in a sub-dict context
|
||||
static bool execute(dictionary& parentDict, Istream& is);
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class inputModeError Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- Temporarily change inputMode to %error for the following entry
|
||||
class inputModeError
|
||||
:
|
||||
public functionEntry
|
||||
{
|
||||
public:
|
||||
|
||||
//- Execute in a sub-dict context
|
||||
static bool execute(dictionary& parentDict, Istream& is);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace functionEntries
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,7 +26,6 @@ License
|
||||
#include "removeEntry.H"
|
||||
#include "dictionary.H"
|
||||
#include "stringListOps.H"
|
||||
#include "StringStream.H"
|
||||
#include "addToMemberFunctionSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
@ -55,17 +54,36 @@ bool Foam::functionEntries::removeEntry::execute
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
wordList dictKeys = parentDict.toc();
|
||||
wordReList patterns = readList<wordRe>(is);
|
||||
const List<keyType> patterns = readList<keyType>(is);
|
||||
|
||||
labelList indices = findStrings(patterns, dictKeys);
|
||||
|
||||
forAll(indices, indexI)
|
||||
for (const keyType& key : patterns)
|
||||
{
|
||||
parentDict.remove(dictKeys[indices[indexI]]);
|
||||
if (key.find('/') != string::npos || !key.isPattern())
|
||||
{
|
||||
// Remove scoped keyword, or keyword in the local scope
|
||||
dictionary::searcher finder =
|
||||
parentDict.searchScoped(key, false, false);
|
||||
|
||||
if (finder.found())
|
||||
{
|
||||
finder.context().remove(finder.ptr()->keyword());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove by pattern
|
||||
const wordList dictKeys = parentDict.toc();
|
||||
const labelList indices = findStrings(regExp(key), dictKeys);
|
||||
|
||||
for (const auto idx : indices)
|
||||
{
|
||||
parentDict.remove(dictKeys[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,17 +27,22 @@ Class
|
||||
Description
|
||||
Remove a dictionary entry.
|
||||
|
||||
The \c \#remove directive takes a list or a single wordRe.
|
||||
The \c \#remove directive takes a list or a single keyType.
|
||||
For example,
|
||||
\verbatim
|
||||
#remove entry0
|
||||
#remove ( entry1 entry2 entry3 otherEntry )
|
||||
#remove "entry[1-3]"
|
||||
#remove ( "entry[1-3]" otherEntry )
|
||||
#remove ^dict1.subdict2.entry2
|
||||
#remove "/dict1/subdict2/entry1"
|
||||
\endverbatim
|
||||
|
||||
The removal only occurs in the current context.
|
||||
Removing sub-entries or parent entries is not supported.
|
||||
Note
|
||||
Unless otherwise scoped, the removal occurs in the current context.
|
||||
To remove from other scopes, a dot-scoped or slash-scoped syntax is
|
||||
required. The slash-scoped syntax must be quoted to ensure that it
|
||||
is properly parsed.
|
||||
|
||||
SourceFiles
|
||||
removeEntry.C
|
||||
@ -57,7 +62,7 @@ namespace functionEntries
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class removeEntry Declaration
|
||||
Class removeEntry Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class removeEntry
|
||||
@ -66,7 +71,7 @@ class removeEntry
|
||||
{
|
||||
public:
|
||||
|
||||
//- Remove entries from the current sub-dict context
|
||||
//- Remove single or multiple entries. Local or scoped entries.
|
||||
static bool execute(dictionary& parentDict, Istream& is);
|
||||
};
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ bool Foam::primitiveEntry::expandVariable
|
||||
{
|
||||
// Recursive substitution mode.
|
||||
// Content between {} is replaced with expansion.
|
||||
string expanded = varName.substr(1, varName.size()-2);
|
||||
string expanded(varName.substr(1, varName.size()-2));
|
||||
|
||||
// Substitute dictionary and environment variables.
|
||||
// Do not allow empty substitutions.
|
||||
@ -57,46 +57,45 @@ bool Foam::primitiveEntry::expandVariable
|
||||
|
||||
return expandVariable(expanded, dict);
|
||||
}
|
||||
|
||||
// Lookup variable name in the given dictionary WITHOUT pattern matching.
|
||||
// Having a pattern match means that in this example:
|
||||
// {
|
||||
// internalField XXX;
|
||||
// boundaryField { ".*" {YYY;} movingWall {value $internalField;}
|
||||
// }
|
||||
// The $internalField would be matched by the ".*" !!!
|
||||
|
||||
// Recursive, non-patterns
|
||||
const entry* eptr = dict.lookupScopedEntryPtr(varName, true, false);
|
||||
if (!eptr)
|
||||
{
|
||||
// Not found - revert to environment variable
|
||||
const string str(getEnv(varName));
|
||||
|
||||
if (str.empty())
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
dict
|
||||
) << "Illegal dictionary entry or environment variable name "
|
||||
<< varName << endl << "Valid dictionary entries are "
|
||||
<< dict.toc() << exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
append(tokenList(IStringStream('(' + str + ')')()));
|
||||
}
|
||||
else if (eptr->isDict())
|
||||
{
|
||||
// Found dictionary entry
|
||||
append(eptr->dict().tokens());
|
||||
}
|
||||
else
|
||||
{
|
||||
// lookup the variable name in the given dictionary....
|
||||
// Note: allow wildcards to match? For now disabled since following
|
||||
// would expand internalField to wildcard match and not expected
|
||||
// internalField:
|
||||
// internalField XXX;
|
||||
// boundaryField { ".*" {YYY;} movingWall {value $internalField;}
|
||||
const entry* ePtr = dict.lookupScopedEntryPtr(varName, true, false);
|
||||
|
||||
// ...if defined append its tokens into this
|
||||
if (ePtr)
|
||||
{
|
||||
if (ePtr->isDict())
|
||||
{
|
||||
append(ePtr->dict().tokens());
|
||||
}
|
||||
else
|
||||
{
|
||||
append(ePtr->stream());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not in the dictionary - try an environment variable
|
||||
const string envStr = getEnv(varName);
|
||||
|
||||
if (envStr.empty())
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
dict
|
||||
) << "Illegal dictionary entry or environment variable name "
|
||||
<< varName << endl << "Valid dictionary entries are "
|
||||
<< dict.toc() << exit(FatalIOError);
|
||||
|
||||
return false;
|
||||
}
|
||||
append(tokenList(IStringStream('(' + envStr + ')')()));
|
||||
}
|
||||
// Found primitive entry
|
||||
append(eptr->stream());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@ -29,11 +29,71 @@ License
|
||||
#include "etcFiles.H"
|
||||
#include "StringStream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// Standard handling of "~/", "./" etc.
|
||||
static void standardExpansions(Foam::string& s)
|
||||
{
|
||||
if (s.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (s[0] == '.')
|
||||
{
|
||||
// Expand a lone '.' and an initial './' into cwd
|
||||
if (s.size() == 1)
|
||||
{
|
||||
s = cwd();
|
||||
}
|
||||
else if (s[1] == '/')
|
||||
{
|
||||
s.std::string::replace(0, 1, cwd());
|
||||
}
|
||||
}
|
||||
else if (s[0] == '~')
|
||||
{
|
||||
// Expand initial ~
|
||||
// ~/ => home directory
|
||||
// ~OpenFOAM => site/user OpenFOAM configuration directory
|
||||
// ~user => home directory for specified user
|
||||
|
||||
string user;
|
||||
fileName file;
|
||||
|
||||
const auto slash = s.find('/');
|
||||
if (slash == std::string::npos)
|
||||
{
|
||||
user = s.substr(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
user = s.substr(1, slash - 1);
|
||||
file = s.substr(slash + 1);
|
||||
}
|
||||
|
||||
// NB: be a bit lazy and expand ~unknownUser as an
|
||||
// empty string rather than leaving it untouched.
|
||||
// otherwise add extra test
|
||||
|
||||
if (user == "OpenFOAM")
|
||||
{
|
||||
s = findEtcFile(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = home(user)/file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//! \cond fileScope
|
||||
// Find the type/position of the ":-" or ":+" alternative values
|
||||
// Returns 0, '-', '+' corresponding to not-found or ':-' or ':+'
|
||||
static inline int findParameterAlternative
|
||||
(
|
||||
const std::string& s,
|
||||
@ -70,6 +130,8 @@ static inline int findParameterAlternative
|
||||
//! \endcond
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::string Foam::stringOps::expand
|
||||
(
|
||||
const string& original,
|
||||
@ -257,13 +319,14 @@ Foam::string Foam::stringOps::getVariable
|
||||
{
|
||||
string value;
|
||||
|
||||
const entry* ePtr = dict.lookupScopedEntryPtr
|
||||
const entry* eptr = dict.lookupScopedEntryPtr
|
||||
(
|
||||
name,
|
||||
true,
|
||||
false
|
||||
);
|
||||
if (ePtr)
|
||||
|
||||
if (eptr)
|
||||
{
|
||||
OStringStream buf;
|
||||
// Force floating point numbers to be printed with at least
|
||||
@ -271,11 +334,8 @@ Foam::string Foam::stringOps::getVariable
|
||||
buf << fixed;
|
||||
buf.precision(IOstream::defaultPrecision());
|
||||
|
||||
// fail for non-primitiveEntry
|
||||
dynamicCast<const primitiveEntry>
|
||||
(
|
||||
*ePtr
|
||||
).write(buf, true);
|
||||
// Fails for non-primitiveEntry
|
||||
dynamicCast<const primitiveEntry>(*eptr).write(buf, true);
|
||||
|
||||
value = buf.str();
|
||||
}
|
||||
@ -308,8 +368,11 @@ Foam::string Foam::stringOps::getVariable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!allowEmpty && value.empty())
|
||||
if (!allowEmpty && value.empty())
|
||||
{
|
||||
if (allowEnvVars)
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
@ -317,15 +380,14 @@ Foam::string Foam::stringOps::getVariable
|
||||
) << "Cannot find dictionary or environment variable "
|
||||
<< name << exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
|
||||
if (!allowEmpty && value.empty())
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
dict
|
||||
) << "Cannot find dictionary variable "
|
||||
<< name << exit(FatalIOError);
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction
|
||||
(
|
||||
dict
|
||||
) << "Cannot find dictionary variable "
|
||||
<< name << exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
@ -360,8 +422,9 @@ Foam::string Foam::stringOps::expand
|
||||
{
|
||||
newString.append(string(s[index]));
|
||||
}
|
||||
index++;
|
||||
++index;
|
||||
}
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
@ -390,7 +453,7 @@ Foam::string& Foam::stringOps::inplaceExpand
|
||||
if (s[begVar+1] == '{')
|
||||
{
|
||||
// Recursive variable expansion mode
|
||||
label stringStart = begVar;
|
||||
auto stringStart = begVar;
|
||||
begVar += 2;
|
||||
string varValue
|
||||
(
|
||||
@ -471,53 +534,8 @@ Foam::string& Foam::stringOps::inplaceExpand
|
||||
}
|
||||
}
|
||||
|
||||
if (!s.empty())
|
||||
{
|
||||
if (s[0] == '~')
|
||||
{
|
||||
// Expand initial ~
|
||||
// ~/ => home directory
|
||||
// ~OpenFOAM => site/user OpenFOAM configuration directory
|
||||
// ~user => home directory for specified user
|
||||
|
||||
string user;
|
||||
fileName file;
|
||||
|
||||
if ((begVar = s.find('/')) != string::npos)
|
||||
{
|
||||
user = s.substr(1, begVar - 1);
|
||||
file = s.substr(begVar + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
user = s.substr(1);
|
||||
}
|
||||
|
||||
// NB: be a bit lazy and expand ~unknownUser as an
|
||||
// empty string rather than leaving it untouched.
|
||||
// otherwise add extra test
|
||||
if (user == "OpenFOAM")
|
||||
{
|
||||
s = findEtcFile(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = home(user)/file;
|
||||
}
|
||||
}
|
||||
else if (s[0] == '.')
|
||||
{
|
||||
// Expand a lone '.' and an initial './' into cwd
|
||||
if (s.size() == 1)
|
||||
{
|
||||
s = cwd();
|
||||
}
|
||||
else if (s[1] == '/')
|
||||
{
|
||||
s.std::string::replace(0, 1, cwd());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Standard handling of "~/", "./" etc.
|
||||
standardExpansions(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
@ -596,32 +614,33 @@ Foam::string& Foam::stringOps::inplaceExpand
|
||||
);
|
||||
|
||||
|
||||
// lookup in the dictionary
|
||||
const entry* ePtr = dict.lookupScopedEntryPtr
|
||||
// Lookup in the dictionary without wildcards.
|
||||
// See note in primitiveEntry
|
||||
const entry* eptr = dict.lookupScopedEntryPtr
|
||||
(
|
||||
varName,
|
||||
true,
|
||||
false // wildcards disabled. See primitiveEntry
|
||||
false
|
||||
);
|
||||
|
||||
// if defined - copy its entries
|
||||
if (ePtr)
|
||||
if (eptr)
|
||||
{
|
||||
OStringStream buf;
|
||||
// Force floating point numbers to be printed with at least
|
||||
// some decimal digits.
|
||||
buf << fixed;
|
||||
buf.precision(IOstream::defaultPrecision());
|
||||
if (ePtr->isDict())
|
||||
if (eptr->isDict())
|
||||
{
|
||||
ePtr->dict().write(buf, false);
|
||||
eptr->dict().write(buf, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fail for other types
|
||||
// Fail for non-primitiveEntry
|
||||
dynamicCast<const primitiveEntry>
|
||||
(
|
||||
*ePtr
|
||||
*eptr
|
||||
).write(buf, true);
|
||||
}
|
||||
|
||||
@ -816,53 +835,8 @@ Foam::string& Foam::stringOps::inplaceExpand
|
||||
}
|
||||
}
|
||||
|
||||
if (!s.empty())
|
||||
{
|
||||
if (s[0] == '~')
|
||||
{
|
||||
// Expand initial ~
|
||||
// ~/ => home directory
|
||||
// ~OpenFOAM => site/user OpenFOAM configuration directory
|
||||
// ~user => home directory for specified user
|
||||
|
||||
string user;
|
||||
fileName file;
|
||||
|
||||
if ((begVar = s.find('/')) != string::npos)
|
||||
{
|
||||
user = s.substr(1, begVar - 1);
|
||||
file = s.substr(begVar + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
user = s.substr(1);
|
||||
}
|
||||
|
||||
// NB: be a bit lazy and expand ~unknownUser as an
|
||||
// empty string rather than leaving it untouched.
|
||||
// otherwise add extra test
|
||||
if (user == "OpenFOAM")
|
||||
{
|
||||
s = findEtcFile(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = home(user)/file;
|
||||
}
|
||||
}
|
||||
else if (s[0] == '.')
|
||||
{
|
||||
// Expand a lone '.' and an initial './' into cwd
|
||||
if (s.size() == 1)
|
||||
{
|
||||
s = cwd();
|
||||
}
|
||||
else if (s[1] == '/')
|
||||
{
|
||||
s.std::string::replace(0, 1, cwd());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Standard handling of "~/", "./" etc.
|
||||
standardExpansions(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
@ -886,11 +860,9 @@ bool Foam::stringOps::inplaceReplaceVar(string& s, const word& varName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
s.replace(i, content.size(), string("${" + varName + "}"));
|
||||
return true;
|
||||
}
|
||||
|
||||
s.replace(i, content.size(), string("${" + varName + "}"));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -12,6 +12,4 @@ maxCo 12;
|
||||
|
||||
maxDeltaT 1;
|
||||
|
||||
#inputMode merge
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -12,6 +12,4 @@ maxCo 2.5;
|
||||
|
||||
maxDeltaT 0.3;
|
||||
|
||||
#inputMode merge
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -12,6 +12,4 @@ maxCo 8;
|
||||
|
||||
maxDeltaT 1;
|
||||
|
||||
#inputMode merge
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -12,6 +12,4 @@ maxCo 5;
|
||||
|
||||
maxDeltaT 1;
|
||||
|
||||
#inputMode merge
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -12,6 +12,4 @@ maxCo 12;
|
||||
|
||||
maxDeltaT 1;
|
||||
|
||||
#inputMode merge
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -12,6 +12,4 @@ turbulentKE 37;
|
||||
turbulentOmega 32;
|
||||
turbulentEpsilon 30;
|
||||
|
||||
#inputMode merge
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -10,6 +10,5 @@ flowVelocity (10 0 0);
|
||||
pressure 0;
|
||||
turbulentKE 1.5;
|
||||
turbulentEpsilon 0.88;
|
||||
#inputMode merge
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -11,6 +11,5 @@ pressure 0;
|
||||
turbulentKE 0.375;
|
||||
turbulentOmega 3.6;
|
||||
turbulentEpsilon 0.12;
|
||||
#inputMode merge
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
Reference in New Issue
Block a user