145bool upgradeScope(
word& entryName)
149 entryName.find(
'/') == string::npos
150 && entryName.find(
':') != string::npos
157 for (
const word& name : names)
159 if (entryName.size()) entryName.append(
".");
161 entryName.append(name);
180 dictAndKeyword(
const word& scopedName)
182 auto i = scopedName.rfind(
'/');
183 if (i == string::npos)
185 i = scopedName.rfind(
'.');
188 if (i != string::npos)
190 dict_ = scopedName.substr(0, i);
191 key_ = scopedName.substr(i+1);
214 const word& subDictName
217 if (subDictName.empty())
222 const entry* eptr =
dict.findScoped(subDictName, keyType::LITERAL);
224 if (!eptr || !eptr->
isDict())
227 <<
"'" << subDictName <<
"' not found in dictionary "
228 <<
dict.name() <<
" or is not a dictionary" <<
nl
229 <<
"Known entries are " <<
dict.keys()
230 <<
exit(FatalIOError);
239 for (
const entry& refEntry : dictToRemove)
241 auto finder =
dict.search(refEntry.keyword(), keyType::LITERAL);
247 if (refEntry.isDict())
249 removeDict(finder.dict(), refEntry.dict());
252 purge = finder.dict().empty();
255 else if (finder.found() && !refEntry.isDict())
258 purge = (finder.ref() == refEntry);
263 dict.remove(refEntry.keyword());
269int main(
int argc,
char *argv[])
273 "Interrogate and manipulate dictionaries"
277 argList::noJobInfo();
278 argList::addArgument(
"dict",
"The dictionary file to process");
279 argList::addBoolOption(
"keywords",
"List keywords");
280 argList::addOption(
"entry",
"name",
"Report/select the named entry");
281 argList::addBoolOption
290 "Set entry value or add new entry"
298 argList::addBoolOption
307 "Write differences with respect to the specified dictionary"
313 "As per -diff, but locate the file as per foamEtcFile"
315 argList::addOptionCompat(
"diff-etc", {
"diffEtc", 1712});
320 "Set default write precision for IOstreams"
323 argList::addBoolOption
326 "List the #include/#sinclude files to standard output"
328 argList::addBoolOption
331 "Read the specified dictionary file, expand the macros etc. and write "
332 "the resulting dictionary to standard output"
334 argList::addBoolOption
336 "disableFunctionEntries",
337 "Disable expansion of dictionary directives - #include, #codeStream etc"
339 profiling::disable();
343 const bool listIncludes =
args.
found(
"includes");
350 const bool disableEntries =
args.
found(
"disableFunctionEntries");
354 if (Pstream::master())
356 Serr<<
"Not expanding variables or dictionary directives" <<
endl;
358 entry::disableFunctionEntries =
true;
371 IOstream::defaultPrecision(prec);
379 if (!dictFile().good())
382 <<
"Cannot open file " << dictFileName
383 <<
exit(FatalError, 1);
387 bool changed =
false;
398 IOobject::writeBanner(Info)
399 <<
"//\n// " << dictFileName <<
"\n//\n";
400 dict.write(Info,
false);
401 IOobject::writeDivider(Info);
408 bool optDiff =
false;
417 if (!diffFile.good())
420 <<
"Cannot open file " << diffFileName
421 <<
exit(FatalError, 1);
425 diffDict.
read(diffFile,
true);
431 if (foundName.empty())
434 <<
"Cannot find etcFile " << diffFileName
435 <<
exit(FatalError, 1);
439 if (!diffFile.good())
442 <<
"Cannot open file " << foundName
443 <<
exit(FatalError, 1);
447 diffDict.
read(diffFile,
true);
455 upgradeScope(scopedName);
464 const bool overwrite =
args.
found(
"set");
467 const dictAndKeyword dAk(scopedName);
474 entry* ePtr(entry::New(str).ptr());
487 const auto finder =
dict.csearchScoped(scopedName, keyType::REGEX);
497 const dictAndKeyword dAk(scopedName);
511 const dictAndKeyword dAk(scopedName);
514 const dictionary& d2(lookupScopedDict(diffDict, dAk.dict()));
516 const entry* e1Ptr = d1.findEntry(dAk.key(), keyType::REGEX);
517 const entry* e2Ptr = d2.findEntry(dAk.key(), keyType::REGEX);
521 if (*e1Ptr == *e2Ptr)
523 const_cast<dictionary&
>(d1).remove(dAk.key());
536 const auto finder =
dict.csearchScoped(scopedName, keyType::REGEX);
541 <<
"Cannot find entry " << scopedName
542 <<
exit(FatalIOError, 2);
546 for (
const entry&
e : finder.dict())
555 Info<< finder.dict();
557 else if (finder.ref().isStream())
559 const tokenList& tokens = finder.ref().stream();
563 if (i < tokens.size() - 1)
586 removeDict(
dict, diffDict);
587 dict.write(Info,
false);
591 dict.write(Info,
false);
598 IOobject::writeBanner(
os);
599 IOobject::writeDivider(
os);
601 IOobject::writeEndDivider(
os);
Input from file stream, using an ISstream.
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Output to file stream, using an OSstream.
virtual int precision() const
Get precision of output field.
Extract command arguments and options from the supplied argc and argv parameters.
T get(const label index) const
Get a value from the argument at index.
bool found(const word &optName) const
Return true if the named option is found.
bool readIfPresent(const word &optName, T &val) const
Read a value from the named option if present.
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
bool read(Istream &is)
Read dictionary from Istream. Discards the header.
A keyword and a list of tokens is an 'entry'.
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
virtual const dictionary & dict() const =0
Return dictionary, if entry is a dictionary.
A class for handling file names.
Computes the natural logarithm of an input volScalarField.
A class for handling words, derived from Foam::string.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Functions to search 'etc' directories for configuration files etc.
OBJstream os(runTime.globalPath()/outputName)
void set(List< bool > &bools, const labelUList &locations)
Set the listed locations (assign 'true').
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
messageStream Info
Information stream (stdout output on master, null elsewhere)
fileName findEtcFile(const fileName &name, const bool mandatory=false, unsigned short location=0777)
Search for a single FILE within the etc directories.
OSstream Sout
OSstream wrapped stdout (std::cout)
Ostream & endl(Ostream &os)
Add newline and flush stream.
OSstream Serr
OSstream wrapped stderr (std::cerr)
errorManipArg< error, int > exit(error &err, const int errNo=1)
constexpr char nl
The newline '\n' character (0x0a)
dict add("bounds", meshBb)
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.