ENH: add offset support to stringOps::split functions
- for example, string buffer = ...; SubStrings<string> split; { auto colon = buffer.find(':'); if (colon != std::string::npos) { split = stringOps::splitSpace(buffer, colon+1); } } Not really possible with a substr() since that would create a new temporary which then disappears. Similarly awkward to split and then scan for the ':' to decide how many to discard. ENH: add pop_front() and pop_back() methods to SubStrings - the content is trivial enough (a pair of iterators) and the total number of elements is usually reasonable short so that removal of elements is inexpensive For example, string buffer = ...; auto split = stringOps::splitSpace(buffer); if (!split.empty() && split[0].str() == "face") { split.pop_front(); }
This commit is contained in:
parent
3fed41547f
commit
883196981d
@ -123,7 +123,7 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
|
||||
Info<< testInput << nl;
|
||||
SubStrings<string> args = stringOps::splitSpace(testInput);
|
||||
auto args = stringOps::splitSpace(testInput);
|
||||
Info<< "split into " << args.size() << " args" << nl;
|
||||
|
||||
CStringList inC(args);
|
||||
|
@ -47,7 +47,7 @@ using namespace Foam;
|
||||
template<class PrimitiveType>
|
||||
static List<PrimitiveType> splitStringToList(const std::string& str)
|
||||
{
|
||||
const SubStrings<std::string> items = stringOps::splitAny(str, " ,;");
|
||||
const auto items = stringOps::splitAny(str, " ,;");
|
||||
|
||||
DynamicList<PrimitiveType> values(items.size());
|
||||
|
||||
|
@ -148,7 +148,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
Info<< "input: " << input << nl
|
||||
<< "expand: " << output << nl
|
||||
<< "split: " << stringOps::split(output, "/") << nl << nl;
|
||||
<< "split: " << stringOps::split(output, '/') << nl << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -34,6 +34,7 @@ Description
|
||||
#include "argList.H"
|
||||
#include "fileName.H"
|
||||
#include "stringOps.H"
|
||||
#include "Switch.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
@ -65,6 +66,9 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noBanner();
|
||||
argList::noParallel();
|
||||
argList::noMandatoryArgs();
|
||||
argList::addArgument("string .. stringN");
|
||||
|
||||
argList::addOption
|
||||
(
|
||||
"any",
|
||||
@ -89,6 +93,12 @@ int main(int argc, char *argv[])
|
||||
"int",
|
||||
"test split on fixed width"
|
||||
);
|
||||
argList::addOption
|
||||
(
|
||||
"begin",
|
||||
"int",
|
||||
"begin offset for splits"
|
||||
);
|
||||
argList::addBoolOption
|
||||
(
|
||||
"slash",
|
||||
@ -104,18 +114,25 @@ int main(int argc, char *argv[])
|
||||
"empty",
|
||||
"preserve empty strings in split"
|
||||
);
|
||||
argList args(argc, argv, false, true);
|
||||
|
||||
argList args(argc, argv);
|
||||
|
||||
if (args.size() <= 1 && args.options().empty())
|
||||
{
|
||||
args.printUsage();
|
||||
}
|
||||
|
||||
const label beginOffset = args.getOrDefault<label>("begin", 0);
|
||||
|
||||
const bool keepEmpty = args.found("empty");
|
||||
|
||||
Info<< "begin offset: " << beginOffset << nl;
|
||||
Info<< "keep empty : " << Switch::name(keepEmpty) << nl;
|
||||
|
||||
const label nopts =
|
||||
args.count({"any", "slash", "space", "sub", "fixed", "char"});
|
||||
|
||||
|
||||
if (args.found("any"))
|
||||
{
|
||||
const std::string& str = args["any"];
|
||||
@ -125,7 +142,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (label argi=1; argi < args.size(); ++argi)
|
||||
{
|
||||
const auto split = stringOps::splitAny(args[argi], str);
|
||||
auto split = stringOps::splitAny(args[argi], str, beginOffset);
|
||||
printSubStrings(args[argi], split);
|
||||
}
|
||||
|
||||
@ -144,7 +161,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (label argi=1; argi < args.size(); ++argi)
|
||||
{
|
||||
const auto split = stringOps::split(args[argi], str);
|
||||
auto split = stringOps::split(args[argi], str, beginOffset);
|
||||
printSubStrings(args[argi], split);
|
||||
}
|
||||
|
||||
@ -161,7 +178,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (label argi=1; argi < args.size(); ++argi)
|
||||
{
|
||||
const auto split = stringOps::splitSpace(args[argi]);
|
||||
auto split = stringOps::splitSpace(args[argi], beginOffset);
|
||||
printSubStrings(args[argi], split);
|
||||
|
||||
Info<< "pop_front(2)" << nl;
|
||||
split.pop_front(2);
|
||||
printSubStrings(args[argi], split);
|
||||
}
|
||||
|
||||
@ -180,7 +201,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (label argi=1; argi < args.size(); ++argi)
|
||||
{
|
||||
const auto split = stringOps::split(args[argi], delim, keepEmpty);
|
||||
auto split =
|
||||
stringOps::split(args[argi], delim, beginOffset, keepEmpty);
|
||||
printSubStrings(args[argi], split);
|
||||
}
|
||||
|
||||
@ -199,7 +221,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (label argi=1; argi < args.size(); ++argi)
|
||||
{
|
||||
const auto split = stringOps::splitFixed(args[argi], width);
|
||||
auto split = stringOps::splitFixed(args[argi], width, beginOffset);
|
||||
printSubStrings(args[argi], split);
|
||||
}
|
||||
|
||||
@ -219,7 +241,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (label argi=1; argi < args.size(); ++argi)
|
||||
{
|
||||
const auto split = stringOps::split(args[argi], delim, keepEmpty);
|
||||
auto split =
|
||||
stringOps::split(args[argi], delim, beginOffset, keepEmpty);
|
||||
printSubStrings(args[argi], split);
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ namespace Foam
|
||||
template<class PrimitiveType>
|
||||
static List<PrimitiveType> splitStringToList(const std::string& str)
|
||||
{
|
||||
const SubStrings<std::string> items = stringOps::splitAny(str, " ,;");
|
||||
const auto items = stringOps::splitAny(str, " ,;");
|
||||
|
||||
DynamicList<PrimitiveType> values(items.size());
|
||||
|
||||
|
@ -36,7 +36,7 @@ Foam::scalarRanges Foam::scalarRanges::parse
|
||||
bool report
|
||||
)
|
||||
{
|
||||
const SubStrings<std::string> items = stringOps::splitAny(str, " ,;");
|
||||
const auto items = stringOps::splitAny(str, " ,;");
|
||||
|
||||
scalarRanges ranges(items.size());
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -66,12 +66,6 @@ public:
|
||||
typename StringType::const_iterator;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
SubStrings() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- The total string length of all sub-elements.
|
||||
@ -109,6 +103,40 @@ public:
|
||||
this->push_back(range);
|
||||
}
|
||||
|
||||
|
||||
//- Reduce size by 1 or more elements. Can be called on an empty list.
|
||||
void pop_back(size_t n = 1)
|
||||
{
|
||||
if (n >= this->size())
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
else if (n > 0)
|
||||
{
|
||||
this->resize(this->size() - n);
|
||||
}
|
||||
}
|
||||
|
||||
//- Reduce size by 1 or more elements (from the front).
|
||||
//- Can be called on an empty list.
|
||||
void pop_front(size_t n = 1)
|
||||
{
|
||||
if (n >= this->size())
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
else if (n > 0)
|
||||
{
|
||||
// Overlapping range, avoid std::copy, std::move
|
||||
for (size_t src = n, dst = 0; src < this->size(); ++src, ++dst)
|
||||
{
|
||||
(*this)[dst] = (*this)[src];
|
||||
}
|
||||
this->resize(this->size() - n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FUTURE?
|
||||
// #if __cplusplus >= 201703L
|
||||
// std::string_view view(size_t pos) const
|
||||
|
@ -372,8 +372,13 @@ namespace stringOps
|
||||
template<class StringType>
|
||||
Foam::SubStrings<StringType> split
|
||||
(
|
||||
//! The string to split
|
||||
const StringType& str,
|
||||
//! The delimiter for splitting. Ill-defined if NUL character
|
||||
const char delim,
|
||||
//! Offset within string to start splitting
|
||||
std::string::size_type pos = 0,
|
||||
//! Retain empty fields
|
||||
const bool keepEmpty = false
|
||||
);
|
||||
|
||||
@ -382,8 +387,13 @@ namespace stringOps
|
||||
template<class StringType>
|
||||
Foam::SubStrings<StringType> split
|
||||
(
|
||||
//! The string to split
|
||||
const StringType& str,
|
||||
//! The delimiters for splitting. Ill-defined if empty
|
||||
const std::string& delim,
|
||||
//! Offset within string to start splitting
|
||||
std::string::size_type pos = 0,
|
||||
//! Retain empty fields
|
||||
const bool keepEmpty = false
|
||||
);
|
||||
|
||||
@ -393,22 +403,25 @@ namespace stringOps
|
||||
template<class StringType>
|
||||
Foam::SubStrings<StringType> splitAny
|
||||
(
|
||||
//! The string to split
|
||||
const StringType& str,
|
||||
const std::string& delim
|
||||
//! The delimiters for splitting. Ill-defined if empty!
|
||||
const std::string& delim,
|
||||
//! Offset within string to start splitting
|
||||
std::string::size_type pos = 0
|
||||
);
|
||||
|
||||
//- Split string into sub-strings using a fixed field width.
|
||||
// Behaviour is ill-defined if width is zero.
|
||||
// \param str the string to be split
|
||||
// \param width the fixed field width for each sub-string
|
||||
// \param start the optional offset of where to start the splitting.
|
||||
// Any text prior to start is ignored in the operation.
|
||||
template<class StringType>
|
||||
Foam::SubStrings<StringType> splitFixed
|
||||
(
|
||||
//! The string to split
|
||||
const StringType& str,
|
||||
//! Fixed field width for each sub-string
|
||||
const std::string::size_type width,
|
||||
const std::string::size_type start = 0
|
||||
//! Offset within string to start splitting
|
||||
std::string::size_type pos = 0
|
||||
);
|
||||
|
||||
//- Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
|
||||
@ -416,23 +429,25 @@ namespace stringOps
|
||||
template<class StringType>
|
||||
Foam::SubStrings<StringType> splitSpace
|
||||
(
|
||||
const StringType& str
|
||||
//! The string to split
|
||||
const StringType& str,
|
||||
//! Offset within string to start splitting
|
||||
std::string::size_type pos = 0
|
||||
);
|
||||
|
||||
//- Output string with text wrapping.
|
||||
// Always includes a trailing newline, unless the string itself is empty.
|
||||
//
|
||||
// \param os the output stream
|
||||
// \param str the text to be output
|
||||
// \param width the max-width before wrapping
|
||||
// \param indent indentation for continued lines
|
||||
// \param escape escape any backslashes on output
|
||||
void writeWrapped
|
||||
(
|
||||
//! The output stream
|
||||
OSstream& os,
|
||||
//! The text to be output
|
||||
const std::string& str,
|
||||
//! The max-width before wrapping
|
||||
const std::string::size_type width,
|
||||
//! Indentation for continued lines
|
||||
const std::string::size_type indent = 0,
|
||||
//! Escape any backslashes on output
|
||||
const bool escape = false
|
||||
);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -98,34 +98,40 @@ Foam::SubStrings<StringType> Foam::stringOps::split
|
||||
(
|
||||
const StringType& str,
|
||||
const char delim,
|
||||
std::string::size_type pos,
|
||||
const bool keepEmpty
|
||||
)
|
||||
{
|
||||
Foam::SubStrings<StringType> lst;
|
||||
if (str.empty() || !delim)
|
||||
Foam::SubStrings<StringType> list;
|
||||
|
||||
if
|
||||
(
|
||||
!delim
|
||||
|| (pos == std::string::npos || pos >= str.size())
|
||||
)
|
||||
{
|
||||
return lst;
|
||||
return list;
|
||||
}
|
||||
|
||||
lst.reserve(20);
|
||||
list.reserve(20);
|
||||
|
||||
std::string::size_type beg = 0, end = 0;
|
||||
while ((end = str.find(delim, beg)) != std::string::npos)
|
||||
std::string::size_type end;
|
||||
while ((end = str.find(delim, pos)) != std::string::npos)
|
||||
{
|
||||
if (keepEmpty || (beg < end))
|
||||
if (keepEmpty || (pos < end))
|
||||
{
|
||||
lst.append(str.cbegin() + beg, str.cbegin() + end);
|
||||
list.append(str.cbegin() + pos, str.cbegin() + end);
|
||||
}
|
||||
beg = end + 1;
|
||||
pos = end + 1;
|
||||
}
|
||||
|
||||
// Trailing element
|
||||
if (keepEmpty ? (beg <= str.size()) : (beg < str.size()))
|
||||
if (keepEmpty ? (pos <= str.size()) : (pos < str.size()))
|
||||
{
|
||||
lst.append(str.cbegin() + beg, str.cend());
|
||||
list.append(str.cbegin() + pos, str.cend());
|
||||
}
|
||||
|
||||
return lst;
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@ -134,34 +140,40 @@ Foam::SubStrings<StringType> Foam::stringOps::split
|
||||
(
|
||||
const StringType& str,
|
||||
const std::string& delim,
|
||||
std::string::size_type pos,
|
||||
const bool keepEmpty
|
||||
)
|
||||
{
|
||||
Foam::SubStrings<StringType> lst;
|
||||
if (str.empty() || delim.empty())
|
||||
Foam::SubStrings<StringType> list;
|
||||
|
||||
if
|
||||
(
|
||||
delim.empty()
|
||||
|| (pos == std::string::npos || pos >= str.size())
|
||||
)
|
||||
{
|
||||
return lst;
|
||||
return list;
|
||||
}
|
||||
|
||||
lst.reserve(20);
|
||||
list.reserve(20);
|
||||
|
||||
std::string::size_type beg = 0, end = 0;
|
||||
while ((end = str.find(delim, beg)) != std::string::npos)
|
||||
std::string::size_type end;
|
||||
while ((end = str.find(delim, pos)) != std::string::npos)
|
||||
{
|
||||
if (keepEmpty || (beg < end))
|
||||
if (keepEmpty || (pos < end))
|
||||
{
|
||||
lst.append(str.cbegin() + beg, str.cbegin() + end);
|
||||
list.append(str.cbegin() + pos, str.cbegin() + end);
|
||||
}
|
||||
beg = end + delim.size();
|
||||
pos = end + delim.size();
|
||||
}
|
||||
|
||||
// Trailing element
|
||||
if (keepEmpty ? (beg <= str.size()) : (beg < str.size()))
|
||||
if (keepEmpty ? (pos <= str.size()) : (pos < str.size()))
|
||||
{
|
||||
lst.append(str.cbegin() + beg, str.cend());
|
||||
list.append(str.cbegin() + pos, str.cend());
|
||||
}
|
||||
|
||||
return lst;
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@ -169,40 +181,41 @@ template<class StringType>
|
||||
Foam::SubStrings<StringType> Foam::stringOps::splitAny
|
||||
(
|
||||
const StringType& str,
|
||||
const std::string& delim
|
||||
const std::string& delim,
|
||||
std::string::size_type pos
|
||||
)
|
||||
{
|
||||
Foam::SubStrings<StringType> lst;
|
||||
if (str.empty() || delim.empty())
|
||||
Foam::SubStrings<StringType> list;
|
||||
|
||||
if
|
||||
(
|
||||
delim.empty()
|
||||
|| (pos == std::string::npos || pos >= str.size())
|
||||
)
|
||||
{
|
||||
return lst;
|
||||
return list;
|
||||
}
|
||||
|
||||
lst.reserve(20);
|
||||
list.reserve(20);
|
||||
|
||||
for
|
||||
(
|
||||
std::string::size_type pos = 0;
|
||||
(pos = str.find_first_not_of(delim, pos)) != std::string::npos;
|
||||
/*nil*/
|
||||
)
|
||||
while ((pos = str.find_first_not_of(delim, pos)) != std::string::npos)
|
||||
{
|
||||
const auto end = str.find_first_of(delim, pos);
|
||||
|
||||
if (end == std::string::npos)
|
||||
{
|
||||
// Trailing element
|
||||
lst.append(str.cbegin() + pos, str.cend());
|
||||
list.append(str.cbegin() + pos, str.cend());
|
||||
break;
|
||||
}
|
||||
|
||||
// Intermediate element
|
||||
lst.append(str.cbegin() + pos, str.cbegin() + end);
|
||||
list.append(str.cbegin() + pos, str.cbegin() + end);
|
||||
|
||||
pos = end + 1;
|
||||
}
|
||||
|
||||
return lst;
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@ -211,43 +224,53 @@ Foam::SubStrings<StringType> Foam::stringOps::splitFixed
|
||||
(
|
||||
const StringType& str,
|
||||
const std::string::size_type width,
|
||||
const std::string::size_type start
|
||||
std::string::size_type pos
|
||||
)
|
||||
{
|
||||
Foam::SubStrings<StringType> lst;
|
||||
if (str.empty() || !width)
|
||||
Foam::SubStrings<StringType> list;
|
||||
|
||||
if
|
||||
(
|
||||
!width
|
||||
|| (pos == std::string::npos || pos >= str.size())
|
||||
)
|
||||
{
|
||||
return lst;
|
||||
return list;
|
||||
}
|
||||
|
||||
const auto len = str.size();
|
||||
lst.reserve(1 + (len / width));
|
||||
list.reserve(1 + ((str.size() - pos) / width));
|
||||
|
||||
for (std::string::size_type pos = start; pos < len; pos += width)
|
||||
const auto len = str.size();
|
||||
|
||||
while (pos < len)
|
||||
{
|
||||
const auto end = (pos + width);
|
||||
|
||||
if (end >= len)
|
||||
{
|
||||
// Trailing element
|
||||
lst.append(str.cbegin() + pos, str.cend());
|
||||
list.append(str.cbegin() + pos, str.cend());
|
||||
break;
|
||||
}
|
||||
|
||||
lst.append(str.cbegin() + pos, str.cbegin() + end);
|
||||
// Intermediate element
|
||||
list.append(str.cbegin() + pos, str.cbegin() + end);
|
||||
|
||||
pos += width;
|
||||
}
|
||||
|
||||
return lst;
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
template<class StringType>
|
||||
Foam::SubStrings<StringType> Foam::stringOps::splitSpace
|
||||
(
|
||||
const StringType& str
|
||||
const StringType& str,
|
||||
std::string::size_type pos
|
||||
)
|
||||
{
|
||||
return splitAny(str, "\t\n\v\f\r ");
|
||||
return splitAny(str, "\t\n\v\f\r ", pos);
|
||||
}
|
||||
|
||||
|
||||
|
@ -120,7 +120,7 @@ bool Foam::fileFormats::OBJedgeFormat::read(const fileName& filename)
|
||||
line += this->getLineNoComment(is);
|
||||
}
|
||||
|
||||
const SubStrings<string> tokens = stringOps::splitSpace(line);
|
||||
const auto tokens = stringOps::splitSpace(line);
|
||||
|
||||
// Require command and some arguments
|
||||
if (tokens.size() < 2)
|
||||
|
@ -193,7 +193,8 @@ bool Foam::fileFormats::NASsurfaceFormat<Face>::read
|
||||
if (line.starts_with("$ANSA_NAME"))
|
||||
{
|
||||
// Keep empty elements when splitting
|
||||
const auto args = stringOps::split<std::string>(line, ';', true);
|
||||
const auto args =
|
||||
stringOps::split<std::string>(line, ';', 0, true);
|
||||
|
||||
if (args.size() > 4 && line.starts_with("$ANSA_NAME_COMMENT"))
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ bool Foam::fileFormats::OBJsurfaceFormat<Face>::read
|
||||
line += this->getLineNoComment(is);
|
||||
}
|
||||
|
||||
const SubStrings<string> tokens = stringOps::splitSpace(line);
|
||||
const auto tokens = stringOps::splitSpace(line);
|
||||
|
||||
// Require command and some arguments
|
||||
if (tokens.size() < 2)
|
||||
|
Loading…
Reference in New Issue
Block a user