Commit bfce1cee authored by Dominik Charousset's avatar Dominik Charousset

Streamline string algos, add (begins|ends)_with

parent 517dc6cb
...@@ -106,6 +106,7 @@ set(LIBCAF_CORE_SRCS ...@@ -106,6 +106,7 @@ set(LIBCAF_CORE_SRCS
src/stream_aborter.cpp src/stream_aborter.cpp
src/stream_manager.cpp src/stream_manager.cpp
src/stream_priority.cpp src/stream_priority.cpp
src/string_algorithms.cpp
src/string_view.cpp src/string_view.cpp
src/stringification_inspector.cpp src/stringification_inspector.cpp
src/sync_request_bouncer.cpp src/sync_request_bouncer.cpp
......
...@@ -28,118 +28,60 @@ ...@@ -28,118 +28,60 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/string_view.hpp"
namespace caf { namespace caf {
// provide boost::split compatible interface // provide boost::split compatible interface
inline std::string is_any_of(std::string arg) { inline string_view is_any_of(string_view arg) {
return arg; return arg;
} }
constexpr bool token_compress_on = false; constexpr bool token_compress_on = false;
template <class Container, class Str, class Delim> void split(std::vector<std::string>& result, string_view str,
void split(Container& result, const Str& str, const Delim& delims, string_view delims, bool keep_all = true);
bool keep_all = true) {
size_t pos = 0;
size_t prev = 0;
while ((pos = str.find_first_of(delims, prev)) != std::string::npos) {
if (pos > prev) {
auto substr = str.substr(prev, pos - prev);
if (!substr.empty() || keep_all) {
result.push_back(std::move(substr));
}
}
prev = pos + 1;
}
if (prev < str.size())
result.push_back(str.substr(prev, std::string::npos));
}
template <class Iterator>
class iterator_range {
public:
using iterator = Iterator;
iterator_range(iterator first, iterator last) : begin_(first), end_(last) {
// nop
}
iterator begin() const {
return begin_;
}
iterator end() const { void split(std::vector<string_view>& result, string_view str,
return end_; string_view delims, bool keep_all = true);
}
private:
iterator begin_;
iterator end_;
};
template <class InputIterator>
std::string join(InputIterator first, InputIterator last, string_view glue) {
if (first == last)
return {};
std::ostringstream oss;
oss << *first++;
for (; first != last; ++first)
oss << glue << *first;
return oss.str();
}
template <class Container> template <class Container>
std::string join(const Container& c, const std::string& glue) { std::string join(const Container& c, const std::string& glue) {
auto begin = c.begin(); return join(c.begin(), c.end(), glue);
auto end = c.end();
bool first = true;
std::ostringstream oss;
for ( ; begin != end; ++begin) {
if (first)
first = false;
else
oss << glue;
oss << *begin;
}
return oss.str();
} }
// end of recursion // end of recursion
inline void splice(std::string&, const std::string&) { inline void splice(std::string&, string_view) {
// nop // nop
} }
template <class T, class... Ts> template <class T, class... Ts>
void splice(std::string& str, const std::string& glue, T&& arg, Ts&&... xs) { void splice(std::string& str, string_view glue, T&& arg, Ts&&... xs) {
str += glue; str.insert(str.end(), glue.begin(), glue.end());
str += std::forward<T>(arg); str += std::forward<T>(arg);
splice(str, glue, std::forward<Ts>(xs)...); splice(str, glue, std::forward<Ts>(xs)...);
} }
template <ptrdiff_t WhatSize, ptrdiff_t WithSize> /// Replaces all occurrences of `what` by `with` in `str`.
void replace_all(std::string& str, void replace_all(std::string& str, string_view what, string_view with);
const char (&what)[WhatSize],
const char (&with)[WithSize]) {
// end(what) - 1 points to the null-terminator
auto next = [&](std::string::iterator pos) -> std::string::iterator {
return std::search(pos, str.end(), std::begin(what), std::end(what) - 1);
};
auto i = next(std::begin(str));
while (i != std::end(str)) {
auto before = std::distance(std::begin(str), i);
CAF_ASSERT(before >= 0);
str.replace(i, i + WhatSize - 1, with);
// i became invalidated -> use new iterator pointing
// to the first character after the replaced text
i = next(str.begin() + before + (WithSize - 1));
}
}
template<size_t S> /// Returns whether `str` begins with `prefix`.
bool starts_with(const std::string& str, const char (&prefix)[S]) { bool starts_with(string_view str, string_view prefix);
return str.compare(0, S - 1, prefix) == 0;
}
template <size_t S> /// Returns whether `str` ends with `suffix`.
bool ends_with(const std::string& str, const char (&suffix)[S]) { bool ends_with(string_view str, string_view suffix);
auto n = str.size();
auto m = S - 1;
if (n >= m)
return str.compare(n - m, m, suffix) == 0;
return false;
}
template <class T> template <class T>
typename std::enable_if< typename std::enable_if<
......
...@@ -25,16 +25,15 @@ std::string replies_to_type_name(size_t input_size, ...@@ -25,16 +25,15 @@ std::string replies_to_type_name(size_t input_size,
const std::string* input, const std::string* input,
size_t output_opt1_size, size_t output_opt1_size,
const std::string* output_opt1) { const std::string* output_opt1) {
using irange = iterator_range<const std::string*>; string_view glue = ",";
std::string glue = ",";
std::string result; std::string result;
// 'void' is not an announced type, hence we check whether uniform_typeid // 'void' is not an announced type, hence we check whether uniform_typeid
// did return a valid pointer to identify 'void' (this has the // did return a valid pointer to identify 'void' (this has the
// possibility of false positives, but those will be catched anyways) // possibility of false positives, but those will be catched anyways)
result = "caf::replies_to<"; result = "caf::replies_to<";
result += join(irange{input, input + input_size}, glue); result += join(input, input + input_size, glue);
result += ">::with<"; result += ">::with<";
result += join(irange{output_opt1, output_opt1 + output_opt1_size}, glue); result += join(output_opt1, output_opt1 + output_opt1_size, glue);
result += ">"; result += ">";
return result; return result;
} }
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/string_algorithms.hpp"
namespace caf {
namespace {
template <class F>
void split_impl(F consume, string_view str, string_view delims, bool keep_all) {
size_t pos = 0;
size_t prev = 0;
while ((pos = str.find_first_of(delims, prev)) != std::string::npos) {
if (pos > prev) {
auto substr = str.substr(prev, pos - prev);
if (!substr.empty() || keep_all)
consume(substr);
}
prev = pos + 1;
}
if (prev < str.size())
consume(str.substr(prev, std::string::npos));
}
} // namespace <anonymous>
void split(std::vector<std::string>& result, string_view str,
string_view delims, bool keep_all) {
auto f = [&](string_view sv) {
result.emplace_back(sv.begin(), sv.end());
};
return split_impl(f, str, delims, keep_all);
}
void split(std::vector<string_view>& result, string_view str,
string_view delims, bool keep_all) {
auto f = [&](string_view sv) {
result.emplace_back(sv);
};
return split_impl(f, str, delims, keep_all);
}
void replace_all(std::string& str, string_view what, string_view with) {
// end(what) - 1 points to the null-terminator
auto next = [&](std::string::iterator pos) -> std::string::iterator {
return std::search(pos, str.end(), what.begin(), what.end());
};
auto i = next(str.begin());
while (i != str.end()) {
auto before = std::distance(str.begin(), i);
CAF_ASSERT(before >= 0);
str.replace(i, i + what.size(), with.begin(), with.end());
// Iterator i became invalidated -> use new iterator pointing to the first
// character after the replaced text.
i = next(str.begin() + before + with.size());
}
}
bool starts_with(string_view str, string_view prefix) {
return str.compare(0, prefix.size(), prefix) == 0;
}
bool ends_with(string_view str, string_view suffix) {
auto n = str.size();
auto m = suffix.size();
return n >= m ? str.compare(n - m, m, suffix) == 0 : false;
}
} // namespace caf
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment