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:
parent
3c9c39e92a
commit
083181cac4
@ -436,7 +436,7 @@ Foam::Istream& Foam::ISstream::read(word& str)
|
||||
{
|
||||
if (!depth)
|
||||
{
|
||||
break; // Closed ')' without a '(' ? ... stop
|
||||
break; // Closed ')' without an opening '(' ? ... stop
|
||||
}
|
||||
--depth;
|
||||
}
|
||||
@ -627,43 +627,55 @@ Foam::Istream& Foam::ISstream::readVariable(std::string& str)
|
||||
}
|
||||
buf[nChar++] = c;
|
||||
|
||||
char endChar = token::END_LIST;
|
||||
|
||||
str.clear();
|
||||
if (c == token::BEGIN_BLOCK)
|
||||
{
|
||||
// Processing ${...} style
|
||||
|
||||
endChar = token::END_BLOCK;
|
||||
// Processing ${...} style.
|
||||
++depth;
|
||||
|
||||
// Could check that the next char is good and not one of '{}'
|
||||
// since this would indicate "${}", "${{..." or truncated "${"
|
||||
|
||||
while
|
||||
(
|
||||
(nChar < maxLen) && get(c)
|
||||
&&
|
||||
(
|
||||
validVariableChar(c)
|
||||
|| (c == token::BEGIN_BLOCK || c == token::END_BLOCK)
|
||||
)
|
||||
)
|
||||
while (get(c))
|
||||
{
|
||||
buf[nChar++] = c;
|
||||
if (nChar == maxLen)
|
||||
{
|
||||
str.append(buf, nChar);
|
||||
nChar = 0;
|
||||
}
|
||||
if (c == token::BEGIN_BLOCK)
|
||||
{
|
||||
++depth;
|
||||
}
|
||||
else if (c == token::END_BLOCK)
|
||||
{
|
||||
--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))
|
||||
{
|
||||
@ -683,7 +695,7 @@ Foam::Istream& Foam::ISstream::readVariable(std::string& str)
|
||||
{
|
||||
if (!depth)
|
||||
{
|
||||
break; // Closed ')' without a '(' ? ... stop
|
||||
break; // Closed ')' without an opening '(' ? ... stop
|
||||
}
|
||||
--depth;
|
||||
}
|
||||
@ -733,7 +745,7 @@ Foam::Istream& Foam::ISstream::readVariable(std::string& str)
|
||||
{
|
||||
IOWarningInFunction(*this)
|
||||
<< "Missing " << depth
|
||||
<< " closing '" << endChar << "' while parsing" << nl << nl
|
||||
<< " closing ')' while parsing" << nl << nl
|
||||
<< buf << nl << endl;
|
||||
}
|
||||
|
||||
@ -762,7 +774,7 @@ Foam::Istream& Foam::ISstream::readVerbatim(std::string& str)
|
||||
get(nextC);
|
||||
if (nextC == token::END_BLOCK)
|
||||
{
|
||||
// The closing "#}" found
|
||||
// Found closing "#}" sequence
|
||||
str.append(buf, nChar);
|
||||
return *this;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2019 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -937,6 +937,9 @@ public:
|
||||
|
||||
// Write
|
||||
|
||||
//- Write sub-dictionary with its dictName as its header
|
||||
void writeEntry(Ostream& os) const;
|
||||
|
||||
//- Write sub-dictionary with the keyword as its header
|
||||
void writeEntry(const keyType& keyword, Ostream& os) const;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2019 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -161,6 +161,14 @@ Foam::Istream& Foam::operator>>(Istream& is, dictionary& dict)
|
||||
|
||||
// * * * * * * * * * * * * * * 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
|
||||
{
|
||||
os.beginBlock(kw);
|
||||
|
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2019 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -31,6 +31,45 @@ License
|
||||
#include "OSspecific.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 * * * * * * * * * * * //
|
||||
|
||||
bool Foam::primitiveEntry::expandVariable
|
||||
@ -39,19 +78,49 @@ bool Foam::primitiveEntry::expandVariable
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
int altType = 0; // Type ('-' or '+') for ":-" or ":+" alternatives
|
||||
word expanded;
|
||||
string altValue;
|
||||
|
||||
if (varName.size() > 1 && varName[0] == token::BEGIN_BLOCK)
|
||||
{
|
||||
// Recursive substitution mode.
|
||||
// Content between {} is replaced with expansion.
|
||||
string expanded(varName.substr(1, varName.size()-2));
|
||||
// Replace content between {} with string expansion and
|
||||
// handle ${parameter:-word} or ${parameter:+word}
|
||||
|
||||
// Copy into a word without stripping
|
||||
expanded.assign(varName, 1, varName.size()-2);
|
||||
|
||||
// Substitute dictionary and environment variables.
|
||||
// Do not allow empty substitutions.
|
||||
stringOps::inplaceExpand(expanded, dict, true, false);
|
||||
// - Allow environment.
|
||||
// - 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.
|
||||
// Having a pattern match means that in this example:
|
||||
// {
|
||||
@ -61,18 +130,36 @@ bool Foam::primitiveEntry::expandVariable
|
||||
// The $internalField would be matched by the ".*" !!!
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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)
|
||||
<< "Illegal dictionary entry or environment variable name "
|
||||
<< varName << nl
|
||||
<< lookupName << nl
|
||||
<< "Known dictionary entries: " << dict.toc() << nl
|
||||
<< exit(FatalIOError);
|
||||
|
||||
@ -91,12 +178,33 @@ bool Foam::primitiveEntry::expandVariable
|
||||
|
||||
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
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v1912 |
|
||||
| \\ / O peration | Version: v2006 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ 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}"
|
||||
foamApi nonZero;
|
||||
#if ${FOAM_API:-false}
|
||||
foamApi nonZero is ${FOAM_API:-0};
|
||||
#else
|
||||
foamApi zeroValue;
|
||||
#endif
|
||||
|
||||
#if #eval "${XX_XXX_FOAM_API:-1000}"
|
||||
other "some entry";
|
||||
#if ${XX_XXX_FOAM_API:-1000}
|
||||
other "some entry" ${XX_XXX_FOAM_API:-(0 1 0)};
|
||||
#else
|
||||
other "unexpected";
|
||||
#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"
|
||||
evalType hasEvalWithConditionals;
|
||||
#else
|
||||
@ -44,5 +71,23 @@ FoamFile
|
||||
condition false;
|
||||
#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
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
Loading…
Reference in New Issue
Block a user