]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Util: Add split_into_views/split_into_strings functions
authorThomas Otto <thomas.otto@pdv-fs.de>
Tue, 3 Mar 2020 22:14:05 +0000 (23:14 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 16 Apr 2020 20:33:39 +0000 (22:33 +0200)
src/Util.cpp
src/Util.hpp
unittest/test_Util.cpp

index 5a2adb655855bde6b3a8e7653b30c34a2ccbfc3e..3ff0bac37fe813d96b6ad83bc002580daeb1494c 100644 (file)
@@ -89,6 +89,31 @@ path_max(const char* path)
 #endif
 }
 
+template<typename T>
+std::vector<T>
+split_at(string_view input, const char* separators)
+{
+  assert(separators != nullptr && separators[0] != '\0');
+
+  std::vector<T> result;
+
+  size_t start = 0;
+  while (start < input.size()) {
+    size_t end = input.find_first_of(separators, start);
+
+    if (end == string_view::npos) {
+      result.emplace_back(input.data() + start, input.size() - start);
+      break;
+    } else if (start != end) {
+      result.emplace_back(input.data() + start, end - start);
+    }
+
+    start = end + 1;
+  }
+
+  return result;
+}
+
 } // namespace
 
 namespace Util {
@@ -538,6 +563,18 @@ remove_extension(string_view path)
   return path.substr(0, path.length() - get_extension(path).length());
 }
 
+std::vector<string_view>
+split_into_views(string_view s, const char* separators)
+{
+  return split_at<string_view>(s, separators);
+}
+
+std::vector<std::string>
+split_into_strings(string_view s, const char* separators)
+{
+  return split_at<std::string>(s, separators);
+}
+
 bool
 starts_with(string_view string, string_view prefix)
 {
index 62f290bafb673edc76e1e377a2b2eb1d79a03170..f1dbd9418351d4af25ce43f3029a4f833000a44b 100644 (file)
@@ -239,6 +239,16 @@ std::string real_path(const std::string& path,
 // extension as determined by `get_extension()`.
 nonstd::string_view remove_extension(nonstd::string_view path);
 
+// Split `input` into words at any of the characters listed in `separators`.
+// These words are a view into `input`; empty words are omitted. `separators`
+// must neither be the empty string nor a nullptr.
+std::vector<nonstd::string_view> split_into_views(nonstd::string_view input,
+                                                  const char* separators);
+
+// Same as `split_into_views` but the words are copied from `input`.
+std::vector<std::string> split_into_strings(nonstd::string_view input,
+                                            const char* separators);
+
 // Return true if prefix is a prefix of string.
 bool starts_with(nonstd::string_view string, nonstd::string_view prefix);
 
index 0b0e9a0d00094704f889843af3ebb48028b206d2..3fc4d952c6a3eb9b7156e18424e85d8fc3a43c4a 100644 (file)
@@ -456,6 +456,88 @@ TEST_CASE("Util::remove_extension")
   CHECK(Util::remove_extension("/foo/bar/f.abc.txt") == "/foo/bar/f.abc");
 }
 
+TEST_CASE("Util::split_into_views")
+{
+  {
+    CHECK(Util::split_into_views("", "/").empty());
+  }
+  {
+    CHECK(Util::split_into_views("///", "/").empty());
+  }
+  {
+    auto s = Util::split_into_views("a/b", "/");
+    REQUIRE(s.size() == 2);
+    CHECK(s.at(0) == "a");
+    CHECK(s.at(1) == "b");
+  }
+  {
+    auto s = Util::split_into_views("a/b", "x");
+    REQUIRE(s.size() == 1);
+    CHECK(s.at(0) == "a/b");
+  }
+  {
+    auto s = Util::split_into_views("a/b:c", "/:");
+    REQUIRE(s.size() == 3);
+    CHECK(s.at(0) == "a");
+    CHECK(s.at(1) == "b");
+    CHECK(s.at(2) == "c");
+  }
+  {
+    auto s = Util::split_into_views(":a//b..:.c/:/.", "/:.");
+    REQUIRE(s.size() == 3);
+    CHECK(s.at(0) == "a");
+    CHECK(s.at(1) == "b");
+    CHECK(s.at(2) == "c");
+  }
+  {
+    auto s = Util::split_into_views(".0.1.2.3.4.5.6.7.8.9.", "/:.+_abcdef");
+    REQUIRE(s.size() == 10);
+    CHECK(s.at(0) == "0");
+    CHECK(s.at(9) == "9");
+  }
+}
+
+TEST_CASE("Util::split_into_strings")
+{
+  {
+    CHECK(Util::split_into_strings("", "/").empty());
+  }
+  {
+    CHECK(Util::split_into_strings("///", "/").empty());
+  }
+  {
+    auto s = Util::split_into_strings("a/b", "/");
+    REQUIRE(s.size() == 2);
+    CHECK(s.at(0) == "a");
+    CHECK(s.at(1) == "b");
+  }
+  {
+    auto s = Util::split_into_strings("a/b", "x");
+    REQUIRE(s.size() == 1);
+    CHECK(s.at(0) == "a/b");
+  }
+  {
+    auto s = Util::split_into_strings("a/b:c", "/:");
+    REQUIRE(s.size() == 3);
+    CHECK(s.at(0) == "a");
+    CHECK(s.at(1) == "b");
+    CHECK(s.at(2) == "c");
+  }
+  {
+    auto s = Util::split_into_strings(":a//b..:.c/:/.", "/:.");
+    REQUIRE(s.size() == 3);
+    CHECK(s.at(0) == "a");
+    CHECK(s.at(1) == "b");
+    CHECK(s.at(2) == "c");
+  }
+  {
+    auto s = Util::split_into_strings(".0.1.2.3.4.5.6.7.8.9.", "/:.+_abcdef");
+    REQUIRE(s.size() == 10);
+    CHECK(s.at(0) == "0");
+    CHECK(s.at(9) == "9");
+  }
+}
+
 TEST_CASE("Util::starts_with")
 {
   CHECK(Util::starts_with("", ""));