ENH: retain original FoamFile dictionary header when including files.

- previously using a top-level #include would inadvertently remove the
  original header
This commit is contained in:
Mark Olesen 2017-10-29 12:37:47 +01:00
parent 69786840af
commit f76431c536
4 changed files with 107 additions and 114 deletions

View File

@ -414,7 +414,7 @@ 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& dict);
@ -765,7 +765,7 @@ public:
bool read(Istream& is);
//- Read dictionary from Istream, optionally keeping the header
bool read(Istream& is, const bool keepHeader);
bool read(Istream& is, bool keepHeader);
// Write

View File

@ -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");

View File

@ -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
@ -237,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
{
@ -276,9 +261,6 @@ bool Foam::entry::New
return false;
}
// How to manage duplicate entries
bool mergeEntry = false;
const bool scoped =
(
!disableFunctionEntries
@ -293,27 +275,19 @@ bool Foam::entry::New
: parentDict.search(keyword, false, false)
);
// How to manage duplicate entries
bool mergeEntry = false;
if (finder.found())
{
// Use keyword from the found entry (ie, eliminate scoping chars)
const keyType key = finder.ref().keyword();
if (mode == inputMode::MERGE)
if (mode == inputMode::PROTECT || keyword == "FoamFile")
{
mergeEntry = true;
}
else if (mode == inputMode::OVERWRITE)
{
// Clear existing dictionary so merge acts like overwrite
if (finder.isDict())
{
finder.dict().clear();
}
mergeEntry = true;
}
else if (mode == inputMode::PROTECT)
{
// Read and discard the entry.
// 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;
@ -330,7 +304,8 @@ bool Foam::entry::New
entry::disableFunctionEntries = oldFlag;
return true;
}
else if (mode == inputMode::ERROR)
if (mode == inputMode::ERROR)
{
FatalIOErrorInFunction(is)
<< "duplicate entry: " << key
@ -339,6 +314,20 @@ bool Foam::entry::New
return false;
}
if (mode == inputMode::MERGE)
{
mergeEntry = true;
}
else if (mode == inputMode::OVERWRITE)
{
// Clear existing dictionary so merge acts like overwrite
if (finder.isDict())
{
finder.dict().clear();
}
mergeEntry = true;
}
// Merge/overwrite data entry
if (nextToken == token::BEGIN_BLOCK)

View File

@ -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;