mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: handle entry alternatives outside of string expansion
- string expansions have supported "${var:-default}" syntax for
several versions, but this did not apply plain dictionary expansions.
Eg, the following did not parse
massFlow ${entry1:-100};
ENH: remove content and length restriction on '${..}' quoted variables
- allows this type of content:
velocity2 ${velocity1:- ( 0 -100 10) };
- accept empty parameter strings for entries. This allows the
following expansion to work as expected:
hex (n1 n2..) ${inletBlock:-} (10 10 10) simpleGrading (1 1 1)
ie, optionally define the cellZone name for a given block
ENH: add single parameter dictionary writeEntry method.
- the dictionary knows its own name (dictName), which can be used
when writing content
This commit is contained in:
@ -436,7 +436,7 @@ Foam::Istream& Foam::ISstream::read(word& str)
|
|||||||
{
|
{
|
||||||
if (!depth)
|
if (!depth)
|
||||||
{
|
{
|
||||||
break; // Closed ')' without a '(' ? ... stop
|
break; // Closed ')' without an opening '(' ? ... stop
|
||||||
}
|
}
|
||||||
--depth;
|
--depth;
|
||||||
}
|
}
|
||||||
@ -627,43 +627,55 @@ Foam::Istream& Foam::ISstream::readVariable(std::string& str)
|
|||||||
}
|
}
|
||||||
buf[nChar++] = c;
|
buf[nChar++] = c;
|
||||||
|
|
||||||
char endChar = token::END_LIST;
|
str.clear();
|
||||||
|
|
||||||
if (c == token::BEGIN_BLOCK)
|
if (c == token::BEGIN_BLOCK)
|
||||||
{
|
{
|
||||||
// Processing ${...} style
|
// Processing ${...} style.
|
||||||
|
|
||||||
endChar = token::END_BLOCK;
|
|
||||||
++depth;
|
++depth;
|
||||||
|
|
||||||
// Could check that the next char is good and not one of '{}'
|
// Could check that the next char is good and not one of '{}'
|
||||||
// since this would indicate "${}", "${{..." or truncated "${"
|
// since this would indicate "${}", "${{..." or truncated "${"
|
||||||
|
|
||||||
while
|
while (get(c))
|
||||||
(
|
|
||||||
(nChar < maxLen) && get(c)
|
|
||||||
&&
|
|
||||||
(
|
|
||||||
validVariableChar(c)
|
|
||||||
|| (c == token::BEGIN_BLOCK || c == token::END_BLOCK)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
|
buf[nChar++] = c;
|
||||||
|
if (nChar == maxLen)
|
||||||
|
{
|
||||||
|
str.append(buf, nChar);
|
||||||
|
nChar = 0;
|
||||||
|
}
|
||||||
if (c == token::BEGIN_BLOCK)
|
if (c == token::BEGIN_BLOCK)
|
||||||
{
|
{
|
||||||
++depth;
|
++depth;
|
||||||
}
|
}
|
||||||
else if (c == token::END_BLOCK)
|
else if (c == token::END_BLOCK)
|
||||||
{
|
{
|
||||||
|
--depth;
|
||||||
if (!depth)
|
if (!depth)
|
||||||
{
|
{
|
||||||
break; // Closed '}' without a '{' ? ... stop
|
// Found closing '}' character
|
||||||
|
str.append(buf, nChar);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
--depth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[nChar++] = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should never reach here on normal input
|
||||||
|
|
||||||
|
str.append(buf, nChar); // Finalize pending buffer input
|
||||||
|
|
||||||
|
nChar = str.length();
|
||||||
|
if (str.length() > errLen)
|
||||||
|
{
|
||||||
|
str.erase(errLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
FatalIOErrorInFunction(*this)
|
||||||
|
<< "stream terminated while reading variable '"
|
||||||
|
<< str.c_str() << "...' [" << nChar << "]\n"
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
else if (validVariableChar(c))
|
else if (validVariableChar(c))
|
||||||
{
|
{
|
||||||
@ -683,7 +695,7 @@ Foam::Istream& Foam::ISstream::readVariable(std::string& str)
|
|||||||
{
|
{
|
||||||
if (!depth)
|
if (!depth)
|
||||||
{
|
{
|
||||||
break; // Closed ')' without a '(' ? ... stop
|
break; // Closed ')' without an opening '(' ? ... stop
|
||||||
}
|
}
|
||||||
--depth;
|
--depth;
|
||||||
}
|
}
|
||||||
@ -733,7 +745,7 @@ Foam::Istream& Foam::ISstream::readVariable(std::string& str)
|
|||||||
{
|
{
|
||||||
IOWarningInFunction(*this)
|
IOWarningInFunction(*this)
|
||||||
<< "Missing " << depth
|
<< "Missing " << depth
|
||||||
<< " closing '" << endChar << "' while parsing" << nl << nl
|
<< " closing ')' while parsing" << nl << nl
|
||||||
<< buf << nl << endl;
|
<< buf << nl << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,7 +774,7 @@ Foam::Istream& Foam::ISstream::readVerbatim(std::string& str)
|
|||||||
get(nextC);
|
get(nextC);
|
||||||
if (nextC == token::END_BLOCK)
|
if (nextC == token::END_BLOCK)
|
||||||
{
|
{
|
||||||
// The closing "#}" found
|
// Found closing "#}" sequence
|
||||||
str.append(buf, nChar);
|
str.append(buf, nChar);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||||
Copyright (C) 2016-2019 OpenCFD Ltd.
|
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -937,6 +937,9 @@ public:
|
|||||||
|
|
||||||
// Write
|
// Write
|
||||||
|
|
||||||
|
//- Write sub-dictionary with its dictName as its header
|
||||||
|
void writeEntry(Ostream& os) const;
|
||||||
|
|
||||||
//- Write sub-dictionary with the keyword as its header
|
//- Write sub-dictionary with the keyword as its header
|
||||||
void writeEntry(const keyType& keyword, Ostream& os) const;
|
void writeEntry(const keyType& keyword, Ostream& os) const;
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||||
Copyright (C) 2016-2019 OpenCFD Ltd.
|
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -161,6 +161,14 @@ Foam::Istream& Foam::operator>>(Istream& is, dictionary& dict)
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::dictionary::writeEntry(Ostream& os) const
|
||||||
|
{
|
||||||
|
os.beginBlock(dictName());
|
||||||
|
writeEntries(os);
|
||||||
|
os.endBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::dictionary::writeEntry(const keyType& kw, Ostream& os) const
|
void Foam::dictionary::writeEntry(const keyType& kw, Ostream& os) const
|
||||||
{
|
{
|
||||||
os.beginBlock(kw);
|
os.beginBlock(kw);
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2017-2019 OpenCFD Ltd.
|
Copyright (C) 2017-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -31,6 +31,45 @@ License
|
|||||||
#include "OSspecific.H"
|
#include "OSspecific.H"
|
||||||
#include "stringOps.H"
|
#include "stringOps.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
std::string::size_type& pos,
|
||||||
|
std::string::size_type endPos = std::string::npos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
while (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
pos = s.find(':', pos);
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
if (pos < endPos)
|
||||||
|
{
|
||||||
|
// in-range: check for '+' or '-' following the ':'
|
||||||
|
const int altType = s[pos+1];
|
||||||
|
if (altType == '+' || altType == '-')
|
||||||
|
{
|
||||||
|
return altType;
|
||||||
|
}
|
||||||
|
|
||||||
|
++pos; // unknown/unsupported - continue at next position
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// out-of-range: abort
|
||||||
|
pos = std::string::npos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
bool Foam::primitiveEntry::expandVariable
|
bool Foam::primitiveEntry::expandVariable
|
||||||
@ -39,19 +78,49 @@ bool Foam::primitiveEntry::expandVariable
|
|||||||
const dictionary& dict
|
const dictionary& dict
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
int altType = 0; // Type ('-' or '+') for ":-" or ":+" alternatives
|
||||||
|
word expanded;
|
||||||
|
string altValue;
|
||||||
|
|
||||||
if (varName.size() > 1 && varName[0] == token::BEGIN_BLOCK)
|
if (varName.size() > 1 && varName[0] == token::BEGIN_BLOCK)
|
||||||
{
|
{
|
||||||
// Recursive substitution mode.
|
// Replace content between {} with string expansion and
|
||||||
// Content between {} is replaced with expansion.
|
// handle ${parameter:-word} or ${parameter:+word}
|
||||||
string expanded(varName.substr(1, varName.size()-2));
|
|
||||||
|
// Copy into a word without stripping
|
||||||
|
expanded.assign(varName, 1, varName.size()-2);
|
||||||
|
|
||||||
// Substitute dictionary and environment variables.
|
// Substitute dictionary and environment variables.
|
||||||
// Do not allow empty substitutions.
|
// - Allow environment.
|
||||||
stringOps::inplaceExpand(expanded, dict, true, false);
|
// - No empty substitutions.
|
||||||
|
// - No sub-dictionary lookups
|
||||||
|
|
||||||
return expandVariable(expanded, dict);
|
stringOps::inplaceExpand(expanded, dict, true, false, false);
|
||||||
|
|
||||||
|
// Position of ":-" or ":+" alternative values
|
||||||
|
std::string::size_type altPos = 0;
|
||||||
|
|
||||||
|
// Check for parameter:-word or parameter:+word
|
||||||
|
altType = findParameterAlternative(expanded, altPos);
|
||||||
|
|
||||||
|
if (altType)
|
||||||
|
{
|
||||||
|
altValue = expanded.substr(altPos + 2);
|
||||||
|
expanded.erase(altPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catch really bad expansions and let them die soon after.
|
||||||
|
// Eg, ${:-other} should not be allowed.
|
||||||
|
if (expanded.empty())
|
||||||
|
{
|
||||||
|
altType = 0;
|
||||||
|
altValue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallthrough for further processing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Lookup variable name in the given dictionary WITHOUT pattern matching.
|
// Lookup variable name in the given dictionary WITHOUT pattern matching.
|
||||||
// Having a pattern match means that in this example:
|
// Having a pattern match means that in this example:
|
||||||
// {
|
// {
|
||||||
@ -61,18 +130,36 @@ bool Foam::primitiveEntry::expandVariable
|
|||||||
// The $internalField would be matched by the ".*" !!!
|
// The $internalField would be matched by the ".*" !!!
|
||||||
|
|
||||||
// Recursive, non-patterns
|
// Recursive, non-patterns
|
||||||
const entry* eptr = dict.findScoped(varName, keyType::LITERAL_RECURSIVE);
|
|
||||||
|
const word& lookupName = (expanded.empty() ? varName : expanded);
|
||||||
|
|
||||||
|
const entry* eptr =
|
||||||
|
dict.findScoped(lookupName, keyType::LITERAL_RECURSIVE);
|
||||||
|
|
||||||
if (!eptr)
|
if (!eptr)
|
||||||
{
|
{
|
||||||
// Not found - revert to environment variable
|
// Not found - revert to environment variable
|
||||||
const string str(Foam::getEnv(varName));
|
// and parse into a series of tokens.
|
||||||
|
|
||||||
if (str.empty())
|
// We wish to fail if the environment variable returns
|
||||||
|
// an empty string and there is no alternative given.
|
||||||
|
//
|
||||||
|
// Always allow empty strings as alternative parameters,
|
||||||
|
// since the user provided them for a reason.
|
||||||
|
|
||||||
|
string str(Foam::getEnv(lookupName));
|
||||||
|
|
||||||
|
if (str.empty() ? (altType == '-') : (altType == '+'))
|
||||||
|
{
|
||||||
|
// Not found or empty: use ":-" alternative value
|
||||||
|
// Found and not empty: use ":+" alternative value
|
||||||
|
str = std::move(altValue);
|
||||||
|
}
|
||||||
|
else if (str.empty())
|
||||||
{
|
{
|
||||||
FatalIOErrorInFunction(dict)
|
FatalIOErrorInFunction(dict)
|
||||||
<< "Illegal dictionary entry or environment variable name "
|
<< "Illegal dictionary entry or environment variable name "
|
||||||
<< varName << nl
|
<< lookupName << nl
|
||||||
<< "Known dictionary entries: " << dict.toc() << nl
|
<< "Known dictionary entries: " << dict.toc() << nl
|
||||||
<< exit(FatalIOError);
|
<< exit(FatalIOError);
|
||||||
|
|
||||||
@ -91,12 +178,33 @@ bool Foam::primitiveEntry::expandVariable
|
|||||||
|
|
||||||
tokenList toks(eptr->dict().tokens());
|
tokenList toks(eptr->dict().tokens());
|
||||||
|
|
||||||
|
if (toks.empty() ? (altType == '-') : (altType == '+'))
|
||||||
|
{
|
||||||
|
// Not found or empty: use ":-" alternative value
|
||||||
|
// Found and not empty: use ":+" alternative value
|
||||||
|
|
||||||
|
toks = ITstream::parse(altValue, IOstream::ASCII);
|
||||||
|
}
|
||||||
|
|
||||||
ITstream::append(std::move(toks), true); // Lazy resizing
|
ITstream::append(std::move(toks), true); // Lazy resizing
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Found primitive entry - copy tokens
|
// Found primitive entry - copy tokens
|
||||||
ITstream::append(eptr->stream(), true); // Lazy resizing
|
|
||||||
|
if (eptr->stream().empty() ? (altType == '-') : (altType == '+'))
|
||||||
|
{
|
||||||
|
// Not found or empty: use ":-" alternative value
|
||||||
|
// Found and not empty: use ":+" alternative value
|
||||||
|
|
||||||
|
tokenList toks(ITstream::parse(altValue, IOstream::ASCII));
|
||||||
|
|
||||||
|
ITstream::append(std::move(toks), true); // Lazy resizing
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ITstream::append(eptr->stream(), true); // Lazy resizing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*--------------------------------*- C++ -*----------------------------------*\
|
/*--------------------------------*- C++ -*----------------------------------*\
|
||||||
| ========= | |
|
| ========= | |
|
||||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||||
| \\ / O peration | Version: v1912 |
|
| \\ / O peration | Version: v2006 |
|
||||||
| \\ / A nd | Website: www.openfoam.com |
|
| \\ / A nd | Website: www.openfoam.com |
|
||||||
| \\/ M anipulation | |
|
| \\/ M anipulation | |
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
@ -14,21 +14,48 @@ FoamFile
|
|||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
// Do comparison
|
// Do comparison. Handles the first token after then '#if', which should
|
||||||
|
// correspond to a logical (true/false, ...) and integer (0,1, ...)
|
||||||
|
// but also a floating-point value with 0-1 range.
|
||||||
|
|
||||||
#if #eval "${FOAM_API:-0}"
|
#if ${FOAM_API:-false}
|
||||||
foamApi nonZero;
|
foamApi nonZero is ${FOAM_API:-0};
|
||||||
#else
|
#else
|
||||||
foamApi zeroValue;
|
foamApi zeroValue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if #eval "${XX_XXX_FOAM_API:-1000}"
|
#if ${XX_XXX_FOAM_API:-1000}
|
||||||
other "some entry";
|
other "some entry" ${XX_XXX_FOAM_API:-(0 1 0)};
|
||||||
#else
|
#else
|
||||||
other "unexpected";
|
other "unexpected";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if 0.1
|
||||||
|
roundToZero failed;
|
||||||
|
#else
|
||||||
|
roundToZero good with ${__expand_or_ignore_:-};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0.99
|
||||||
|
roundToOne good;
|
||||||
|
#else
|
||||||
|
roundToOne failed;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if -0.1
|
||||||
|
roundNegZero failed;
|
||||||
|
#else
|
||||||
|
roundNegZero good;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if -0.99
|
||||||
|
roundToNegOne good;
|
||||||
|
#else
|
||||||
|
roundToNegOne failed;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if #eval "${FOAM_API:-0} >= 1910"
|
#if #eval "${FOAM_API:-0} >= 1910"
|
||||||
evalType hasEvalWithConditionals;
|
evalType hasEvalWithConditionals;
|
||||||
#else
|
#else
|
||||||
@ -44,5 +71,23 @@ FoamFile
|
|||||||
condition false;
|
condition false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Some other conditionals
|
||||||
|
|
||||||
|
condition1 true;
|
||||||
|
condition2 false;
|
||||||
|
|
||||||
|
#if ${unknown:-${condition2:-${condition1}}}
|
||||||
|
multiExpansion1 failed;
|
||||||
|
#else
|
||||||
|
multiExpansion1 good;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if ${unknown:-${unknown:-${condition2:+true}}}
|
||||||
|
multiExpansion2 good = ${unkn:-${unkn:-${condition2:+on}}};
|
||||||
|
#else
|
||||||
|
multiExpansion2 failed;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
Reference in New Issue
Block a user