Commit 5f93f206 authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: add stringOps::inplaceRemoveSpace()

Style changes:
  - use std algorithm for some stringOps internals
  - pass SubStrings iterators by const reference

ENH: special nullptr handling for ISstream getLine
  - pass through to istream::ignore to support read and discard
parent 6b3b6bb9
Test-IFstream.C
EXE = $(FOAM_USER_APPBIN)/Test-IFstream
/* EXE_INC = */
/* EXE_LIBS = */
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
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/>.
Application
Test-IFstream
Description
Tests on low-level reading
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Fstream.H"
#include "etcFiles.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noBanner();
argList::noParallel();
#include "setRootCase.H"
// Test with etc/controlDict (mandatory, from distribution)
{
const fileName inputFile
(
findEtcFile("controlDict", true, 0007)
);
Info<< nl << "Test getLine" << nl << inputFile << nl;
IFstream is(inputFile);
string buf;
// Test that buffer resizing works as expected
Info<< "buf: " << buf.size() << '/' << buf.capacity() << nl;
bool skipDoc = true;
while (is.good())
{
if (skipDoc || is.lineNumber() % 2)
{
is.getLine(buf);
Info<< is.lineNumber() << ": "
<< buf.size() << '/' << buf.capacity() << ' '
<< buf << nl;
if (buf.starts_with("Documentation"))
{
skipDoc = false;
Info<< "Found Documentation: skip until closing '}'"
<< " line number will now be incorrect"
<< nl;
auto n = is.getLine(nullptr, '}');
Info<< is.lineNumber() << ": [" << label(n) << "]" << nl;
}
}
else
{
auto n = is.getLine(nullptr);
Info<< is.lineNumber() << ": [" << label(n) << "]" << nl;
}
}
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //
......@@ -41,6 +41,7 @@ SourceFiles
#include "Istream.H"
#include "fileName.H"
#include <limits>
#include <iostream>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -148,9 +149,13 @@ public:
// end of file is read.
inline int peek();
//- Raw, low-level getline into a string function.
//- Raw, low-level getline (until delimiter) into a string.
inline ISstream& getLine(std::string& str, char delim = '\n');
//- Low-level discard until delimiter
// \return the number of characters extracted
inline std::streamsize getLine(std::nullptr_t, char delim = '\n');
//- Raw, low-level putback character function.
inline ISstream& putback(const char c);
......
......@@ -87,6 +87,22 @@ inline Foam::ISstream& Foam::ISstream::getLine(std::string& str, char delim)
}
inline std::streamsize Foam::ISstream::getLine(std::nullptr_t, char delim)
{
is_.ignore(std::numeric_limits<std::streamsize>::max(), delim);
setState(is_.rdstate());
std::streamsize count = is_.gcount();
if (count && delim == '\n')
{
++lineNumber_;
}
return count;
}
inline Foam::ISstream& Foam::ISstream::putback(const char c)
{
if (c == '\n')
......
......@@ -134,12 +134,12 @@ void Foam::csvTableReader<Type>::operator()
const label maxEntry =
max(refColumn_, componentColumns_[findMax(componentColumns_)]);
string line;
label lineNo = 0;
// Skip header
if (headerLine_)
{
string line;
is.getLine(line);
++lineNo;
}
......@@ -149,7 +149,6 @@ void Foam::csvTableReader<Type>::operator()
while (is.good())
{
string line;
is.getLine(line);
++lineNo;
......
......@@ -118,12 +118,12 @@ void Foam::Function1Types::CSV<Type>::read()
const label maxEntry =
max(refColumn_, componentColumns_[findMax(componentColumns_)]);
string line;
label lineNo = 0;
// Skip header
for (label i = 0; i < nHeaderLine_; ++i)
{
string line;
is.getLine(line);
++lineNo;
}
......@@ -133,7 +133,6 @@ void Foam::Function1Types::CSV<Type>::read()
while (is.good())
{
string line;
is.getLine(line);
++lineNo;
......
......@@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -35,8 +35,8 @@ Description
#ifndef SubStrings_H
#define SubStrings_H
#include <string>
#include <regex>
#include <string>
#include <vector>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -67,13 +67,13 @@ public:
// Constructors
//- Construct null
//- Default construct
SubStrings() = default;
// Member Functions
//- The total length of all sub-elements.
//- The total string length of all sub-elements.
// Use size() for the number elements.
std::string::size_type length() const
{
......@@ -89,7 +89,11 @@ public:
//- Append sub-string defined by begin/end iterators
void append(string_iterator b, string_iterator e)
void append
(
const typename String::const_iterator& b,
const typename String::const_iterator& e
)
{
value_type range;
range.first = b;
......@@ -101,7 +105,7 @@ public:
//- Const reference to the first element,
// for consistency with other OpenFOAM containers
//- for consistency with other OpenFOAM containers
auto first() const -> decltype(this->front())
{
return this->front();
......@@ -109,7 +113,7 @@ public:
//- Const reference to the last element,
// for consistency with other OpenFOAM containers
//- for consistency with other OpenFOAM containers
auto last() const -> decltype(this->back())
{
return this->back();
......@@ -121,9 +125,9 @@ public:
{
return (*this)[pos].str();
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -190,7 +190,7 @@ bool Foam::string::removeRepeated(const char character)
}
}
resize(nChar);
erase(nChar);
}
return changed;
......@@ -219,7 +219,7 @@ bool Foam::string::removeEnd(const std::string& text)
if (txtLen && strLen >= txtLen && !compare(strLen - txtLen, npos, text))
{
resize(strLen - txtLen);
erase(strLen - txtLen);
return true;
}
......@@ -244,7 +244,7 @@ bool Foam::string::removeEnd(const char c)
const auto n = length();
if (n > 1 && back() == c)
{
resize(n-1);
erase(n-1);
return true;
}
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2019 OpenCFD Ltd.
Copyright (C) 2017-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -29,10 +29,11 @@ License
#include "stringOps.H"
#include "typeInfo.H"
#include "etcFiles.H"
#include "Pstream.H"
#include "UPstream.H"
#include "StringStream.H"
#include "OSstream.H"
#include "OSspecific.H"
#include <algorithm>
#include <cctype>
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
......@@ -162,7 +163,7 @@ static void expandLeadingTilde(std::string& s)
// Single warning (on master) with guard to avoid Pstream::master()
// when Pstream has not yet been initialized
if (Pstream::parRun() ? Pstream::master() : true)
if (UPstream::parRun() ? UPstream::master() : true)
{
std::cerr
<< nl
......@@ -696,55 +697,35 @@ static void expandString
std::string::size_type Foam::stringOps::count
(
const std::string& str,
const std::string& s,
const char c
)
{
std::string::size_type n = 0;
for (auto iter = str.cbegin(); iter != str.cend(); ++iter)
{
if (*iter == c)
{
++n;
}
}
return n;
return std::count(s.cbegin(), s.cend(), c);
}
std::string::size_type Foam::stringOps::count(const char* str, const char c)
std::string::size_type Foam::stringOps::count(const char* s, const char c)
{
if (!str)
{
return 0;
}
std::string::size_type n = 0;
for (const char *iter = str; *iter; ++iter)
{
if (*iter == c)
{
++n;
}
}
return n;
return
(
s == nullptr
? 0
: std::count(s, (s + std::char_traits<char>::length(s)), c)
);
}
Foam::string Foam::stringOps::expand
(
const std::string& str,
const std::string& s,
const HashTable<string, word, string::hash>& mapping,
const char sigil
)
{
string s(str);
inplaceExpand(s, mapping);
return s;
string out(s);
inplaceExpand(out, mapping);
return out;
}
......@@ -862,14 +843,14 @@ void Foam::stringOps::inplaceExpand
Foam::string Foam::stringOps::expand
(
const std::string& str,
const std::string& s,
const dictionary& dict,
const char sigil
)
{
string s(str);
inplaceExpand(s, dict, sigil);
return s;
string out(s);
inplaceExpand(out, dict, sigil);
return out;
}
......@@ -902,13 +883,13 @@ void Foam::stringOps::inplaceExpand
Foam::string Foam::stringOps::expand
(
const std::string& str,
const std::string& s,
const bool allowEmpty
)
{
string s(str);
inplaceExpand(s, allowEmpty);
return s;
string out(s);
inplaceExpand(out, allowEmpty);
return out;
}
......@@ -1064,24 +1045,24 @@ Foam::stringOps::findTrim
}
Foam::string Foam::stringOps::trim(const std::string& str)
Foam::string Foam::stringOps::trim(const std::string& s)
{
std::string::size_type pos = 0;
std::string::size_type end = str.length();
std::string::size_type end = s.length();
// Right
while (pos < end && std::isspace(str[end-1]))
while (pos < end && std::isspace(s[end-1]))
{
--end;
}
// Left
while (pos < end && std::isspace(str[pos]))
while (pos < end && std::isspace(s[pos]))
{
++pos;
}
return str.substr(pos, end-pos);
return s.substr(pos, end-pos);
}
......@@ -1092,11 +1073,17 @@ void Foam::stringOps::inplaceTrim(std::string& s)
}
Foam::string Foam::stringOps::removeComments(const std::string& str)
void Foam::stringOps::inplaceRemoveSpace(std::string& s)
{
string s(str);
inplaceRemoveComments(s);
return s;
s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
}
Foam::string Foam::stringOps::removeComments(const std::string& s)
{
string out(s);
inplaceRemoveComments(out);
return out;
}
......@@ -1196,43 +1183,35 @@ void Foam::stringOps::inplaceRemoveComments(std::string& s)
}
Foam::string Foam::stringOps::lower(const std::string& str)
Foam::string Foam::stringOps::lower(const std::string& s)
{
string s(str);
inplaceLower(s);
return s;
string out;
out.resize(s.length());
std::transform(s.begin(), s.end(), out.begin(), ::tolower);
return out;
}
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))
);
}
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}
Foam::string Foam::stringOps::upper(const std::string& str)
Foam::string Foam::stringOps::upper(const std::string& s)
{
string s(str);
inplaceUpper(s);
return s;
string out;
out.resize(s.length());
std::transform(s.begin(), s.end(), out.begin(), ::toupper);
return out;
}
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))
);
}
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
}
......
......@@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2012 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -55,7 +55,7 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class OSstream;
/*---------------------------------------------------------------------------*\
......@@ -65,11 +65,11 @@ class OSstream;
namespace stringOps
{
//- Count the number of occurrences of the specified character
std::string::size_type count(const std::string& str, const char c);
std::string::size_type count(const std::string& s, const char c);
//- Count the number of occurrences of the specified character
// Correctly handles nullptr.
std::string::size_type count(const char* str, const char c);
std::string::size_type count(const char* s, const char c);
//- Return true if text matches one of the regular expressions.
inline bool match(const UList<wordRe>& patterns, const std::string& text)
......@@ -83,7 +83,7 @@ namespace stringOps
// \sa stringOps::inplaceExpand() for details
string expand
(
const std::string& str,
const std::string& s,
const HashTable<string, word, string::hash>& mapping,
const char sigil = '$'
);
......@@ -213,7 +213,7 @@ namespace stringOps
// \sa stringOps::inplaceExpand(std::string&, const dictionary&, char)
string expand
(
const std::string& str,
const std::string& s,