foamDictionary: Added '-diff <dict>' option

- Write differences with respect to the specified dictionary
    (or sub entry if -entry specified)

  - Write the differences with respect to a template dictionary:
      foamDictionary 0/U -diff $FOAM_ETC/templates/closedVolume/0/U

  - Write the differences in boundaryField with respect to a
    template dictionary:
      foamDictionary 0/U -diff $FOAM_ETC/templates/closedVolume/0/U \
        -entry boundaryField

Patch contributed by Mattijs Janssens
This commit is contained in:
Henry Weller
2016-10-18 18:23:24 +01:00
parent 919c486871
commit d2b96d88da

View File

@ -46,14 +46,18 @@ Usage
- \par -remove - \par -remove
Remove the selected entry Remove the selected entry
- \par -diff \<dictionary\>
Write differences with respect to the specified dictionary
(or sub entry if -entry specified)
- \par -expand - \par -expand
Read the specified dictionary file, expand the macros etc. and write Read the specified dictionary file, expand the macros etc. and write
the resulting dictionary to standard output. the resulting dictionary to standard output.
- \par -includes - \par -includes
List the \c #include and \c #includeIfPresent files to standard output. List the \c #include and \c #includeIfPresent files to standard output
Typical usage: Example usage:
- Change simulation to run for one timestep only: - Change simulation to run for one timestep only:
\verbatim \verbatim
foamDictionary system/controlDict -entry stopAt -set writeNow foamDictionary system/controlDict -entry stopAt -set writeNow
@ -81,6 +85,18 @@ Usage
-set "{type uniformFixedValue; uniformValue (2 0 0);}" -set "{type uniformFixedValue; uniformValue (2 0 0);}"
\endverbatim \endverbatim
- Write the differences with respect to a template dictionary:
\verbatim
foamDictionary 0/U -diff $FOAM_ETC/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 \
-entry boundaryField
\endverbatim
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "argList.H" #include "argList.H"
@ -114,238 +130,94 @@ word scope(const fileName& entryName)
} }
//- Extract keyword (last bit of scoped name //- Extracts dict name and keyword
word keyword(const word& scopedName) Pair<word> dictAndKeyword(const word& scopedName)
{ {
word key(scopedName);
string::size_type i = scopedName.find_last_of("."); string::size_type i = scopedName.find_last_of(".");
if (i != string::npos) if (i != string::npos)
{ {
key = scopedName.substr(i+1, string::npos); return Pair<word>
}
return key;
}
void removeScoped(dictionary& dict, const word& keyword)
{
if (keyword[0] == ':')
{
// Go up to top level and recurse to find entries
removeScoped
( (
const_cast<dictionary&>(dict.topDict()), scopedName.substr(0, i),
keyword.substr(1, keyword.size()-1) scopedName.substr(i+1, string::npos)
); );
return;
} }
else else
{ {
string::size_type dotPos = keyword.find('.'); return Pair<word>("", scopedName);
}
if (dotPos == string::npos)
{
// Non-scoped lookup
dict.remove(keyword);
return;
} }
else
{
if (dotPos == 0)
{
// Starting with a '.'. Go up for every 2nd '.' found
const dictionary* dictPtr = &dict;
string::size_type begVar = dotPos + 1; const dictionary& lookupScopedDict
string::const_iterator iter =
keyword.begin() + begVar;
string::size_type endVar = begVar;
while
( (
iter != keyword.end() const dictionary& dict,
&& *iter == '.' const word& subDictName
) )
{ {
++iter; if (subDictName == "")
++endVar;
// Go to parent
if (&dictPtr->parent() == &dictionary::null)
{ {
FatalIOErrorInFunction(dict) return dict;
<< "No parent of current dictionary"
<< " when searching for "
<< keyword.substr
(
begVar,
keyword.size() - begVar
)
<< exit(FatalIOError);
}
dictPtr = &dictPtr->parent();
}
removeScoped
(
const_cast<dictionary&>(*dictPtr),
keyword.substr(endVar)
);
return;
} }
else else
{ {
// Extract the first word
word firstWord = keyword.substr(0, dotPos);
const entry* entPtr = dict.lookupScopedEntryPtr const entry* entPtr = dict.lookupScopedEntryPtr
( (
firstWord, subDictName,
false, // Recursive false,
false false
); );
if (!entPtr || !entPtr->isDict()) if (!entPtr || !entPtr->isDict())
{ {
FatalIOErrorInFunction(dict) FatalIOErrorInFunction(dict)
<< "keyword " << firstWord << "keyword " << subDictName
<< " is undefined in dictionary " << " is undefined in dictionary "
<< dict.name() << " or is not a dictionary" << dict.name() << " or is not a dictionary"
<< endl << endl
<< "Valid keywords are " << dict.keys() << "Valid keywords are " << dict.keys()
<< exit(FatalIOError); << exit(FatalIOError);
} }
return entPtr->dict();
}
}
const dictionary& firstDict = entPtr->dict();
removeScoped void remove(dictionary& dict, const dictionary& removeDict)
{
forAllConstIter(dictionary, removeDict, iter)
{
const entry* entPtr = dict.lookupEntryPtr
( (
const_cast<dictionary&>(firstDict), iter().keyword(),
keyword.substr(dotPos, keyword.size()-dotPos) false,
);
return;
}
}
}
}
void setScoped
(
dictionary& dict,
const word& keyword,
const bool overwrite,
entry* d
)
{
if (keyword[0] == ':')
{
// Go up to top level and recurse to find entries
setScoped
(
const_cast<dictionary&>(dict.topDict()),
keyword.substr(1, keyword.size()-1),
overwrite,
d
);
return;
}
else
{
string::size_type dotPos = keyword.find('.');
if (dotPos == string::npos)
{
// Non-scoped lookup
if (overwrite)
{
dict.set(d);
}
else
{
dict.add(d, false);
}
return;
}
else
{
if (dotPos == 0)
{
// Starting with a '.'. Go up for every 2nd '.' found
const dictionary* dictPtr = &dict;
string::size_type begVar = dotPos + 1;
string::const_iterator iter =
keyword.begin() + begVar;
string::size_type endVar = begVar;
while
(
iter != keyword.end()
&& *iter == '.'
)
{
++iter;
++endVar;
// Go to parent
if (&dictPtr->parent() == &dictionary::null)
{
FatalIOErrorInFunction(dict)
<< "No parent of current dictionary"
<< " when searching for "
<< keyword.substr
(
begVar,
keyword.size() - begVar
)
<< exit(FatalIOError);
}
dictPtr = &dictPtr->parent();
}
setScoped
(
const_cast<dictionary&>(*dictPtr),
keyword.substr(endVar),
overwrite,
d
);
return;
}
else
{
// Extract the first word
word firstWord = keyword.substr(0, dotPos);
const entry* entPtr = dict.lookupScopedEntryPtr
(
firstWord,
false, // Recursive
false false
); );
if (!entPtr || !entPtr->isDict()) if (entPtr)
{ {
FatalIOErrorInFunction(dict) if (entPtr->isDict())
<< "keyword " << firstWord {
<< " is undefined in dictionary " if (iter().isDict())
<< dict.name() << " or is not a dictionary" {
<< endl remove
<< "Valid keywords are " << dict.keys()
<< exit(FatalIOError);
}
const dictionary& firstDict = entPtr->dict();
setScoped
( (
const_cast<dictionary&>(firstDict), const_cast<dictionary&>(entPtr->dict()),
keyword.substr(dotPos, keyword.size()-dotPos), iter().dict()
overwrite,
d
); );
return;
// Check if dictionary is empty
if (!entPtr->dict().size())
{
dict.remove(iter().keyword());
}
}
}
else if (!iter().isDict())
{
if (*entPtr == iter())
{
dict.remove(iter().keyword());
}
} }
} }
} }
@ -363,35 +235,41 @@ int main(int argc, char *argv[])
argList::addBoolOption argList::addBoolOption
( (
"value", "value",
"print entry value" "Print entry value"
); );
argList::addOption argList::addOption
( (
"set", "set",
"value", "value",
"set entry value or add new entry" "Set entry value or add new entry"
); );
argList::addOption argList::addOption
( (
"add", "add",
"value", "value",
"add a new entry" "Add a new entry"
); );
argList::addBoolOption argList::addBoolOption
( (
"remove", "remove",
"remove the entry." "Remove the entry."
);
argList::addOption
(
"diff",
"dict",
"Write differences with respect to the specified dictionary"
); );
argList::addBoolOption argList::addBoolOption
( (
"includes", "includes",
"List the #include/#includeIfPresent files to standard output." "List the #include/#includeIfPresent files to standard output"
); );
argList::addBoolOption argList::addBoolOption
( (
"expand", "expand",
"Read the specified dictionary file, expand the macros etc. and write " "Read the specified dictionary file, expand the macros etc. and write "
"the resulting dictionary to standard output." "the resulting dictionary to standard output"
); );
argList args(argc, argv); argList args(argc, argv);
@ -406,9 +284,14 @@ int main(int argc, char *argv[])
fileName dictFileName(args[1]); fileName dictFileName(args[1]);
autoPtr<IFstream> dictFile(new IFstream(dictFileName)); autoPtr<IFstream> dictFile(new IFstream(dictFileName));
if (!dictFile().good())
if (dictFile().good())
{ {
FatalErrorInFunction
<< "Cannot open file " << dictFileName
<< exit(FatalError, 1);
}
bool changed = false; bool changed = false;
// Read but preserve headers // Read but preserve headers
@ -429,6 +312,25 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
// 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);
}
// Read but preserve headers
diffDict.read(diffFile(), true);
}
word entryName; word entryName;
if (args.optionReadIfPresent("entry", entryName)) if (args.optionReadIfPresent("entry", entryName))
{ {
@ -443,10 +345,20 @@ int main(int argc, char *argv[])
{ {
bool overwrite = args.optionFound("set"); bool overwrite = args.optionFound("set");
word key(keyword(scopedName)); Pair<word> dAk(dictAndKeyword(scopedName));
IStringStream str(string(key) + ' ' + newValue + ';'); IStringStream str(string(dAk.second()) + ' ' + newValue + ';');
setScoped(dict, scopedName, overwrite, entry::New(str).ptr()); entry* ePtr(entry::New(str).ptr());
const dictionary& d(lookupScopedDict(dict, dAk.first()));
if (overwrite)
{
const_cast<dictionary&>(d).set(ePtr);
}
else
{
const_cast<dictionary&>(d).add(ePtr, false);
}
changed = true; changed = true;
// Print the changed entry // Print the changed entry
@ -463,11 +375,46 @@ int main(int argc, char *argv[])
} }
else if (args.optionFound("remove")) else if (args.optionFound("remove"))
{ {
removeScoped(dict, scopedName); // Extract dictionary name and keyword
Pair<word> dAk(dictAndKeyword(scopedName));
const dictionary& d(lookupScopedDict(dict, dAk.first()));
const_cast<dictionary&>(d).remove(dAk.second());
changed = true; changed = true;
} }
else else
{ {
// Optionally remove a second dictionary
if (args.optionFound("diff"))
{
Pair<word> dAk(dictAndKeyword(scopedName));
const dictionary& d(lookupScopedDict(dict, dAk.first()));
const dictionary& d2(lookupScopedDict(diffDict, dAk.first()));
const entry* ePtr =
d.lookupEntryPtr(dAk.second(), false, true);
const entry* e2Ptr =
d2.lookupEntryPtr(dAk.second(), false, true);
if (ePtr && e2Ptr)
{
if (*ePtr == *e2Ptr)
{
const_cast<dictionary&>(d).remove(dAk.second());
}
else if (ePtr->isDict() && e2Ptr->isDict())
{
remove
(
const_cast<dictionary&>(ePtr->dict()),
e2Ptr->dict()
);
}
}
}
const entry* entPtr = dict.lookupScopedEntryPtr const entry* entPtr = dict.lookupScopedEntryPtr
( (
scopedName, scopedName,
@ -524,9 +471,14 @@ int main(int argc, char *argv[])
Info<< iter().keyword() << endl; Info<< iter().keyword() << endl;
} }
} }
else if (args.optionFound("diff"))
{
remove(dict, diffDict);
dict.write(Info, false);
}
else else
{ {
Info<< dict; dict.write(Info, false);
} }
if (changed) if (changed)
@ -537,13 +489,6 @@ int main(int argc, char *argv[])
dict.write(os, false); dict.write(os, false);
IOobject::writeEndDivider(os); IOobject::writeEndDivider(os);
} }
}
else
{
FatalErrorInFunction
<< "Cannot open file " << dictFileName
<< exit(FatalError, 1);
}
return 0; return 0;
} }