ENH: stringOps inplace methods now use a std::string parameter

- this makes them applicable to Foam::string, Foam::word etc

ENH: improvements to CStringList

- add strings() sublist variant which can be useful when handling
  command arguments separately

- add construct from SubStrings.
This commit is contained in:
Mark Olesen
2017-11-22 08:03:52 +01:00
parent d65ca495d3
commit a881204946
9 changed files with 449 additions and 220 deletions

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -30,8 +30,10 @@ Description
#include "DynamicList.H" #include "DynamicList.H"
#include "IOstreams.H" #include "IOstreams.H"
#include "fileNameList.H" #include "fileNameList.H"
#include "stringOps.H"
#include "stringList.H" #include "stringList.H"
#include "wordList.H" #include "wordList.H"
#include "SubStrings.H"
using namespace Foam; 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: // Main program:
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -62,18 +84,49 @@ int main(int argc, char *argv[])
dynlst.append("string1 with content"); dynlst.append("string1 with content");
dynlst.append("string2 other content"); dynlst.append("string2 other content");
dynlst.append("string3 done"); dynlst.append("string3 more");
dynlst.append("string4 done");
{ {
CStringList inC(dynlst); CStringList inC(dynlst);
Info<< "input: " << dynlst << endl; Info<< "input: " << dynlst << nl;
print(inC); 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<string> 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; Info<<"command-line with " << CStringList::count(argv) << " items"<< endl;
print(argc, argv); print(argc, argv);
Info<< nl;
{ {
dynlst.clear(); dynlst.clear();
for (int i=0; i<argc; ++i) for (int i=0; i<argc; ++i)

View File

@ -112,6 +112,7 @@ $(strings)/fileName/fileNameIO.C
$(strings)/keyType/keyType.C $(strings)/keyType/keyType.C
$(strings)/wordRe/wordRe.C $(strings)/wordRe/wordRe.C
$(strings)/wordRes/wordRes.C $(strings)/wordRes/wordRes.C
$(strings)/lists/CStringList.C
$(strings)/lists/hashedWordList.C $(strings)/lists/hashedWordList.C
$(strings)/stringOps/stringOps.C $(strings)/stringOps/stringOps.C
$(strings)/stringOps/stringOpsSort.C $(strings)/stringOps/stringOpsSort.C

View File

@ -69,7 +69,7 @@ word name(const char* fmt, const int32_t val);
//- Return a word representation of an int32, using printf-style formatter. //- Return a word representation of an int32, using printf-style formatter.
// The representation is not checked for valid word characters. // The representation is not checked for valid word characters.
word name(const std::string&, const int32_t val); word name(const std::string& fmt, const int32_t val);
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //

View File

@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#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<n; ++i)
{
if (i) os << ' ';
if (list[i]) os << list[i];
}
return os;
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -58,6 +58,13 @@ Description
namespace Foam namespace Foam
{ {
// Forward declarations
class Ostream;
class CStringList;
template<class String> class SubStrings;
Ostream& operator<<(Ostream& os, const CStringList& list);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class CStringList Declaration Class CStringList Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -82,6 +89,19 @@ class CStringList
// Private Member Functions // 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<class ListType>
int resetContent(const ListType& input);
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
CStringList(const CStringList&) = delete; CStringList(const CStringList&) = delete;
@ -96,11 +116,15 @@ public:
//- Construct empty, adding content later (via reset). //- Construct empty, adding content later (via reset).
inline CStringList(); inline CStringList();
//- Copy construct from a list of strings
//- Construct from a list of strings
// Copies the input characters. // Copies the input characters.
template<class StringType> template<class StringType>
CStringList(const UList<StringType>& input); inline explicit CStringList(const UList<StringType>& input);
//- Copy construct from a list of sub-string references
// Copies the input characters.
template<class StringType>
inline explicit CStringList(const SubStrings<StringType>& input);
//- Destructor //- Destructor
@ -123,6 +147,11 @@ public:
// The position at argc is a nullptr // The position at argc is a nullptr
inline char** strings() const; 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 //- Overall length of the flattened character (data) content
inline size_t length() const; inline size_t length() const;
@ -130,15 +159,20 @@ public:
//- The flattened character content, with interspersed nul-chars //- The flattened character content, with interspersed nul-chars
inline const char* data() const; inline const char* data() const;
// Edit // Edit
//- Clear contents and free memory //- Clear contents and free memory
inline void clear(); inline void clear();
//- Copy the input list of strings. //- Copy the input list of strings.
// \return number of arguments (argc)
template<class StringType> template<class StringType>
void reset(const UList<StringType>& input); inline int reset(const UList<StringType>& input);
//- Copy the input list of strings.
// \return number of arguments (argc)
template<class StringType>
inline int reset(const SubStrings<StringType>& input);
// Other // Other
@ -153,6 +187,17 @@ public:
template<class StringType> template<class StringType>
static inline List<StringType> asList(const char * const argv[]); static inline List<StringType> 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);
}; };

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License 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 * * * * * * * * * * * * * // // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
inline int Foam::CStringList::count(const char * const argv[]) inline int Foam::CStringList::count(const char * const argv[])
{ {
int nElem = 0; int n = 0;
if (argv) if (argv)
{ {
while (argv[nElem]) while (argv[n])
{ {
++nElem; ++n;
} }
} }
return n;
return nElem;
} }
@ -51,6 +65,24 @@ inline Foam::CStringList::CStringList()
{} {}
template<class StringType>
inline Foam::CStringList::CStringList(const UList<StringType>& input)
:
CStringList()
{
reset(input);
}
template<class StringType>
inline Foam::CStringList::CStringList(const SubStrings<StringType>& input)
:
CStringList()
{
reset(input);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
inline Foam::CStringList::~CStringList() 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 inline const char* Foam::CStringList::data() const
{ {
return data_; return data_;
} }
template<class StringType>
inline int Foam::CStringList::reset(const UList<StringType>& input)
{
return resetContent(input);
}
template<class StringType>
inline int Foam::CStringList::reset(const SubStrings<StringType>& input)
{
return resetContent(input);
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline const char* Foam::CStringList::operator[](int i) const
{
return argv_[i];
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -23,26 +23,14 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // #include "SubStrings.H"
template<class StringType> // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::CStringList::CStringList
template<class ListType>
int Foam::CStringList::resetContent
( (
const UList<StringType>& input const ListType& input
)
:
CStringList()
{
reset(input);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class StringType>
void Foam::CStringList::reset
(
const UList<StringType>& input
) )
{ {
clear(); clear();
@ -52,36 +40,35 @@ void Foam::CStringList::reset
// Special handling of an empty list // Special handling of an empty list
argv_ = new char*[1]; argv_ = new char*[1];
argv_[0] = nullptr; // Final nullptr terminator argv_[0] = nullptr; // Final nullptr terminator
return; return 0;
} }
// Count overall required string length, including each trailing nul char // Count overall required string length, including each trailing nul char
for (const auto& str : input) for (const auto& str : input)
{ {
len_ += str.size() + 1; len_ += str.length() + 1;
} }
--len_; // No final nul in overall count --len_; // No final nul in overall count
argv_ = new char*[input.size()+1]; // Extra +1 for terminating nullptr argv_ = new char*[input.size()+1]; // Extra +1 for terminating nullptr
data_ = new char[len_+1]; // Extra +1 for terminating nul char data_ = new char[len_+1]; // Extra +1 for terminating nul char
// Copy contents argv_[0] = data_; // Starts here
char* ptr = data_;
for (const auto& str : input) for (const auto& str : input)
{ {
argv_[argc_++] = ptr; // The start of this string char *next = stringCopy(argv_[argc_], str);
argv_[++argc_] = next; // The start of next string
for (auto iter = str.cbegin(); iter != str.cend(); ++iter)
{
*(ptr++) = *iter;
}
*(ptr++) = '\0';
} }
argv_[argc_] = nullptr; // Final nullptr terminator argv_[argc_] = nullptr; // Final nullptr terminator
return argc_;
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class StringType> template<class StringType>
Foam::List<StringType> Foam::List<StringType>
Foam::CStringList::asList(int argc, const char * const argv[]) Foam::CStringList::asList(int argc, const char * const argv[])

View File

@ -28,13 +28,14 @@ License
#include "OSspecific.H" #include "OSspecific.H"
#include "etcFiles.H" #include "etcFiles.H"
#include "StringStream.H" #include "StringStream.H"
#include <cctype>
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// Standard handling of "~/", "./" etc. // Standard handling of "~/", "./" etc.
static void standardExpansions(Foam::string& s) static void standardExpansions(std::string& s)
{ {
if (s.empty()) if (s.empty())
{ {
@ -181,52 +182,53 @@ Foam::string Foam::stringOps::expand
) )
{ {
string s(original); 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<string, word, string::hash>& mapping, const HashTable<string, word, string::hash>& mapping,
const char sigil const char sigil
) )
{ {
string::size_type begVar = 0; std::string::size_type varBeg = 0;
// Expand $VAR or ${VAR} // Expand $VAR or ${VAR}
// Repeat until nothing more is found // Repeat until nothing more is found
while while
( (
(begVar = s.find(sigil, begVar)) != string::npos (varBeg = s.find(sigil, varBeg)) != std::string::npos
&& begVar < s.size()-1 && varBeg < s.size()-1
) )
{ {
if (begVar == 0 || s[begVar-1] != '\\') if (varBeg == 0 || s[varBeg-1] != '\\')
{ {
// Find end of first occurrence // Find end of first occurrence
string::size_type endVar = begVar; std::string::size_type varEnd = varBeg;
string::size_type delim = 0; std::string::size_type delim = 0;
// The type/position of the ":-" or ":+" alternative values // The type/position of the ":-" or ":+" alternative values
int altType = 0; 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; delim = 1;
// check for ${parameter:-word} or ${parameter:+word} // check for ${parameter:-word} or ${parameter:+word}
if (endVar != string::npos) if (varEnd != std::string::npos)
{ {
altPos = begVar; altPos = varBeg;
altType = findParameterAlternative(s, altPos, endVar); altType = findParameterAlternative(s, altPos, varEnd);
} }
} }
else 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 // more generous in accepting keywords than for env variables
while while
@ -242,19 +244,19 @@ Foam::string& Foam::stringOps::inplaceExpand
) )
{ {
++iter; ++iter;
++endVar; ++varEnd;
} }
} }
if (endVar == string::npos) if (varEnd == std::string::npos)
{ {
// likely parsed '${...' without closing '}' - abort // likely parsed '${...' without closing '}' - abort
break; break;
} }
else if (endVar == begVar) else if (varEnd == varBeg)
{ {
// parsed '${}' or $badChar - skip over // parsed '${}' or $badChar - skip over
begVar = endVar + 1; varBeg = varEnd + 1;
} }
else else
{ {
@ -262,23 +264,23 @@ Foam::string& Foam::stringOps::inplaceExpand
( (
s.substr s.substr
( (
begVar + 1 + delim, varBeg + 1 + delim,
( (
(altPos == string::npos ? endVar : altPos) (altPos == std::string::npos ? varEnd : altPos)
- begVar - 2*delim - varBeg - 2*delim
) )
), ),
false false
); );
std::string altValue; std::string altValue;
if (altPos != string::npos) if (altPos != std::string::npos)
{ {
// had ":-" or ":+" alternative value // had ":-" or ":+" alternative value
altValue = s.substr altValue = s.substr
( (
altPos + 2, altPos + 2,
endVar - altPos - 2*delim varEnd - altPos - 2*delim
); );
} }
@ -287,54 +289,52 @@ Foam::string& Foam::stringOps::inplaceExpand
if (fnd.found()) if (fnd.found())
{ {
if (altPos != string::npos && altType == '+') if (altPos != std::string::npos && altType == '+')
{ {
// was found, use ":+" alternative // was found, use ":+" alternative
s.std::string::replace s.std::string::replace
( (
begVar, varBeg,
endVar - begVar + 1, varEnd - varBeg + 1,
altValue altValue
); );
begVar += altValue.size(); varBeg += altValue.size();
} }
else else
{ {
// was found, use value // was found, use value
s.std::string::replace s.std::string::replace
( (
begVar, varBeg,
endVar - begVar + 1, varEnd - varBeg + 1,
*fnd *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 // was not found, use ":-" alternative
s.std::string::replace s.std::string::replace
( (
begVar, varBeg,
endVar - begVar + 1, varEnd - varBeg + 1,
altValue altValue
); );
begVar += altValue.size(); varBeg += altValue.size();
} }
else else
{ {
// substitute with nothing, also for ":+" alternative // substitute with nothing, also for ":+" alternative
s.std::string::erase(begVar, endVar - begVar + 1); s.std::string::erase(varBeg, varEnd - varBeg + 1);
} }
} }
} }
else else
{ {
++begVar; ++varBeg;
} }
} }
return s;
} }
@ -346,7 +346,8 @@ Foam::string Foam::stringOps::expand
) )
{ {
string s(original); 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; string value;
const entry* eptr = dict.lookupScopedEntryPtr const entry* eptr = dict.lookupScopedEntryPtr(name, true, false);
(
name,
true,
false
);
if (eptr) if (eptr)
{ {
@ -387,7 +383,7 @@ Foam::string Foam::stringOps::getVariable
if (value.empty() && !name.empty()) if (value.empty() && !name.empty())
{ {
// The type/position of the ":-" or ":+" alternative values // 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 // check for parameter:-word or parameter:+word
const int altType = const int altType =
@ -438,13 +434,13 @@ Foam::string Foam::stringOps::getVariable
Foam::string Foam::stringOps::expand Foam::string Foam::stringOps::expand
( (
const string& s, const string& s,
string::size_type& index, std::string::size_type& index,
const dictionary& dict, const dictionary& dict,
const bool allowEnvVars, const bool allowEnvVars,
const bool allowEmpty const bool allowEmpty
) )
{ {
string newString; string out;
while (index < s.size()) while (index < s.size())
{ {
@ -453,55 +449,55 @@ Foam::string Foam::stringOps::expand
// Recurse to parse variable name // Recurse to parse variable name
index += 2; index += 2;
string val = expand(s, index, dict, allowEnvVars, allowEmpty); string val = expand(s, index, dict, allowEnvVars, allowEmpty);
newString.append(val); out.append(val);
} }
else if (s[index] == '}') else if (s[index] == '}')
{ {
return getVariable(newString, dict, allowEnvVars, allowEmpty); return getVariable(out, dict, allowEnvVars, allowEmpty);
} }
else else
{ {
newString.append(string(s[index])); out.append(string(s[index]));
} }
++index; ++index;
} }
return newString; return out;
} }
Foam::string& Foam::stringOps::inplaceExpand void Foam::stringOps::inplaceExpand
( (
string& s, std::string& s,
const dictionary& dict, const dictionary& dict,
const bool allowEnvVars, const bool allowEnvVars,
const bool allowEmpty, const bool allowEmpty,
const char sigil const char sigil
) )
{ {
string::size_type begVar = 0; std::string::size_type varBeg = 0;
// Expand $VAR or ${VAR} // Expand $VAR or ${VAR}
// Repeat until nothing more is found // Repeat until nothing more is found
while while
( (
(begVar = s.find(sigil, begVar)) != string::npos (varBeg = s.find(sigil, varBeg)) != std::string::npos
&& begVar < s.size()-1 && 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 // Recursive variable expansion mode
auto stringStart = begVar; auto stringStart = varBeg;
begVar += 2; varBeg += 2;
string varValue string varValue
( (
expand expand
( (
s, s,
begVar, varBeg,
dict, dict,
allowEnvVars, allowEnvVars,
allowEmpty allowEmpty
@ -511,16 +507,16 @@ Foam::string& Foam::stringOps::inplaceExpand
s.std::string::replace s.std::string::replace
( (
stringStart, stringStart,
begVar - stringStart + 1, varBeg - stringStart + 1,
varValue varValue
); );
begVar = stringStart+varValue.size(); varBeg = stringStart+varValue.size();
} }
else else
{ {
string::const_iterator iter = s.cbegin() + begVar + 1; std::string::const_iterator iter = s.cbegin() + varBeg + 1;
string::size_type endVar = begVar; std::string::size_type varEnd = varBeg;
// more generous in accepting keywords than for env variables // more generous in accepting keywords than for env variables
while while
@ -536,15 +532,15 @@ Foam::string& Foam::stringOps::inplaceExpand
) )
{ {
++iter; ++iter;
++endVar; ++varEnd;
} }
const word varName const word varName
( (
s.substr s.substr
( (
begVar + 1, varBeg + 1,
endVar - begVar varEnd - varBeg
), ),
false false
); );
@ -562,57 +558,55 @@ Foam::string& Foam::stringOps::inplaceExpand
s.std::string::replace s.std::string::replace
( (
begVar, varBeg,
varName.size()+1, varName.size()+1,
varValue varValue
); );
begVar += varValue.size(); varBeg += varValue.size();
} }
} }
else else
{ {
++begVar; ++varBeg;
} }
} }
// Standard handling of "~/", "./" etc. // Standard handling of "~/", "./" etc.
standardExpansions(s); standardExpansions(s);
return s;
} }
Foam::string& Foam::stringOps::inplaceExpand void Foam::stringOps::inplaceExpand
( (
string& s, std::string& s,
const dictionary& dict, const dictionary& dict,
const char sigil const char sigil
) )
{ {
string::size_type begVar = 0; std::string::size_type varBeg = 0;
// Expand $VAR or ${VAR} // Expand $VAR or ${VAR}
// Repeat until nothing more is found // Repeat until nothing more is found
while while
( (
(begVar = s.find(sigil, begVar)) != string::npos (varBeg = s.find(sigil, varBeg)) != std::string::npos
&& begVar < s.size()-1 && varBeg < s.size()-1
) )
{ {
if (begVar == 0 || s[begVar-1] != '\\') if (varBeg == 0 || s[varBeg-1] != '\\')
{ {
// Find end of first occurrence // Find end of first occurrence
string::size_type endVar = begVar; std::string::size_type varEnd = varBeg;
string::size_type delim = 0; std::string::size_type delim = 0;
if (s[begVar+1] == '{') if (s[varBeg+1] == '{')
{ {
endVar = s.find('}', begVar); varEnd = s.find('}', varBeg);
delim = 1; delim = 1;
} }
else 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 // more generous in accepting keywords than for env variables
while while
@ -628,19 +622,19 @@ Foam::string& Foam::stringOps::inplaceExpand
) )
{ {
++iter; ++iter;
++endVar; ++varEnd;
} }
} }
if (endVar == string::npos) if (varEnd == std::string::npos)
{ {
// likely parsed '${...' without closing '}' - abort // likely parsed '${...' without closing '}' - abort
break; break;
} }
else if (endVar == begVar) else if (varEnd == varBeg)
{ {
// parsed '${}' or $badChar - skip over // parsed '${}' or $badChar - skip over
begVar = endVar + 1; varBeg = varEnd + 1;
} }
else else
{ {
@ -648,8 +642,8 @@ Foam::string& Foam::stringOps::inplaceExpand
( (
s.substr s.substr
( (
begVar + 1 + delim, varBeg + 1 + delim,
endVar - begVar - 2*delim varEnd - varBeg - 2*delim
), ),
false false
); );
@ -687,26 +681,24 @@ Foam::string& Foam::stringOps::inplaceExpand
s.std::string::replace s.std::string::replace
( (
begVar, varBeg,
endVar - begVar + 1, varEnd - varBeg + 1,
buf.str() buf.str()
); );
begVar += buf.str().size(); varBeg += buf.str().size();
} }
else else
{ {
// not defined - leave original string untouched // not defined - leave original string untouched
begVar = endVar + 1; varBeg = varEnd + 1;
} }
} }
} }
else else
{ {
++begVar; ++varBeg;
} }
} }
return s;
} }
@ -717,51 +709,52 @@ Foam::string Foam::stringOps::expand
) )
{ {
string s(original); 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 const bool allowEmpty
) )
{ {
string::size_type begVar = 0; std::string::size_type varBeg = 0;
// Expand $VARS // Expand $VARS
// Repeat until nothing more is found // Repeat until nothing more is found
while while
( (
(begVar = s.find('$', begVar)) != string::npos (varBeg = s.find('$', varBeg)) != std::string::npos
&& begVar < s.size()-1 && varBeg < s.size()-1
) )
{ {
if (begVar == 0 || s[begVar-1] != '\\') if (varBeg == 0 || s[varBeg-1] != '\\')
{ {
// Find end of first occurrence // Find end of first occurrence
string::size_type endVar = begVar; std::string::size_type varEnd = varBeg;
string::size_type delim = 0; std::string::size_type delim = 0;
// The type/position of the ":-" or ":+" alternative values // The type/position of the ":-" or ":+" alternative values
int altType = 0; 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; delim = 1;
// check for ${parameter:-word} or ${parameter:+word} // check for ${parameter:-word} or ${parameter:+word}
if (endVar != string::npos) if (varEnd != std::string::npos)
{ {
altPos = begVar; altPos = varBeg;
altType = findParameterAlternative(s, altPos, endVar); altType = findParameterAlternative(s, altPos, varEnd);
} }
} }
else else
{ {
string::const_iterator iter = s.cbegin() + begVar + 1; string::const_iterator iter = s.cbegin() + varBeg + 1;
while while
( (
@ -770,20 +763,20 @@ Foam::string& Foam::stringOps::inplaceExpand
) )
{ {
++iter; ++iter;
++endVar; ++varEnd;
} }
} }
if (endVar == string::npos) if (varEnd == std::string::npos)
{ {
// likely parsed '${...' without closing '}' - abort // likely parsed '${...' without closing '}' - abort
break; break;
} }
else if (endVar == begVar) else if (varEnd == varBeg)
{ {
// parsed '${}' or $badChar - skip over // parsed '${}' or $badChar - skip over
begVar = endVar + 1; varBeg = varEnd + 1;
} }
else else
{ {
@ -791,53 +784,53 @@ Foam::string& Foam::stringOps::inplaceExpand
( (
s.substr s.substr
( (
begVar + 1 + delim, varBeg + 1 + delim,
( (
(altPos == string::npos ? endVar : altPos) (altPos == std::string::npos ? varEnd : altPos)
- begVar - 2*delim - varBeg - 2*delim
) )
), ),
false false
); );
std::string altValue; std::string altValue;
if (altPos != string::npos) if (altPos != std::string::npos)
{ {
// had ":-" or ":+" alternative value // had ":-" or ":+" alternative value
altValue = s.substr altValue = s.substr
( (
altPos + 2, altPos + 2,
endVar - altPos - 2*delim varEnd - altPos - 2*delim
); );
} }
const string varValue = getEnv(varName); const string varValue = getEnv(varName);
if (varValue.size()) if (varValue.size())
{ {
if (altPos != string::npos && altType == '+') if (altPos != std::string::npos && altType == '+')
{ {
// was found, use ":+" alternative // was found, use ":+" alternative
s.std::string::replace s.std::string::replace
( (
begVar, varBeg,
endVar - begVar + 1, varEnd - varBeg + 1,
altValue altValue
); );
begVar += altValue.size(); varBeg += altValue.size();
} }
else else
{ {
// was found, use value // was found, use value
s.std::string::replace s.std::string::replace
( (
begVar, varBeg,
endVar - begVar + 1, varEnd - varBeg + 1,
varValue varValue
); );
begVar += varValue.size(); varBeg += varValue.size();
} }
} }
else if (altPos != string::npos) else if (altPos != std::string::npos)
{ {
// use ":-" or ":+" alternative values // use ":-" or ":+" alternative values
if (altType == '-') if (altType == '-')
@ -845,22 +838,22 @@ Foam::string& Foam::stringOps::inplaceExpand
// was not found, use ":-" alternative // was not found, use ":-" alternative
s.std::string::replace s.std::string::replace
( (
begVar, varBeg,
endVar - begVar + 1, varEnd - varBeg + 1,
altValue altValue
); );
begVar += altValue.size(); varBeg += altValue.size();
} }
else else
{ {
// was not found, ":+" alternative implies // was not found, ":+" alternative implies
// substitute with nothing // substitute with nothing
s.std::string::erase(begVar, endVar - begVar + 1); s.std::string::erase(varBeg, varEnd - varBeg + 1);
} }
} }
else if (allowEmpty) else if (allowEmpty)
{ {
s.std::string::erase(begVar, endVar - begVar + 1); s.std::string::erase(varBeg, varEnd - varBeg + 1);
} }
else else
{ {
@ -872,18 +865,16 @@ Foam::string& Foam::stringOps::inplaceExpand
} }
else else
{ {
++begVar; ++varBeg;
} }
} }
// Standard handling of "~/", "./" etc. // Standard handling of "~/", "./" etc.
standardExpansions(s); 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()) if (s.empty() || varName.empty())
{ {
@ -911,7 +902,7 @@ Foam::string Foam::stringOps::trimLeft(const string& s)
{ {
if (!s.empty()) if (!s.empty())
{ {
string::size_type beg = 0; std::string::size_type beg = 0;
while (beg < s.size() && std::isspace(s[beg])) while (beg < s.size() && std::isspace(s[beg]))
{ {
++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()) if (!s.empty())
{ {
string::size_type beg = 0; std::string::size_type beg = 0;
while (beg < s.size() && std::isspace(s[beg])) while (beg < s.size() && std::isspace(s[beg]))
{ {
++beg; ++beg;
@ -942,8 +933,6 @@ Foam::string& Foam::stringOps::inplaceTrimLeft(string& s)
s.erase(0, beg); s.erase(0, beg);
} }
} }
return s;
} }
@ -951,15 +940,15 @@ Foam::string Foam::stringOps::trimRight(const string& s)
{ {
if (!s.empty()) if (!s.empty())
{ {
string::size_type sz = s.size(); auto n = s.size();
while (sz && std::isspace(s[sz-1])) 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()) if (!s.empty())
{ {
string::size_type sz = s.size(); auto n = s.size();
while (sz && std::isspace(s[sz-1])) 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); inplaceTrimRight(s);
inplaceTrimLeft(s); inplaceTrimLeft(s);
}
Foam::string Foam::stringOps::lower(const string& original)
{
string s(original);
inplaceLower(s);
return s; return s;
} }
void Foam::stringOps::inplaceLower(std::string& s)
{
for (auto iter = s.begin(); iter != s.end(); ++iter)
{
*iter = static_cast<std::string::value_type>
(
std::tolower(static_cast<unsigned char>(*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::string::value_type>
(
std::toupper(static_cast<unsigned char>(*iter))
);
}
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -122,9 +122,9 @@ namespace stringOps
// //
// \note the leading sigil can be changed to avoid conflicts with other // \note the leading sigil can be changed to avoid conflicts with other
// string expansions // string expansions
string& inplaceExpand void inplaceExpand
( (
string& s, std::string& s,
const HashTable<string, word, string::hash>& mapping, const HashTable<string, word, string::hash>& mapping,
const char sigil = '$' const char sigil = '$'
); );
@ -168,7 +168,7 @@ namespace stringOps
string expand string expand
( (
const string& s, const string& s,
string::size_type& index, std::string::size_type& index,
const dictionary& dict, const dictionary& dict,
const bool allowEnvVars, const bool allowEnvVars,
const bool allowEmpty const bool allowEmpty
@ -186,9 +186,9 @@ namespace stringOps
// //
// \note the leading sigil can be changed to avoid conflicts with other // \note the leading sigil can be changed to avoid conflicts with other
// string expansions // string expansions
string& inplaceExpand void inplaceExpand
( (
string& s, std::string& s,
const dictionary& dict, const dictionary& dict,
const bool allowEnvVars, const bool allowEnvVars,
const bool allowEmpty, const bool allowEmpty,
@ -205,9 +205,9 @@ namespace stringOps
// //
// \note the leading sigil can be changed to avoid conflicts with other // \note the leading sigil can be changed to avoid conflicts with other
// string expansions // string expansions
string& inplaceExpand void inplaceExpand
( (
string& s, std::string& s,
const dictionary& dict, const dictionary& dict,
const char sigil = '$' const char sigil = '$'
); );
@ -276,9 +276,9 @@ namespace stringOps
// //
// \sa // \sa
// Foam::findEtcFile // Foam::findEtcFile
string& inplaceExpand void inplaceExpand
( (
string& s, std::string& s,
const bool allowEmpty = false const bool allowEmpty = false
); );
@ -286,26 +286,39 @@ namespace stringOps
//- Replace environment variable contents with its name. //- Replace environment variable contents with its name.
// This is essentially the inverse operation for inplaceExpand. // This is essentially the inverse operation for inplaceExpand.
// Return true if a replacement was successful. // 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 //- Return string trimmed of leading whitespace
string trimLeft(const string& s); string trimLeft(const string& s);
//- Trim leading whitespace inplace //- Trim leading whitespace inplace
string& inplaceTrimLeft(string& s); void inplaceTrimLeft(std::string& s);
//- Return string trimmed of trailing whitespace //- Return string trimmed of trailing whitespace
string trimRight(const string& s); string trimRight(const string& s);
//- Trim trailing whitespace inplace //- Trim trailing whitespace inplace
string& inplaceTrimRight(string& s); void inplaceTrimRight(std::string& s);
//- Return string trimmed of leading and trailing whitespace //- Return string trimmed of leading and trailing whitespace
string trim(const string& original); string trim(const string& original);
//- Trim leading and trailing whitespace inplace //- 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. //- Using printf-formatter for a word representation of the primitive.