Skip to content

Commit

Permalink
Reduce dependency on Boost string_view/algorithms ECFLOW-1922
Browse files Browse the repository at this point in the history
  • Loading branch information
marcosbento authored Nov 17, 2023
2 parents f2dea78 + e39fc77 commit c00afce
Show file tree
Hide file tree
Showing 42 changed files with 160 additions and 278 deletions.
6 changes: 2 additions & 4 deletions ACore/src/NodePath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

#include "NodePath.hpp"

#include <boost/algorithm/string/trim.hpp>

#include "Str.hpp"

using namespace ecf;
Expand Down Expand Up @@ -45,8 +43,8 @@ bool NodePath::extractHostPort(const std::string& path, std::string& host, std::
host = thePath[0].substr(0, colonPos);
port = thePath[0].substr(colonPos + 1);

boost::algorithm::trim(host);
boost::algorithm::trim(port);
ecf::algorithm::trim(host);
ecf::algorithm::trim(port);
if (host.empty())
return false;
if (port.empty())
Expand Down
4 changes: 1 addition & 3 deletions ACore/src/PasswdFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

#include <iostream>

#include <boost/algorithm/string/trim.hpp>

#include "Converter.hpp"
#include "File.hpp"
#include "PasswordEncryption.hpp"
Expand Down Expand Up @@ -73,7 +71,7 @@ bool PasswdFile::load(const std::string& file, bool debug, std::string& errorMsg
theLine.erase(comment_pos);
}

boost::algorithm::trim(theLine); // remove leading and trailing spaces
ecf::algorithm::trim(theLine); // remove leading and trailing spaces
std::vector<std::string> lineTokens;
Str::split(theLine, lineTokens);
if (lineTokens.empty())
Expand Down
32 changes: 14 additions & 18 deletions ACore/src/Str.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ void Str::split(const std::string& line, std::vector<std::string>& tokens, const
// times = 0.686s wall, (0.690s user + 0.000s system = 0.690s) CPU (100.6%) Time for Str::split_using_string_view
// 1000000 times = 0.482s wall, (0.480s user + 0.000s system = 0.480s) CPU (99.6%) Time for
// make_split_iterator::split 1000000 times = 3.611s wall, (3.610s user + 0.000s system = 3.610s) CPU (100.0%)
// Time for boost::string_view 1000000 times = 0.769s wall, (0.770s user + 0.000s system = 0.770s) CPU
// (100.1%) Time for boost::string_view(2) 1000000 times = 0.688s wall, (0.690s user + 0.000s system =
// Time for std::string_view 1000000 times = 0.769s wall, (0.770s user + 0.000s system = 0.770s) CPU
// (100.1%) Time for std::string_view(2) 1000000 times = 0.688s wall, (0.690s user + 0.000s system =
// 0.690s) CPU (100.3%)
// ACore:: ...test_str_split_perf_with_file
// This test will split each line in file ${ECF_TEST_DEFS_DIR}vsms2.31415.def
Expand All @@ -295,9 +295,9 @@ void Str::split(const std::string& line, std::vector<std::string>& tokens, const
// (0.500s user + 0.000s system = 0.500s) CPU (99.7%) Time for Str::split_using_string_view 2001774 times =
// 0.489s wall, (0.490s user + 0.000s system = 0.490s) CPU (100.3%) Time for Str::split_using_string_view2 2001774
// times = 0.639s wall, (0.630s user + 0.000s system = 0.630s) CPU (98.6%) Time for boost::make_split_iterator
// 2001774 times = 3.338s wall, (3.340s user + 0.000s system = 3.340s) CPU (100.1%) Time for boost::string_view
// 2001774 times = 3.338s wall, (3.340s user + 0.000s system = 3.340s) CPU (100.1%) Time for std::string_view
// 2001774 times = 0.599s wall, (0.600s user + 0.000s system = 0.600s) CPU (100.1%) Time for
// boost::string_view(2) 2001774 times = 0.696s wall, (0.700s user + 0.000s system = 0.700s) CPU (100.6%)
// std::string_view(2) 2001774 times = 0.696s wall, (0.700s user + 0.000s system = 0.700s) CPU (100.6%)
}

void Str::split_orig(const std::string& line, std::vector<std::string>& tokens, const std::string& delimiters) {
Expand Down Expand Up @@ -331,9 +331,7 @@ void Str::split_orig1(const std::string& line, std::vector<std::string>& tokens,
}
}

void Str::split_using_string_view(boost::string_view strv,
std::vector<std::string>& output,
boost::string_view delims) {
void Str::split_using_string_view(std::string_view strv, std::vector<std::string>& output, std::string_view delims) {
// Uses pointers
for (auto first = strv.data(), second = strv.data(), last = first + strv.size(); second != last && first != last;
first = second + 1) {
Expand All @@ -344,28 +342,26 @@ void Str::split_using_string_view(boost::string_view strv,
}
}

void Str::split_using_string_view2(boost::string_view strv,
std::vector<std::string>& output,
boost::string_view delims) {
void Str::split_using_string_view2(std::string_view strv, std::vector<std::string>& output, std::string_view delims) {
size_t first = 0;

size_t strv_size = strv.size();
while (first < strv_size) {
const auto second = strv.find_first_of(delims, first);

if (first != second) {
boost::string_view ref = strv.substr(first, second - first);
std::string_view ref = strv.substr(first, second - first);
output.emplace_back(ref.begin(), ref.end());
}

if (second == boost::string_view::npos)
if (second == std::string_view::npos)
break;

first = second + 1;
}
}

bool Str::get_token(boost::string_view str, size_t pos, std::string& token, boost::string_view delims) {
bool Str::get_token(std::string_view str, size_t pos, std::string& token, std::string_view delims) {
// Time for StringSplitter::get_token 250000 times = 1.457s wall, (1.460s user + 0.000s system = 1.460s) CPU
// (100.2%) Time for Str::get_token 250000 times = 0.566s wall, (0.560s user + 0.000s system = 0.560s)
// CPU (99.0%) Time for Str::get_token2 250000 times = 0.668s wall, (0.670s user + 0.000s system =
Expand Down Expand Up @@ -395,30 +391,30 @@ bool Str::get_token(boost::string_view str, size_t pos, std::string& token, boos
return false;
}

bool Str::get_token2(boost::string_view strv, size_t pos, std::string& token, boost::string_view delims) {
bool Str::get_token2(std::string_view strv, size_t pos, std::string& token, std::string_view delims) {
size_t current_pos = 0;
size_t first = 0;
while (first < strv.size()) {
const auto second = strv.find_first_of(delims, first);

if (first != second) {
if (current_pos == pos) {
boost::string_view ref = strv.substr(first, second - first);
token = std::string(ref.begin(), ref.end());
std::string_view ref = strv.substr(first, second - first);
token = std::string(ref.begin(), ref.end());
return true;
}
current_pos++;
}

if (second == boost::string_view::npos)
if (second == std::string_view::npos)
break;

first = second + 1;
}
return false;
}

bool Str::get_token3(boost::string_view str, size_t pos, std::string& token, boost::string_view delims) {
bool Str::get_token3(std::string_view str, size_t pos, std::string& token, std::string_view delims) {
size_t current_pos = 0;
for (auto first = str.data(), second = str.data(), last = first + str.size(); second != last && first != last;
first = second + 1) {
Expand Down
48 changes: 39 additions & 9 deletions ACore/src/Str.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,46 @@
//
// Description : This class is used as a helper class
//============================================================================
#include <cstring> //for strcmp

#include <cstring>
#include <limits>
#include <string>
#include <vector>

#include <boost/algorithm/string.hpp>
#include <boost/utility/string_view.hpp>
#include <string_view>

namespace ecf {

namespace algorithm {

template <typename Sequence1, typename Sequence2>
inline static auto join(const Sequence1& strings, const Sequence2& separator) {
return ::boost::algorithm::join(strings, separator);
}

template <typename Sequence, typename SearchSequence, typename ReplaceSequence>
inline static auto replace_first(Sequence& input, const SearchSequence& search, const ReplaceSequence& replace) {
return ::boost::algorithm::replace_first(input, search, replace);
}

template <typename ResultSequence, typename Sequence1, typename Sequence2>
inline static ResultSequence& split(ResultSequence& result, const Sequence1& input, const Sequence2& separators) {
return ::boost::algorithm::split(result, input, ::boost::is_any_of(separators));
}

template <typename Sequence1, typename Sequence2>
inline static bool starts_with(const Sequence1& input, const Sequence2& pattern) {
return ::boost::algorithm::starts_with(input, pattern);
}

template <typename Sequence>
inline static void trim(Sequence& input) {
::boost::algorithm::trim(input);
}

} // namespace algorithm

class Str {
public:
static int reserve_4() { return 4; }
Expand Down Expand Up @@ -69,18 +99,18 @@ class Str {
static void
split_orig1(const std::string& line, std::vector<std::string>& tokens, const std::string& delimiters = " \t");

static void split_using_string_view(boost::string_view line,
static void split_using_string_view(std::string_view line,
std::vector<std::string>& tokens,
boost::string_view delimiters = " \t");
std::string_view delimiters = " \t");

static void split_using_string_view2(boost::string_view line,
static void split_using_string_view2(std::string_view line,
std::vector<std::string>& tokens,
boost::string_view delimiters = " \t");
std::string_view delimiters = " \t");

// Get token at a given pos. Two different implementations
static bool get_token(boost::string_view line, size_t pos, std::string& token, boost::string_view sep = " \t");
static bool get_token2(boost::string_view line, size_t pos, std::string& token, boost::string_view sep = " \t");
static bool get_token3(boost::string_view line, size_t pos, std::string& token, boost::string_view sep = " \t");
static bool get_token(std::string_view line, size_t pos, std::string& token, std::string_view sep = " \t");
static bool get_token2(std::string_view line, size_t pos, std::string& token, std::string_view sep = " \t");
static bool get_token3(std::string_view line, size_t pos, std::string& token, std::string_view sep = " \t");

// Uses boost::make_split_iterator will remove
// consecutive delimiters in the middle of the string
Expand Down
48 changes: 17 additions & 31 deletions ACore/src/StringSplitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ bool StringSplitter::finished() const {
if (finished_)
return true;
first_not_of_ = rem_.find_first_not_of(sep_);
if (first_not_of_ == boost::string_view::npos)
if (first_not_of_ == std::string_view::npos)
finished_ = true;
return finished_;
}

boost::string_view StringSplitter::next() const {
std::string_view StringSplitter::next() const {
if (first_not_of_ != 0)
rem_ = rem_.substr(first_not_of_);

boost::string_view::size_type pos = rem_.find_first_of(sep_); // Find first "non-delimiter".
if (pos != boost::string_view::npos) {
boost::string_view ret = rem_.substr(0, pos);
rem_ = rem_.substr(pos + 1); // skip over separator
std::string_view::size_type pos = rem_.find_first_of(sep_); // Find first "non-delimiter".
if (pos != std::string_view::npos) {
std::string_view ret = rem_.substr(0, pos);
rem_ = rem_.substr(pos + 1); // skip over separator

// if separator is at the end, lose the last empty tokens
if (rem_.find_first_not_of(sep_) == boost::string_view::npos) {
if (rem_.find_first_not_of(sep_) == std::string_view::npos) {
finished_ = true;
}
return ret;
Expand All @@ -54,30 +54,18 @@ void StringSplitter::reset() {
}

void StringSplitter::split(const std::string& str,
std::vector<boost::string_view>& lineTokens,
boost::string_view delimiters) {
std::vector<std::string_view>& lineTokens,
std::string_view delimiters) {
StringSplitter string_splitter(str, delimiters);
while (!string_splitter.finished()) {
lineTokens.push_back(string_splitter.next());
}
}

void StringSplitter::split2(boost::string_view str, std::vector<boost::string_view>& ret, const char* delims) {
// // Skip delimiters at beginning.
// boost::string_view ::size_type lastPos = str.find_first_not_of( delims, 0 );
//
// // Find first "non-delimiter".
// boost::string_view::size_type pos = str.find_first_of( delims, lastPos );
//
// while ( boost::string_view::npos != pos || boost::string_view::npos != lastPos ) {
// ret.push_back( str.substr( lastPos, pos - lastPos ) ); // Found a token, add it to the vector.
// lastPos = str.find_first_not_of( delims, pos ); // Skip delimiters. Note the "not_of"
// pos = str.find_first_of( delims, lastPos ); // Find next "non-delimiter"
// }

boost::string_view::size_type start = 0;
auto pos = str.find_first_of(delims, start);
while (pos != boost::string_view::npos) {
void StringSplitter::split2(std::string_view str, std::vector<std::string_view>& ret, const char* delims) {
std::string_view::size_type start = 0;
auto pos = str.find_first_of(delims, start);
while (pos != std::string_view::npos) {
if (pos != start) {
ret.emplace_back(str.substr(start, pos - start));
}
Expand All @@ -88,21 +76,19 @@ void StringSplitter::split2(boost::string_view str, std::vector<boost::string_vi
ret.emplace_back(str.substr(start, str.length() - start));
}

void StringSplitter::split(const std::string& str,
std::vector<std::string>& lineTokens,
boost::string_view delimiters) {
void StringSplitter::split(const std::string& str, std::vector<std::string>& lineTokens, std::string_view delimiters) {
StringSplitter string_splitter(str, delimiters);
while (!string_splitter.finished()) {
boost::string_view ref = string_splitter.next();
std::string_view ref = string_splitter.next();
lineTokens.emplace_back(ref.begin(), ref.end());
}
}

bool StringSplitter::get_token(boost::string_view line, size_t pos, std::string& token, boost::string_view sep) {
bool StringSplitter::get_token(std::string_view line, size_t pos, std::string& token, std::string_view sep) {
size_t count = 0;
StringSplitter string_splitter(line, sep);
while (!string_splitter.finished()) {
boost::string_view the_token = string_splitter.next();
std::string_view the_token = string_splitter.next();
if (count == pos) {
token = std::string(the_token.begin(), the_token.end());
return true;
Expand Down
34 changes: 17 additions & 17 deletions ACore/src/StringSplitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,72 +15,72 @@
// Description :
//============================================================================

#include <string>
#include <vector>

#include <boost/utility/string_view.hpp>
#include <string_view>

namespace ecf {

// ****************************************************************************
// IMPORTANT: boost::string_view is a *READ ONLY* REFERENCE to an existing string
// IMPORTANT: std::string_view is a *READ ONLY* REFERENCE to an existing string
// HENCE: the reference string *MUST* not change, and its lifetime must EXCEED string_view
//
// Will split a string. Will return a empty boost::string_view if there a separator at the end.
// Will split a string. Will return a empty std::string_view if there a separator at the end.
// This shows the fastest split for a string. **** Based on boost 1.64 ****
// Method: time
// boost::split: 4.06
// Str::split: 2.33
// make_split_iterator 4.07
// boost::string_view 1.42
// std::string_view 1.42

class StringSplitter {
boost::string_view src_;
mutable boost::string_view rem_;
boost::string_view sep_;
mutable boost::string_view::size_type first_not_of_;
std::string_view src_;
mutable std::string_view rem_;
std::string_view sep_;
mutable std::string_view::size_type first_not_of_;
mutable bool finished_;

public:
explicit StringSplitter(boost::string_view src, boost::string_view sep = " \t")
explicit StringSplitter(std::string_view src, std::string_view sep = " \t")
: src_(src),
rem_(src),
sep_(sep),
first_not_of_(0),
finished_(false) {}

// this rules out temp strings, it also rules out char * because of two available overloads
StringSplitter(const std::string&& src, boost::string_view sep) = delete;
StringSplitter(const std::string&& src, std::string_view sep) = delete;

// this re-enables support for string literals (which are never temp)
// it even handles correctly char arrays that contain a null terminated string
// because string_view does not have a char array constructor!
template <std::size_t N>
explicit StringSplitter(const char (&sz)[N], boost::string_view sep = " \t")
explicit StringSplitter(const char (&sz)[N], std::string_view sep = " \t")
: src_(sz),
rem_(sz),
sep_(sep),
first_not_of_(0),
finished_(false) {}

boost::string_view next() const;
std::string_view next() const;
bool finished() const;
bool last() const { return finished_; }
void reset();

/// The preferred splitter as it does not create strings
static void
split(const std::string& str, std::vector<boost::string_view>& lineTokens, boost::string_view delimiters = " \t");
split(const std::string& str, std::vector<std::string_view>& lineTokens, std::string_view delimiters = " \t");

// This the fastest splitter at the moment
static void
split2(boost::string_view str, std::vector<boost::string_view>& lineTokens, const char* delimiters = " \t");
static void split2(std::string_view str, std::vector<std::string_view>& lineTokens, const char* delimiters = " \t");

/// This was added to maintain compatibility, slightly faster than original Str::split
static void
split(const std::string& str, std::vector<std::string>& lineTokens, boost::string_view delimiters = " \t");
split(const std::string& str, std::vector<std::string>& lineTokens, std::string_view delimiters = " \t");

/// return the token at pos, otherwise returns false.
static bool get_token(boost::string_view line, size_t pos, std::string& token, boost::string_view sep = " \t");
static bool get_token(std::string_view line, size_t pos, std::string& token, std::string_view sep = " \t");
};

} // namespace ecf
Expand Down
Loading

0 comments on commit c00afce

Please sign in to comment.