diff --git a/applications/test/cstring/Test-cstring.C b/applications/test/cstring/Test-cstring.C index fc4605cfa4..fadc7a4755 100644 --- a/applications/test/cstring/Test-cstring.C +++ b/applications/test/cstring/Test-cstring.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -30,8 +30,10 @@ Description #include "DynamicList.H" #include "IOstreams.H" #include "fileNameList.H" +#include "stringOps.H" #include "stringList.H" #include "wordList.H" +#include "SubStrings.H" using namespace Foam; @@ -53,6 +55,26 @@ int print(const CStringList& cstrLst) } +// Using nullptr termination +int print(char *argv[]) +{ + if (!argv) + { + Info<< "argv=null" << endl; + return 0; + } + + int i=0; + while (argv[i]) + { + Info<< " argv[" << i << "] = \"" << argv[i] << "\"" << endl; + ++i; + } + + return i; +} + + // Main program: int main(int argc, char *argv[]) @@ -62,18 +84,49 @@ int main(int argc, char *argv[]) dynlst.append("string1 with content"); dynlst.append("string2 other content"); - dynlst.append("string3 done"); + dynlst.append("string3 more"); + dynlst.append("string4 done"); { CStringList inC(dynlst); - Info<< "input: " << dynlst << endl; + Info<< "input: " << dynlst << nl; print(inC); + + Info<< "null-terminated string list" << nl; + print(inC.strings()); + + Info<< "sublist: starting at " << inC.size()/2 << nl; + print(inC.strings(inC.size()/2)); + + Info<< nl; + } + + { + string testInput + ( + " A test input line with various spacing " + " and text to be split on whitespace " + ); + + Info<< testInput << nl; + SubStrings args = stringOps::splitSpace(testInput); + Info<< "split into " << args.size() << " args" << nl; + + CStringList inC(args); + print(inC); + + Info<< "sublist: starting at " << inC.size()/2 << nl; + print(inC.strings(inC.size()/2)); + + Info<< nl; } Info<<"command-line with " << CStringList::count(argv) << " items"<< endl; print(argc, argv); + + Info<< nl; { dynlst.clear(); for (int i=0; i. + +\*---------------------------------------------------------------------------*/ + +#include "CStringList.H" +#include "Ostream.H" + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Ostream& Foam::operator<<(Ostream& os, const CStringList& list) +{ + const int n = list.size(); + + for (int i = 0; i class SubStrings; + +Ostream& operator<<(Ostream& os, const CStringList& list); + /*---------------------------------------------------------------------------*\ Class CStringList Declaration \*---------------------------------------------------------------------------*/ @@ -82,6 +89,19 @@ class CStringList // Private Member Functions + //- Copy string characters into dest as NUL-terminated string. + // Forces conversion of std::sub_match to string form + // + // \return the location one-past the end of dest, which is used + // for the next destination + static inline char* stringCopy(char *dest, const std::string& str); + + //- Copy the input list of strings. + // \return number of arguments (argc) + template + int resetContent(const ListType& input); + + //- Disallow default bitwise copy construct CStringList(const CStringList&) = delete; @@ -96,11 +116,15 @@ public: //- Construct empty, adding content later (via reset). inline CStringList(); - - //- Construct from a list of strings + //- Copy construct from a list of strings // Copies the input characters. template - CStringList(const UList& input); + inline explicit CStringList(const UList& input); + + //- Copy construct from a list of sub-string references + // Copies the input characters. + template + inline explicit CStringList(const SubStrings& input); //- Destructor @@ -123,6 +147,11 @@ public: // The position at argc is a nullptr inline char** strings() const; + //- Return the sublist of C-strings (ie, argv) starting at the + //- specified offset. + // \param start the offset, must be less than argc + inline char** strings(int start) const; + //- Overall length of the flattened character (data) content inline size_t length() const; @@ -130,15 +159,20 @@ public: //- The flattened character content, with interspersed nul-chars inline const char* data() const; - // Edit //- Clear contents and free memory inline void clear(); //- Copy the input list of strings. + // \return number of arguments (argc) template - void reset(const UList& input); + inline int reset(const UList& input); + + //- Copy the input list of strings. + // \return number of arguments (argc) + template + inline int reset(const SubStrings& input); // Other @@ -153,6 +187,17 @@ public: template static inline List asList(const char * const argv[]); + + // Member operators + + //- Return element at the given index. No bounds checking. + inline const char* operator[](int i) const; + + + // IOstream Operators + + friend Ostream& operator<<(Ostream& os, const CStringList& list); + }; diff --git a/src/OpenFOAM/primitives/strings/lists/CStringListI.H b/src/OpenFOAM/primitives/strings/lists/CStringListI.H index 197633691e..6b9efee13a 100644 --- a/src/OpenFOAM/primitives/strings/lists/CStringListI.H +++ b/src/OpenFOAM/primitives/strings/lists/CStringListI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -23,20 +23,34 @@ License \*---------------------------------------------------------------------------*/ +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +inline char* Foam::CStringList::stringCopy(char *dest, const std::string& str) +{ + for (auto iter = str.cbegin(); iter != str.cend(); ++iter) + { + *dest = *iter; + ++dest; + } + *(dest++) = '\0'; + + return dest; +} + + // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * // inline int Foam::CStringList::count(const char * const argv[]) { - int nElem = 0; + int n = 0; if (argv) { - while (argv[nElem]) + while (argv[n]) { - ++nElem; + ++n; } } - - return nElem; + return n; } @@ -51,6 +65,24 @@ inline Foam::CStringList::CStringList() {} +template +inline Foam::CStringList::CStringList(const UList& input) +: + CStringList() +{ + reset(input); +} + + +template +inline Foam::CStringList::CStringList(const SubStrings& input) +: + CStringList() +{ + reset(input); +} + + // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // inline Foam::CStringList::~CStringList() @@ -97,10 +129,38 @@ inline char** Foam::CStringList::strings() const } +inline char** Foam::CStringList::strings(int start) const +{ + return &(argv_[start]); +} + + inline const char* Foam::CStringList::data() const { return data_; } +template +inline int Foam::CStringList::reset(const UList& input) +{ + return resetContent(input); +} + + +template +inline int Foam::CStringList::reset(const SubStrings& input) +{ + return resetContent(input); +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +inline const char* Foam::CStringList::operator[](int i) const +{ + return argv_[i]; +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/primitives/strings/lists/CStringListTemplates.C b/src/OpenFOAM/primitives/strings/lists/CStringListTemplates.C index 8c2fad816e..b656d32d93 100644 --- a/src/OpenFOAM/primitives/strings/lists/CStringListTemplates.C +++ b/src/OpenFOAM/primitives/strings/lists/CStringListTemplates.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -23,26 +23,14 @@ License \*---------------------------------------------------------------------------*/ -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // +#include "SubStrings.H" -template -Foam::CStringList::CStringList +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template +int Foam::CStringList::resetContent ( - const UList& input -) -: - CStringList() -{ - reset(input); -} - - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -template -void Foam::CStringList::reset -( - const UList& input + const ListType& input ) { clear(); @@ -52,36 +40,35 @@ void Foam::CStringList::reset // Special handling of an empty list argv_ = new char*[1]; argv_[0] = nullptr; // Final nullptr terminator - return; + return 0; } // Count overall required string length, including each trailing nul char for (const auto& str : input) { - len_ += str.size() + 1; + len_ += str.length() + 1; } --len_; // No final nul in overall count argv_ = new char*[input.size()+1]; // Extra +1 for terminating nullptr data_ = new char[len_+1]; // Extra +1 for terminating nul char - // Copy contents - char* ptr = data_; + argv_[0] = data_; // Starts here + for (const auto& str : input) { - argv_[argc_++] = ptr; // The start of this string - - for (auto iter = str.cbegin(); iter != str.cend(); ++iter) - { - *(ptr++) = *iter; - } - *(ptr++) = '\0'; + char *next = stringCopy(argv_[argc_], str); + argv_[++argc_] = next; // The start of next string } argv_[argc_] = nullptr; // Final nullptr terminator + + return argc_; } +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + template Foam::List Foam::CStringList::asList(int argc, const char * const argv[]) diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C index 8646523b68..5bbc041ba5 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C @@ -28,13 +28,14 @@ License #include "OSspecific.H" #include "etcFiles.H" #include "StringStream.H" +#include // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // namespace Foam { // Standard handling of "~/", "./" etc. -static void standardExpansions(Foam::string& s) +static void standardExpansions(std::string& s) { if (s.empty()) { @@ -181,52 +182,53 @@ Foam::string Foam::stringOps::expand ) { string s(original); - return inplaceExpand(s, mapping); + inplaceExpand(s, mapping); + return s; } -Foam::string& Foam::stringOps::inplaceExpand +void Foam::stringOps::inplaceExpand ( - string& s, + std::string& s, const HashTable& mapping, const char sigil ) { - string::size_type begVar = 0; + std::string::size_type varBeg = 0; // Expand $VAR or ${VAR} // Repeat until nothing more is found while ( - (begVar = s.find(sigil, begVar)) != string::npos - && begVar < s.size()-1 + (varBeg = s.find(sigil, varBeg)) != std::string::npos + && varBeg < s.size()-1 ) { - if (begVar == 0 || s[begVar-1] != '\\') + if (varBeg == 0 || s[varBeg-1] != '\\') { // Find end of first occurrence - string::size_type endVar = begVar; - string::size_type delim = 0; + std::string::size_type varEnd = varBeg; + std::string::size_type delim = 0; // The type/position of the ":-" or ":+" alternative values int altType = 0; - string::size_type altPos = string::npos; + auto altPos = std::string::npos; - if (s[begVar+1] == '{') + if (s[varBeg+1] == '{') { - endVar = s.find('}', begVar); + varEnd = s.find('}', varBeg); delim = 1; // check for ${parameter:-word} or ${parameter:+word} - if (endVar != string::npos) + if (varEnd != std::string::npos) { - altPos = begVar; - altType = findParameterAlternative(s, altPos, endVar); + altPos = varBeg; + altType = findParameterAlternative(s, altPos, varEnd); } } else { - string::const_iterator iter = s.cbegin() + begVar + 1; + string::const_iterator iter = s.cbegin() + varBeg + 1; // more generous in accepting keywords than for env variables while @@ -242,19 +244,19 @@ Foam::string& Foam::stringOps::inplaceExpand ) { ++iter; - ++endVar; + ++varEnd; } } - if (endVar == string::npos) + if (varEnd == std::string::npos) { // likely parsed '${...' without closing '}' - abort break; } - else if (endVar == begVar) + else if (varEnd == varBeg) { // parsed '${}' or $badChar - skip over - begVar = endVar + 1; + varBeg = varEnd + 1; } else { @@ -262,23 +264,23 @@ Foam::string& Foam::stringOps::inplaceExpand ( s.substr ( - begVar + 1 + delim, + varBeg + 1 + delim, ( - (altPos == string::npos ? endVar : altPos) - - begVar - 2*delim + (altPos == std::string::npos ? varEnd : altPos) + - varBeg - 2*delim ) ), false ); std::string altValue; - if (altPos != string::npos) + if (altPos != std::string::npos) { // had ":-" or ":+" alternative value altValue = s.substr ( altPos + 2, - endVar - altPos - 2*delim + varEnd - altPos - 2*delim ); } @@ -287,54 +289,52 @@ Foam::string& Foam::stringOps::inplaceExpand if (fnd.found()) { - if (altPos != string::npos && altType == '+') + if (altPos != std::string::npos && altType == '+') { // was found, use ":+" alternative s.std::string::replace ( - begVar, - endVar - begVar + 1, + varBeg, + varEnd - varBeg + 1, altValue ); - begVar += altValue.size(); + varBeg += altValue.size(); } else { // was found, use value s.std::string::replace ( - begVar, - endVar - begVar + 1, + varBeg, + varEnd - varBeg + 1, *fnd ); - begVar += (*fnd).size(); + varBeg += (*fnd).size(); } } - else if (altPos != string::npos && altType == '-') + else if (altPos != std::string::npos && altType == '-') { // was not found, use ":-" alternative s.std::string::replace ( - begVar, - endVar - begVar + 1, + varBeg, + varEnd - varBeg + 1, altValue ); - begVar += altValue.size(); + varBeg += altValue.size(); } else { // substitute with nothing, also for ":+" alternative - s.std::string::erase(begVar, endVar - begVar + 1); + s.std::string::erase(varBeg, varEnd - varBeg + 1); } } } else { - ++begVar; + ++varBeg; } } - - return s; } @@ -346,7 +346,8 @@ Foam::string Foam::stringOps::expand ) { string s(original); - return inplaceExpand(s, dict, sigil); + inplaceExpand(s, dict, sigil); + return s; } @@ -360,12 +361,7 @@ Foam::string Foam::stringOps::getVariable { string value; - const entry* eptr = dict.lookupScopedEntryPtr - ( - name, - true, - false - ); + const entry* eptr = dict.lookupScopedEntryPtr(name, true, false); if (eptr) { @@ -387,7 +383,7 @@ Foam::string Foam::stringOps::getVariable if (value.empty() && !name.empty()) { // The type/position of the ":-" or ":+" alternative values - string::size_type altPos = 0; + std::string::size_type altPos = 0; // check for parameter:-word or parameter:+word const int altType = @@ -438,13 +434,13 @@ Foam::string Foam::stringOps::getVariable Foam::string Foam::stringOps::expand ( const string& s, - string::size_type& index, + std::string::size_type& index, const dictionary& dict, const bool allowEnvVars, const bool allowEmpty ) { - string newString; + string out; while (index < s.size()) { @@ -453,55 +449,55 @@ Foam::string Foam::stringOps::expand // Recurse to parse variable name index += 2; string val = expand(s, index, dict, allowEnvVars, allowEmpty); - newString.append(val); + out.append(val); } else if (s[index] == '}') { - return getVariable(newString, dict, allowEnvVars, allowEmpty); + return getVariable(out, dict, allowEnvVars, allowEmpty); } else { - newString.append(string(s[index])); + out.append(string(s[index])); } ++index; } - return newString; + return out; } -Foam::string& Foam::stringOps::inplaceExpand +void Foam::stringOps::inplaceExpand ( - string& s, + std::string& s, const dictionary& dict, const bool allowEnvVars, const bool allowEmpty, const char sigil ) { - string::size_type begVar = 0; + std::string::size_type varBeg = 0; // Expand $VAR or ${VAR} // Repeat until nothing more is found while ( - (begVar = s.find(sigil, begVar)) != string::npos - && begVar < s.size()-1 + (varBeg = s.find(sigil, varBeg)) != std::string::npos + && varBeg < s.size()-1 ) { - if (begVar == 0 || s[begVar-1] != '\\') + if (varBeg == 0 || s[varBeg-1] != '\\') { - if (s[begVar+1] == '{') + if (s[varBeg+1] == '{') { // Recursive variable expansion mode - auto stringStart = begVar; - begVar += 2; + auto stringStart = varBeg; + varBeg += 2; string varValue ( expand ( s, - begVar, + varBeg, dict, allowEnvVars, allowEmpty @@ -511,16 +507,16 @@ Foam::string& Foam::stringOps::inplaceExpand s.std::string::replace ( stringStart, - begVar - stringStart + 1, + varBeg - stringStart + 1, varValue ); - begVar = stringStart+varValue.size(); + varBeg = stringStart+varValue.size(); } else { - string::const_iterator iter = s.cbegin() + begVar + 1; - string::size_type endVar = begVar; + std::string::const_iterator iter = s.cbegin() + varBeg + 1; + std::string::size_type varEnd = varBeg; // more generous in accepting keywords than for env variables while @@ -536,15 +532,15 @@ Foam::string& Foam::stringOps::inplaceExpand ) { ++iter; - ++endVar; + ++varEnd; } const word varName ( s.substr ( - begVar + 1, - endVar - begVar + varBeg + 1, + varEnd - varBeg ), false ); @@ -562,57 +558,55 @@ Foam::string& Foam::stringOps::inplaceExpand s.std::string::replace ( - begVar, + varBeg, varName.size()+1, varValue ); - begVar += varValue.size(); + varBeg += varValue.size(); } } else { - ++begVar; + ++varBeg; } } // Standard handling of "~/", "./" etc. standardExpansions(s); - - return s; } -Foam::string& Foam::stringOps::inplaceExpand +void Foam::stringOps::inplaceExpand ( - string& s, + std::string& s, const dictionary& dict, const char sigil ) { - string::size_type begVar = 0; + std::string::size_type varBeg = 0; // Expand $VAR or ${VAR} // Repeat until nothing more is found while ( - (begVar = s.find(sigil, begVar)) != string::npos - && begVar < s.size()-1 + (varBeg = s.find(sigil, varBeg)) != std::string::npos + && varBeg < s.size()-1 ) { - if (begVar == 0 || s[begVar-1] != '\\') + if (varBeg == 0 || s[varBeg-1] != '\\') { // Find end of first occurrence - string::size_type endVar = begVar; - string::size_type delim = 0; + std::string::size_type varEnd = varBeg; + std::string::size_type delim = 0; - if (s[begVar+1] == '{') + if (s[varBeg+1] == '{') { - endVar = s.find('}', begVar); + varEnd = s.find('}', varBeg); delim = 1; } else { - string::const_iterator iter = s.cbegin() + begVar + 1; + string::const_iterator iter = s.cbegin() + varBeg + 1; // more generous in accepting keywords than for env variables while @@ -628,19 +622,19 @@ Foam::string& Foam::stringOps::inplaceExpand ) { ++iter; - ++endVar; + ++varEnd; } } - if (endVar == string::npos) + if (varEnd == std::string::npos) { // likely parsed '${...' without closing '}' - abort break; } - else if (endVar == begVar) + else if (varEnd == varBeg) { // parsed '${}' or $badChar - skip over - begVar = endVar + 1; + varBeg = varEnd + 1; } else { @@ -648,8 +642,8 @@ Foam::string& Foam::stringOps::inplaceExpand ( s.substr ( - begVar + 1 + delim, - endVar - begVar - 2*delim + varBeg + 1 + delim, + varEnd - varBeg - 2*delim ), false ); @@ -687,26 +681,24 @@ Foam::string& Foam::stringOps::inplaceExpand s.std::string::replace ( - begVar, - endVar - begVar + 1, + varBeg, + varEnd - varBeg + 1, buf.str() ); - begVar += buf.str().size(); + varBeg += buf.str().size(); } else { // not defined - leave original string untouched - begVar = endVar + 1; + varBeg = varEnd + 1; } } } else { - ++begVar; + ++varBeg; } } - - return s; } @@ -717,51 +709,52 @@ Foam::string Foam::stringOps::expand ) { string s(original); - return inplaceExpand(s, allowEmpty); + inplaceExpand(s, allowEmpty); + return s; } -Foam::string& Foam::stringOps::inplaceExpand +void Foam::stringOps::inplaceExpand ( - string& s, + std::string& s, const bool allowEmpty ) { - string::size_type begVar = 0; + std::string::size_type varBeg = 0; // Expand $VARS // Repeat until nothing more is found while ( - (begVar = s.find('$', begVar)) != string::npos - && begVar < s.size()-1 + (varBeg = s.find('$', varBeg)) != std::string::npos + && varBeg < s.size()-1 ) { - if (begVar == 0 || s[begVar-1] != '\\') + if (varBeg == 0 || s[varBeg-1] != '\\') { // Find end of first occurrence - string::size_type endVar = begVar; - string::size_type delim = 0; + std::string::size_type varEnd = varBeg; + std::string::size_type delim = 0; // The type/position of the ":-" or ":+" alternative values int altType = 0; - string::size_type altPos = string::npos; + std::string::size_type altPos = std::string::npos; - if (s[begVar+1] == '{') + if (s[varBeg+1] == '{') { - endVar = s.find('}', begVar); + varEnd = s.find('}', varBeg); delim = 1; // check for ${parameter:-word} or ${parameter:+word} - if (endVar != string::npos) + if (varEnd != std::string::npos) { - altPos = begVar; - altType = findParameterAlternative(s, altPos, endVar); + altPos = varBeg; + altType = findParameterAlternative(s, altPos, varEnd); } } else { - string::const_iterator iter = s.cbegin() + begVar + 1; + string::const_iterator iter = s.cbegin() + varBeg + 1; while ( @@ -770,20 +763,20 @@ Foam::string& Foam::stringOps::inplaceExpand ) { ++iter; - ++endVar; + ++varEnd; } } - if (endVar == string::npos) + if (varEnd == std::string::npos) { // likely parsed '${...' without closing '}' - abort break; } - else if (endVar == begVar) + else if (varEnd == varBeg) { // parsed '${}' or $badChar - skip over - begVar = endVar + 1; + varBeg = varEnd + 1; } else { @@ -791,53 +784,53 @@ Foam::string& Foam::stringOps::inplaceExpand ( s.substr ( - begVar + 1 + delim, + varBeg + 1 + delim, ( - (altPos == string::npos ? endVar : altPos) - - begVar - 2*delim + (altPos == std::string::npos ? varEnd : altPos) + - varBeg - 2*delim ) ), false ); std::string altValue; - if (altPos != string::npos) + if (altPos != std::string::npos) { // had ":-" or ":+" alternative value altValue = s.substr ( altPos + 2, - endVar - altPos - 2*delim + varEnd - altPos - 2*delim ); } const string varValue = getEnv(varName); if (varValue.size()) { - if (altPos != string::npos && altType == '+') + if (altPos != std::string::npos && altType == '+') { // was found, use ":+" alternative s.std::string::replace ( - begVar, - endVar - begVar + 1, + varBeg, + varEnd - varBeg + 1, altValue ); - begVar += altValue.size(); + varBeg += altValue.size(); } else { // was found, use value s.std::string::replace ( - begVar, - endVar - begVar + 1, + varBeg, + varEnd - varBeg + 1, varValue ); - begVar += varValue.size(); + varBeg += varValue.size(); } } - else if (altPos != string::npos) + else if (altPos != std::string::npos) { // use ":-" or ":+" alternative values if (altType == '-') @@ -845,22 +838,22 @@ Foam::string& Foam::stringOps::inplaceExpand // was not found, use ":-" alternative s.std::string::replace ( - begVar, - endVar - begVar + 1, + varBeg, + varEnd - varBeg + 1, altValue ); - begVar += altValue.size(); + varBeg += altValue.size(); } else { // was not found, ":+" alternative implies // substitute with nothing - s.std::string::erase(begVar, endVar - begVar + 1); + s.std::string::erase(varBeg, varEnd - varBeg + 1); } } else if (allowEmpty) { - s.std::string::erase(begVar, endVar - begVar + 1); + s.std::string::erase(varBeg, varEnd - varBeg + 1); } else { @@ -872,18 +865,16 @@ Foam::string& Foam::stringOps::inplaceExpand } else { - ++begVar; + ++varBeg; } } // Standard handling of "~/", "./" etc. standardExpansions(s); - - return s; } -bool Foam::stringOps::inplaceReplaceVar(string& s, const word& varName) +bool Foam::stringOps::inplaceReplaceVar(std::string& s, const word& varName) { if (s.empty() || varName.empty()) { @@ -911,7 +902,7 @@ Foam::string Foam::stringOps::trimLeft(const string& s) { if (!s.empty()) { - string::size_type beg = 0; + std::string::size_type beg = 0; while (beg < s.size() && std::isspace(s[beg])) { ++beg; @@ -927,11 +918,11 @@ Foam::string Foam::stringOps::trimLeft(const string& s) } -Foam::string& Foam::stringOps::inplaceTrimLeft(string& s) +void Foam::stringOps::inplaceTrimLeft(std::string& s) { if (!s.empty()) { - string::size_type beg = 0; + std::string::size_type beg = 0; while (beg < s.size() && std::isspace(s[beg])) { ++beg; @@ -942,8 +933,6 @@ Foam::string& Foam::stringOps::inplaceTrimLeft(string& s) s.erase(0, beg); } } - - return s; } @@ -951,15 +940,15 @@ Foam::string Foam::stringOps::trimRight(const string& s) { if (!s.empty()) { - string::size_type sz = s.size(); - while (sz && std::isspace(s[sz-1])) + auto n = s.size(); + while (n && std::isspace(s[n-1])) { - --sz; + --n; } - if (sz < s.size()) + if (n < s.size()) { - return s.substr(0, sz); + return s.substr(0, n); } } @@ -967,20 +956,18 @@ Foam::string Foam::stringOps::trimRight(const string& s) } -Foam::string& Foam::stringOps::inplaceTrimRight(string& s) +void Foam::stringOps::inplaceTrimRight(std::string& s) { if (!s.empty()) { - string::size_type sz = s.size(); - while (sz && std::isspace(s[sz-1])) + auto n = s.size(); + while (n && std::isspace(s[n-1])) { - --sz; + --n; } - s.resize(sz); + s.resize(n); } - - return s; } @@ -990,13 +977,51 @@ Foam::string Foam::stringOps::trim(const string& original) } -Foam::string& Foam::stringOps::inplaceTrim(string& s) +void Foam::stringOps::inplaceTrim(std::string& s) { inplaceTrimRight(s); inplaceTrimLeft(s); +} + +Foam::string Foam::stringOps::lower(const string& original) +{ + string s(original); + inplaceLower(s); return s; } +void Foam::stringOps::inplaceLower(std::string& s) +{ + for (auto iter = s.begin(); iter != s.end(); ++iter) + { + *iter = static_cast + ( + std::tolower(static_cast(*iter)) + ); + } +} + + +Foam::string Foam::stringOps::upper(const string& original) +{ + string s(original); + inplaceUpper(s); + return s; +} + + +void Foam::stringOps::inplaceUpper(std::string& s) +{ + for (auto iter = s.begin(); iter != s.end(); ++iter) + { + *iter = static_cast + ( + std::toupper(static_cast(*iter)) + ); + } +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H index 7146891d37..de89b954a7 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H @@ -122,9 +122,9 @@ namespace stringOps // // \note the leading sigil can be changed to avoid conflicts with other // string expansions - string& inplaceExpand + void inplaceExpand ( - string& s, + std::string& s, const HashTable& mapping, const char sigil = '$' ); @@ -168,7 +168,7 @@ namespace stringOps string expand ( const string& s, - string::size_type& index, + std::string::size_type& index, const dictionary& dict, const bool allowEnvVars, const bool allowEmpty @@ -186,9 +186,9 @@ namespace stringOps // // \note the leading sigil can be changed to avoid conflicts with other // string expansions - string& inplaceExpand + void inplaceExpand ( - string& s, + std::string& s, const dictionary& dict, const bool allowEnvVars, const bool allowEmpty, @@ -205,9 +205,9 @@ namespace stringOps // // \note the leading sigil can be changed to avoid conflicts with other // string expansions - string& inplaceExpand + void inplaceExpand ( - string& s, + std::string& s, const dictionary& dict, const char sigil = '$' ); @@ -276,9 +276,9 @@ namespace stringOps // // \sa // Foam::findEtcFile - string& inplaceExpand + void inplaceExpand ( - string& s, + std::string& s, const bool allowEmpty = false ); @@ -286,26 +286,39 @@ namespace stringOps //- Replace environment variable contents with its name. // This is essentially the inverse operation for inplaceExpand. // Return true if a replacement was successful. - bool inplaceReplaceVar(string& s, const word& varName); + bool inplaceReplaceVar(std::string& s, const word& varName); //- Return string trimmed of leading whitespace string trimLeft(const string& s); //- Trim leading whitespace inplace - string& inplaceTrimLeft(string& s); + void inplaceTrimLeft(std::string& s); //- Return string trimmed of trailing whitespace string trimRight(const string& s); //- Trim trailing whitespace inplace - string& inplaceTrimRight(string& s); + void inplaceTrimRight(std::string& s); //- Return string trimmed of leading and trailing whitespace string trim(const string& original); //- Trim leading and trailing whitespace inplace - string& inplaceTrim(string& s); + void inplaceTrim(std::string& s); + + + //- Return string transformed with std::tolower on each character + string lower(const string& original); + + //- Inplace transform string with std::tolower on each character + void inplaceLower(std::string& s); + + //- Return string transformed with std::toupper on each character + string upper(const string& original); + + //- Inplace transform string with std::toupper on each character + void inplaceUpper(std::string& s); //- Using printf-formatter for a word representation of the primitive.