#include "string.hpp"
+#include <assertions.hpp>
#include <fmtmacros.hpp>
#include <cctype>
return result;
}
+std::string
+replace_all(const nonstd::string_view string,
+ const nonstd::string_view from,
+ const nonstd::string_view to)
+{
+ if (from.empty()) {
+ return std::string(string);
+ }
+
+ std::string result;
+ size_t left = 0;
+ size_t right = 0;
+ while (left < string.size()) {
+ right = string.find(from, left);
+ if (right == nonstd::string_view::npos) {
+ result.append(string.data() + left);
+ break;
+ }
+ result.append(string.data() + left, right - left);
+ result.append(to.data(), to.size());
+ left = right + from.size();
+ }
+ return result;
+}
+
std::string
replace_first(const nonstd::string_view string,
const nonstd::string_view from,
nonstd::expected<std::string, std::string>
percent_decode(nonstd::string_view string);
+// Replace the all occurrences of `from` to `to` in `string`.
+std::string replace_all(nonstd::string_view string,
+ nonstd::string_view from,
+ nonstd::string_view to);
+
// Replace the first occurrence of `from` to `to` in `string`.
std::string replace_first(nonstd::string_view string,
nonstd::string_view from,
== "invalid percent-encoded string at position 1: a%0g");
}
+TEST_CASE("util::replace_all")
+{
+ CHECK(util::replace_all("", "", "") == "");
+ CHECK(util::replace_all("x", "", "") == "x");
+ CHECK(util::replace_all("", "x", "") == "");
+ CHECK(util::replace_all("", "", "x") == "");
+ CHECK(util::replace_all("x", "y", "z") == "x");
+ CHECK(util::replace_all("x", "x", "y") == "y");
+ CHECK(util::replace_all("abc", "abc", "defdef") == "defdef");
+ CHECK(util::replace_all("xabc", "abc", "defdef") == "xdefdef");
+ CHECK(util::replace_all("abcx", "abc", "defdef") == "defdefx");
+ CHECK(util::replace_all("xabcyabcz", "abc", "defdef") == "xdefdefydefdefz");
+}
+
TEST_CASE("util::replace_first")
{
CHECK(util::replace_first("", "", "") == "");