diff --git a/applications/test/string/Test-string.C b/applications/test/string/Test-string.C index 6d9bfd7babba7fdeb2b826e6877e89fe7d71604c..a53045225ad1119c5708b1de20b373629a0cf328 100644 --- a/applications/test/string/Test-string.C +++ b/applications/test/string/Test-string.C @@ -43,6 +43,8 @@ int main(int argc, char *argv[]) " $HOME kjhkjhkjh \" \\$HOME/tyetyery $; ${FOAM_RUN} \n $; hkjh;" " $(DONOTSUBST) some other <${USER}> with '${__UNKNOWN:-some default}'" " value " + " or with '${HOME:+Home was set}' via :+ alternative" + " or with '${__UNKNOWN:+unknown}' empty" ); dictionary dict; diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C index 2fbadd3a6ae4f0b26525aba053c1e06174ea6d18..ebbc47ca3b1cf1e94a6d3ef858e370286cb464d4 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C @@ -31,6 +31,45 @@ License // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +//! \cond fileScope +// Find the type/position of the ":-" or ":+" alternative values +// +static inline int findParameterAlternative +( + const std::string& s, + std::string::size_type& pos, + std::string::size_type endPos +) +{ + 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; +} +//! \endcond + + Foam::string Foam::stringOps::expand ( const string& original, @@ -66,7 +105,8 @@ Foam::string& Foam::stringOps::inplaceExpand string::size_type endVar = begVar; string::size_type delim = 0; - // The position of the ":-" default value + // The type/position of the ":-" or ":+" alternative values + int altType = 0; string::size_type altPos = string::npos; if (s[begVar+1] == '{') @@ -74,14 +114,11 @@ Foam::string& Foam::stringOps::inplaceExpand endVar = s.find('}', begVar); delim = 1; - // looks like ${parameter:-word} + // check for ${parameter:-word} or ${parameter:+word} if (endVar != string::npos) { - altPos = s.find(":-", begVar); - if (altPos != string::npos && altPos > endVar) - { - altPos = string::npos; - } + altPos = begVar; + altType = findParameterAlternative(s, altPos, endVar); } } else @@ -134,7 +171,7 @@ Foam::string& Foam::stringOps::inplaceExpand std::string altValue; if (altPos != string::npos) { - // had ":-" default value + // had ":-" or ":+" alternative value altValue = s.substr ( altPos + 2, @@ -148,17 +185,32 @@ Foam::string& Foam::stringOps::inplaceExpand if (fnd != HashTable<string, word, string::hash>::end()) { - s.std::string::replace - ( - begVar, - endVar - begVar + 1, - *fnd - ); - begVar += (*fnd).size(); + if (altPos != string::npos && altType == '+') + { + // was found, use ":+" alternative + s.std::string::replace + ( + begVar, + endVar - begVar + 1, + altValue + ); + begVar += altValue.size(); + } + else + { + // was found, use value + s.std::string::replace + ( + begVar, + endVar - begVar + 1, + *fnd + ); + begVar += (*fnd).size(); + } } - else if (altPos != string::npos) + else if (altPos != string::npos && altType == '-') { - // use alternative provided + // was not found, use ":-" alternative s.std::string::replace ( begVar, @@ -169,12 +221,8 @@ Foam::string& Foam::stringOps::inplaceExpand } else { - s.std::string::replace - ( - begVar, - endVar - begVar + 1, - "" - ); + // substitute with nothing, also for ":+" alternative + s.std::string::erase(begVar, endVar - begVar + 1); } } } @@ -351,7 +399,8 @@ Foam::string& Foam::stringOps::inplaceExpand string::size_type endVar = begVar; string::size_type delim = 0; - // The position of the ":-" default value + // The type/position of the ":-" or ":+" alternative values + int altType = 0; string::size_type altPos = string::npos; if (s[begVar+1] == '{') @@ -359,14 +408,11 @@ Foam::string& Foam::stringOps::inplaceExpand endVar = s.find('}', begVar); delim = 1; - // looks like ${parameter:-word} + // check for ${parameter:-word} or ${parameter:+word} if (endVar != string::npos) { - altPos = s.find(":-", begVar); - if (altPos != string::npos && altPos > endVar) - { - altPos = string::npos; - } + altPos = begVar; + altType = findParameterAlternative(s, altPos, endVar); } } else @@ -413,7 +459,7 @@ Foam::string& Foam::stringOps::inplaceExpand std::string altValue; if (altPos != string::npos) { - // had ":-" default value + // had ":-" or ":+" alternative value altValue = s.substr ( altPos + 2, @@ -424,34 +470,53 @@ Foam::string& Foam::stringOps::inplaceExpand const string varValue = getEnv(varName); if (varValue.size()) { - // direct replacement - s.std::string::replace - ( - begVar, - endVar - begVar + 1, - varValue - ); - begVar += varValue.size(); + if (altPos != string::npos && altType == '+') + { + // was found, use ":+" alternative + s.std::string::replace + ( + begVar, + endVar - begVar + 1, + altValue + ); + begVar += altValue.size(); + } + else + { + // was found, use value + s.std::string::replace + ( + begVar, + endVar - begVar + 1, + varValue + ); + begVar += varValue.size(); + } } else if (altPos != string::npos) { - // use alternative provided - s.std::string::replace - ( - begVar, - endVar - begVar + 1, - altValue - ); - begVar += altValue.size(); + // use ":-" or ":+" alternative values + if (altType == '-') + { + // was not found, use ":-" alternative + s.std::string::replace + ( + begVar, + endVar - begVar + 1, + altValue + ); + begVar += altValue.size(); + } + else + { + // was not found, ":+" alternative implies + // substitute with nothing + s.std::string::erase(begVar, endVar - begVar + 1); + } } else if (allowEmpty) { - s.std::string::replace - ( - begVar, - endVar - begVar + 1, - "" - ); + s.std::string::erase(begVar, endVar - begVar + 1); } else { @@ -459,7 +524,7 @@ Foam::string& Foam::stringOps::inplaceExpand ( "stringOps::inplaceExpand(string&, const bool)" ) - << "Unknown variable name " << varName << '.' + << "Unknown variable name '" << varName << "'" << exit(FatalError); } } diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H index 63a4679c9bf5bdf755ebec36e29945e0462de7d6..68ce3ac71979642c72c99b2bca034f852ab3a242 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H @@ -62,6 +62,13 @@ namespace stringOps // If parameter is unset or null, the \c defValue is substituted. // Otherwise, the value of parameter is substituted. // + // Supports alternative values as per the Bourne/Korn shell. + // \code + // "${parameter:+altValue}" + // \endcode + // If parameter is unset or null, nothing is substituted. + // Otherwise the \c altValue is substituted. + // // Any unknown entries are removed silently. // // Malformed entries (eg, brace mismatch, sigil followed by bad character) @@ -89,6 +96,13 @@ namespace stringOps // If parameter is unset or null, the \c defValue is substituted. // Otherwise, the value of parameter is substituted. // + // Supports alternative values as per the Bourne/Korn shell. + // \code + // "${parameter:+altValue}" + // \endcode + // If parameter is unset or null, nothing is substituted. + // Otherwise the \c altValue is substituted. + // // Any unknown entries are removed silently. // // Malformed entries (eg, brace mismatch, sigil followed by bad character) @@ -155,6 +169,13 @@ namespace stringOps // If parameter is unset or null, the \c defValue is substituted. // Otherwise, the value of parameter is substituted. // + // Supports alternative values as per the Bourne/Korn shell. + // \code + // "${parameter:+altValue}" + // \endcode + // If parameter is unset or null, nothing is substituted. + // Otherwise the \c altValue is substituted. + // // Any unknown entries are removed silently, if allowEmpty is true. // // Malformed entries (eg, brace mismatch, sigil followed by bad character) @@ -187,6 +208,13 @@ namespace stringOps // If parameter is unset or null, the \c defValue is substituted. // Otherwise, the value of parameter is substituted. // + // Supports alternative values as per the Bourne/Korn shell. + // \code + // "${parameter:+altValue}" + // \endcode + // If parameter is unset or null, nothing is substituted. + // Otherwise the \c altValue is substituted. + // // Any unknown entries are removed silently, if allowEmpty is true. // // Malformed entries (eg, brace mismatch, sigil followed by bad character)