Foam::string& Foam::stringOps::inplaceExpand ( string& s, const bool allowEmpty ) { string::size_type begVar = 0; // Expand $VARS // Repeat until nothing more is found while ( (begVar = s.find('$', begVar)) != string::npos && begVar < s.size()-1 ) { if (begVar == 0 || s[begVar-1] != '\\') { // Find end of first occurrence string::size_type endVar = begVar; string::size_type delim = 0; // The type/position of the ":-" or ":+" alternative values int altType = 0; string::size_type altPos = string::npos; if (s[begVar+1] == '{') { endVar = s.find('}', begVar); delim = 1; // check for ${parameter:-word} or ${parameter:+word} if (endVar != string::npos) { altPos = begVar; altType = findParameterAlternative(s, altPos, endVar); } } else { string::iterator iter = s.begin() + begVar + 1; while ( iter != s.end() && (isalnum(*iter) || *iter == '_') ) { ++iter; ++endVar; } } if (endVar == string::npos) { // likely parsed '${...' without closing '}' - abort break; } else if (endVar == begVar) { // parsed '${}' or $badChar - skip over begVar = endVar + 1; } else { const word varName ( s.substr ( begVar + 1 + delim, ( (altPos == string::npos ? endVar : altPos) - begVar - 2*delim ) ), false ); std::string altValue; if (altPos != string::npos) { // had ":-" or ":+" alternative value altValue = s.substr ( altPos + 2, endVar - altPos - 2*delim ); } const string varValue = getEnv(varName); if (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 ":-" 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::erase(begVar, endVar - begVar + 1); } else { FatalErrorIn ( "stringOps::inplaceExpand(string&, const bool)" ) << "Unknown variable name '" << varName << "'" << exit(FatalError); } } } else { ++begVar; } } if (!s.empty()) { if (s[0] == '~') { // Expand initial ~ // ~/ => home directory // ~OpenFOAM => site/user OpenFOAM configuration directory // ~user => home directory for specified user string user; fileName file; if ((begVar = s.find('/')) != string::npos) { user = s.substr(1, begVar - 1); file = s.substr(begVar + 1); } else { user = s.substr(1); } // NB: be a bit lazy and expand ~unknownUser as an // empty string rather than leaving it untouched. // otherwise add extra test if (user == "OpenFOAM") { s = findEtcFile(file); } else { s = home(user)/file; } } else if (s[0] == '.') { // Expand a lone '.' and an initial './' into cwd if (s.size() == 1) { s = cwd(); } else if (s[1] == '/') { s.std::string::replace(0, 1, cwd()); } } } return s; }
Foam::string& Foam::stringOps::inplaceExpand ( string& s, const HashTable<string, word, string::hash>& mapping, const char sigil ) { string::size_type begVar = 0; // Expand $VAR or ${VAR} // Repeat until nothing more is found while ( (begVar = s.find(sigil, begVar)) != string::npos && begVar < s.size()-1 ) { if (begVar == 0 || s[begVar-1] != '\\') { // Find end of first occurrence string::size_type endVar = begVar; string::size_type delim = 0; // The type/position of the ":-" or ":+" alternative values int altType = 0; string::size_type altPos = string::npos; if (s[begVar+1] == '{') { endVar = s.find('}', begVar); delim = 1; // check for ${parameter:-word} or ${parameter:+word} if (endVar != string::npos) { altPos = begVar; altType = findParameterAlternative(s, altPos, endVar); } } else { string::iterator iter = s.begin() + begVar + 1; // more generous in accepting keywords than for env variables while ( iter != s.end() && ( isalnum(*iter) || *iter == '.' || *iter == ':' || *iter == '_' ) ) { ++iter; ++endVar; } } if (endVar == string::npos) { // likely parsed '${...' without closing '}' - abort break; } else if (endVar == begVar) { // parsed '${}' or $badChar - skip over begVar = endVar + 1; } else { const word varName ( s.substr ( begVar + 1 + delim, ( (altPos == string::npos ? endVar : altPos) - begVar - 2*delim ) ), false ); std::string altValue; if (altPos != string::npos) { // had ":-" or ":+" alternative value altValue = s.substr ( altPos + 2, endVar - altPos - 2*delim ); } HashTable<string, word, string::hash>::const_iterator fnd = mapping.find(varName); if (fnd != HashTable<string, word, string::hash>::end()) { 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 && altType == '-') { // was not found, use ":-" alternative s.std::string::replace ( begVar, endVar - begVar + 1, altValue ); begVar += altValue.size(); } else { // substitute with nothing, also for ":+" alternative s.std::string::erase(begVar, endVar - begVar + 1); } } } else { ++begVar; } } return s; }
void Foam::stringOps::variables ( wordHashSet& vars, const string& s, const char sigil ) { string::size_type begVar = 0; // Expand $VAR or ${VAR} // Repeat until nothing more is found while ( (begVar = s.find(sigil, begVar)) != string::npos && begVar < s.size()-1 ) { if (begVar == 0 || s[begVar-1] != '\\') { // Find end of first occurrence string::size_type endVar = begVar; string::size_type delim = 0; // The type/position of the ":-" or ":+" alternative values string::size_type altPos = string::npos; if (s[begVar+1] == '{') { endVar = s.find('}', begVar); delim = 1; // check for ${parameter:-word} or ${parameter:+word} if (endVar != string::npos) { altPos = begVar; findParameterAlternative(s, altPos, endVar); } } else { string::const_iterator iter = s.cbegin() + begVar + 1; // more generous in accepting keywords than for env variables while ( iter != s.cend() && ( isalnum(*iter) || *iter == '.' || *iter == ':' || *iter == '_' ) ) { ++iter; ++endVar; } } if (endVar == string::npos) { // likely parsed '${...' without closing '}' - abort break; } else if (endVar == begVar) { // parsed '${}' or $badChar - skip over begVar = endVar + 1; } else { const word varName ( s.substr ( begVar + 1 + delim, ( (altPos == string::npos ? endVar : altPos) - begVar - 2*delim ) ), false ); vars.insert(varName); begVar = endVar + 1; } } else { ++begVar; } } }