Commit 7c1190f0 authored by Mark Olesen's avatar Mark Olesen Committed by Andrew Heather
Browse files

ENH: rationalize some string methods.

- silently deprecate 'startsWith', 'endsWith' methods
  (added in 2016: 2b143606), in favour of
  'starts_with', 'ends_with' methods, corresponding to C++20 and
  allowing us to cull then in a few years.

- handle single character versions of starts_with, ends_with.

- add single character version of removeEnd and silently deprecate
  removeTrailing which did the same thing.

- drop the const versions of removeRepeated, removeTrailing.
  Unused and with potential confusion.

STYLE: use shrink_to_fit(), erase()
parent ea214727
......@@ -83,7 +83,7 @@ int main(int argc, char *argv[])
const word& item
: DirLister::files(".").where
(
[](const word& val){ return val.startsWith("T"); }
[](const word& val){ return val.starts_with('T'); }
)
)
{
......@@ -135,7 +135,7 @@ int main(int argc, char *argv[])
<< "~~~~~~~~~~" << nl
<< DirLister(".").list<fileName>
(
[](const word& val){ return val.startsWith("D"); },
[](const word& val){ return val.starts_with('D'); },
false
)
<< nl;
......
......@@ -353,7 +353,7 @@ int main(int argc, char *argv[])
<< word::printf("formatted '%08d'", val) << "\n";
}
// test startsWith, endsWith methods
// test starts_with, ends_with methods
{
string empty; //;
string input1 = "shorter input";
......@@ -362,64 +362,64 @@ int main(int argc, char *argv[])
stringList checks{"match", "long", "", "short", "text", "s", "l", "t"};
Info<< nl;
Info<< "check startsWith:" << nl
Info<< "check starts_with:" << nl
<< "~~~~~~~~~~~~~~~~~" << nl;
Info<<"input: " << empty << nl;
for (const string& test : checks)
{
Info<< " startsWith(" << test << ") = "
<< Switch(empty.startsWith(test)) << nl;
Info<< " starts_with(" << test << ") = "
<< Switch(empty.starts_with(test)) << nl;
}
Info<<"input: " << input1 << nl;
for (const string& test : checks)
{
Info<< " startsWith(" << test << ") = "
<< Switch(input1.startsWith(test)) << nl;
Info<< " starts_with(" << test << ") = "
<< Switch(input1.starts_with(test)) << nl;
}
Info<<"input: " << input2 << nl;
for (const string& test : checks)
{
Info<< " startsWith(" << test << ") = "
<< Switch(input2.startsWith(test)) << nl;
Info<< " starts_with(" << test << ") = "
<< Switch(input2.starts_with(test)) << nl;
}
Info<< nl;
Info<< "check endsWith:" << nl
Info<< "check ends_with:" << nl
<< "~~~~~~~~~~~~~~~~~" << nl;
Info<<"input: " << empty << nl;
for (const string& test : checks)
{
Info<< " endsWith(" << test << ") = "
<< Switch(empty.endsWith(test)) << nl;
Info<< " ends_with(" << test << ") = "
<< Switch(empty.ends_with(test)) << nl;
}
Info<<"input: " << input1 << nl;
for (const string& test : checks)
{
Info<< " endsWith(" << test << ") = "
<< Switch(input1.endsWith(test)) << nl;
Info<< " ends_with(" << test << ") = "
<< Switch(input1.ends_with(test)) << nl;
}
Info<<"input: " << input2 << nl;
for (const string& test : checks)
{
Info<< " endsWith(" << test << ") = "
<< Switch(input2.endsWith(test)) << nl;
Info<< " ends_with(" << test << ") = "
<< Switch(input2.ends_with(test)) << nl;
}
Info<< nl;
Info<< "check endsWith as applied to field names:" << nl
Info<< "check ends_with as applied to field names:" << nl
<< "~~~~~~~~~~~~~~~~~" << nl;
string input3 = "field_0";
string input4 = "_0";
Info<<input3 << " endsWith(\"_0\") = "
<< Switch(input3.endsWith("_0")) << nl;
Info<<input3 << " ends_with(\"_0\") = "
<< Switch(input3.ends_with("_0")) << nl;
Info<<input4 << " endsWith(\"_0\") = "
<< Switch(input4.endsWith("_0")) << nl;
Info<<input4 << " ends_with(\"_0\") = "
<< Switch(input4.ends_with("_0")) << nl;
}
......
......@@ -175,7 +175,7 @@ int main(int argc, char *argv[])
{
nodeStream.getLine(line);
}
while (line.size() && line[0] == '#');
while (line.starts_with('#'));
IStringStream nodeLine(line);
......@@ -252,7 +252,7 @@ int main(int argc, char *argv[])
{
eleStream.getLine(line);
}
while (line.size() && line[0] == '#');
while (line.starts_with('#'));
IStringStream eleLine(line);
......@@ -368,7 +368,7 @@ int main(int argc, char *argv[])
{
faceStream.getLine(line);
}
while (line.size() && line[0] == '#');
while (line.starts_with('#'));
IStringStream faceLine(line);
......
......@@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -51,7 +52,7 @@ string getLine(std::ifstream& is)
{
std::getline(is, line);
}
while (line.size() && line[0] == '#');
while (line.starts_with('#'));
return line;
}
......
......@@ -40,7 +40,7 @@ Foam::autoPtr<Foam::helpType> Foam::helpType::New
{
// special treatment for -help
// exit without stack trace
if (helpTypeName.startsWith("-help"))
if (helpTypeName.starts_with("-help"))
{
FatalErrorInFunction
<< "Valid helpType selections:" << nl
......
......@@ -678,7 +678,7 @@ void Foam::vtkPVFoam::Update
// Suppress caching of Lagrangian since it normally always changes.
cachedVtp_.filterKeys
(
[](const word& k){ return k.startsWith("lagrangian/"); },
[](const word& k){ return k.starts_with("lagrangian/"); },
true // prune
);
}
......
......@@ -179,7 +179,7 @@ void Foam::vtkPVFoam::convertMeshPatches()
}
}
if (longName.startsWith("group/"))
if (longName.starts_with("group/"))
{
// Patch group. Collect patch faces.
......
......@@ -1221,7 +1221,7 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
(
!handle
&& libName.find('/') == std::string::npos
&& !libso.startsWith("lib")
&& !libso.starts_with("lib")
)
{
// Try with 'lib' prefix
......
......@@ -1674,7 +1674,7 @@ void* Foam::dlOpen(const fileName& libName, const bool check)
if
(
libName.find('/') == std::string::npos
&& !libName.startsWith("lib")
&& !libName.starts_with("lib")
)
{
// Try with 'lib' prefix
......
......@@ -97,17 +97,6 @@ namespace Foam
}
// file-scope
//
// A file is 'outside' of the case if it has been specified using an
// absolute path (starts with '/')
//
static inline bool isOutsideOfCase(const std::string& file)
{
return !file.empty() && file[0] == '/';
}
// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
bool Foam::IOobject::fileNameComponents
......@@ -119,7 +108,7 @@ bool Foam::IOobject::fileNameComponents
)
{
// Convert explicit relative file-system path to absolute file-system path.
if (path.startsWith("./") || path.startsWith("../"))
if (path.starts_with("./") || path.starts_with("../"))
{
fileName absPath = cwd()/path;
absPath.clean();
......@@ -461,7 +450,10 @@ const Foam::fileName& Foam::IOobject::caseName() const
Foam::fileName Foam::IOobject::path() const
{
if (isOutsideOfCase(instance()))
// A file is 'outside' of the case if it has been specified using an
// absolute path (starts with '/')
if (instance().starts_with('/'))
{
return instance();
}
......
......@@ -382,7 +382,7 @@ Foam::label Foam::IOobjectList::prune_0()
return
HashPtrTable<IOobject>::filterKeys
(
[](const word& k){ return k.endsWith("_0"); },
[](const word& k){ return k.ends_with("_0"); },
true // prune
);
}
......
......@@ -924,7 +924,7 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::storeOldTimes() const
(
field0Ptr_
&& timeIndex_ != this->time().timeIndex()
&& !this->name().endsWith("_0")
&& !this->name().ends_with("_0")
)
{
storeOldTime();
......
......@@ -1164,7 +1164,7 @@ void Foam::argList::parse
}
// Case-relative if not absolute and not "./" etc
if (!source.isAbsolute() && !source.startsWith("."))
if (!source.isAbsolute() && !source.starts_with('.'))
{
source = rootPath_/globalCase_/source;
adjustOpt = true;
......@@ -1632,8 +1632,8 @@ void Foam::argList::displayDoc(bool source) const
for (const fileName& dir : docDirs)
{
// http protocols are last in the list
if (dir.startsWith("http:") || dir.startsWith("https:"))
// The http protocols are last in the list
if (dir.starts_with("http:") || dir.starts_with("https:"))
{
url = dir/executable_ + docExt;
break;
......@@ -1643,7 +1643,7 @@ void Foam::argList::displayDoc(bool source) const
if
(
docFile.startsWith("file://")
docFile.starts_with("file://")
? isFile(docFile.substr(7)) // check part after "file://"
: isFile(docFile)
)
......
......@@ -77,11 +77,11 @@ void Foam::solution::read(const dictionary& dict)
{
scalar value = relaxDict.get<scalar>(e);
if (e.startsWith("p"))
if (e.starts_with('p'))
{
fieldRelaxDict_.add(e, value);
}
else if (e.startsWith("rho"))
else if (e.starts_with("rho"))
{
fieldRelaxDict_.add(e, value);
}
......
......@@ -191,36 +191,31 @@ bool Foam::fileName::equals(const std::string& s1, const std::string& s2)
}
bool Foam::fileName::isBackup(const std::string& str)
bool Foam::fileName::isBackup(const std::string& s)
{
if (str.empty())
if (s.empty())
{
return false;
}
else if (str.back() == '~')
else if (s.back() == '~')
{
return true;
}
// Now check the extension
const auto dot = find_ext(str);
auto dot = find_ext(s);
if (dot == npos)
{
return false;
}
const std::string ending = str.substr(dot+1);
if (ending.empty())
{
return false;
}
++dot;
return
(
ending == "bak" || ending == "BAK"
|| ending == "old" || ending == "save"
!s.compare(dot, npos, "bak") || !s.compare(dot, npos, "BAK")
|| !s.compare(dot, npos, "old") || !s.compare(dot, npos, "save")
);
}
......@@ -448,7 +443,7 @@ Foam::fileName Foam::fileName::relative
if
(
top && (f.size() > (top+1)) && f[top] == '/'
&& f.startsWith(parent)
&& f.starts_with(parent)
)
{
if (caseTag)
......
......@@ -128,7 +128,7 @@ inline void Foam::fileName::stripInvalid()
}
removeRepeated('/');
removeTrailing('/');
removeEnd('/');
}
}
......@@ -137,7 +137,7 @@ inline bool Foam::fileName::isAbsolute(const std::string& str)
{
return
(
(!str.empty() && str[0] == '/')
(!str.empty() && str.front() == '/') // ie, str.starts_with('/')
#ifdef _WIN32
||
(
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2017 OpenCFD Ltd.
Copyright (C) 2016-2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -34,7 +34,9 @@ License
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
const char* const Foam::string::typeName = "string";
int Foam::string::debug(Foam::debug::debugSwitch(string::typeName, 0));
int Foam::string::debug(Foam::debug::debugSwitch(Foam::string::typeName, 0));
const Foam::string Foam::string::null;
......@@ -117,16 +119,14 @@ Foam::string::size_type Foam::string::count(const char c) const
Foam::string& Foam::string::replace
(
const string& oldStr,
const string& newStr,
const size_type start
const std::string& s1,
const std::string& s2,
size_type pos
)
{
size_type pos = start;
if ((pos = find(oldStr, pos)) != npos)
if ((pos = find(s1, pos)) != npos)
{
std::string::replace(pos, oldStr.size(), newStr);
std::string::replace(pos, s1.size(), s2);
}
return *this;
......@@ -135,24 +135,20 @@ Foam::string& Foam::string::replace
Foam::string& Foam::string::replaceAll
(
const string& oldStr,
const string& newStr,
const size_type start
const std::string& s1,
const std::string& s2,
size_type pos
)
{
const size_type lenOld = oldStr.size();
const size_type lenNew = newStr.size();
const auto n1 = s1.length();
const auto n2 = s2.length();
if (lenOld)
if (n1)
{
for
(
size_type pos = start;
(pos = find(oldStr, pos)) != npos;
pos += lenNew
)
while ((pos = find(s1, pos)) != npos)
{
std::string::replace(pos, lenOld, newStr);
std::string::replace(pos, n1, s2);
pos += n2;
}
}
......@@ -201,20 +197,14 @@ bool Foam::string::removeRepeated(const char character)
}
Foam::string Foam::string::removeRepeated(const char character) const
bool Foam::string::removeStart(const std::string& text)
{
string str(*this);
str.removeRepeated(character);
return str;
}
const auto txtLen = text.length();
const auto strLen = length();
bool Foam::string::removeTrailing(const char character)
{
const string::size_type nChar = size();
if (character && nChar > 1 && operator[](nChar-1) == character)
if (txtLen && strLen >= txtLen && !compare(0, txtLen, text))
{
resize(nChar-1);
erase(0, txtLen);
return true;
}
......@@ -222,26 +212,14 @@ bool Foam::string::removeTrailing(const char character)
}
Foam::string Foam::string::removeTrailing(const char character) const
{
string str(*this);
str.removeTrailing(character);
return str;
}
bool Foam::string::removeStart(const std::string& text)
bool Foam::string::removeEnd(const std::string& text)
{
const size_type txtLen = text.size();
if (!txtLen)
{
return true;
}
const auto txtLen = text.length();
const auto strLen = length();
const size_type strLen = this->size();
if (strLen >= txtLen && !compare(0, txtLen, text))
if (txtLen && strLen >= txtLen && !compare(strLen - txtLen, npos, text))
{
this->erase(0, txtLen);
resize(strLen - txtLen);
return true;
}
......@@ -249,18 +227,11 @@ bool Foam::string::removeStart(const std::string& text)
}
bool Foam::string::removeEnd(const std::string& text)
bool Foam::string::removeStart(const char c)
{
const size_type txtLen = text.size();
if (!txtLen)
{
return true;
}
const size_type strLen = this->size();
if (strLen >= txtLen && !compare(strLen - txtLen, npos, text))
if (length() > 1 && front() == c)
{
this->resize(strLen - txtLen);
erase(0, 1);
return true;
}
......@@ -268,29 +239,16 @@ bool Foam::string::removeEnd(const std::string& text)
}
bool Foam::string::startsWith(const std::string& text) const
{
const size_type strLen = this->size();
const size_type txtLen = text.size();
return
(
!txtLen
|| (strLen >= txtLen && !compare(0, txtLen, text))
);
}
bool Foam::string::endsWith(const std::string& text) const
bool Foam::string::removeEnd(const char c)
{
const size_type strLen = this->size();
const size_type txtLen = text.size();
const auto n = length();
if (n > 1 && back() == c)
{
resize(n-1);
return true;
}
return
(
!txtLen
|| (strLen >= txtLen && !compare(strLen - txtLen, npos, text))
);
return false;
}
......
......@@ -40,6 +40,7 @@ See also
configuration directory
SourceFiles
stringI.H
string.C
stringIO.C
stringTemplates.C
......@@ -51,7 +52,6 @@ SourceFiles
#include "char.H"
#include "Hasher.H"