summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2021-04-12 07:54:22 -0400
committerAndreas Kling <kling@serenityos.org>2021-04-12 22:37:00 +0200
commit2370efbea6c1b46c1e7aacc303d9a5439c945fcd (patch)
tree57198bda1932029ecd2ecb6707b699691ad97384 /AK
parent04979865722ab558fdc4d909dbb9cecd40869897 (diff)
downloadserenity-2370efbea6c1b46c1e7aacc303d9a5439c945fcd.zip
AK: Add a predicate variant of StringView::split_view
Diffstat (limited to 'AK')
-rw-r--r--AK/StringView.cpp1
-rw-r--r--AK/StringView.h24
-rw-r--r--AK/Tests/TestStringView.cpp7
3 files changed, 31 insertions, 1 deletions
diff --git a/AK/StringView.cpp b/AK/StringView.cpp
index a08d31ff94..50a4c3b677 100644
--- a/AK/StringView.cpp
+++ b/AK/StringView.cpp
@@ -31,7 +31,6 @@
#include <AK/Memory.h>
#include <AK/String.h>
#include <AK/StringView.h>
-#include <AK/Vector.h>
namespace AK {
diff --git a/AK/StringView.h b/AK/StringView.h
index 3fa71bf85f..ae8e5a7a47 100644
--- a/AK/StringView.h
+++ b/AK/StringView.h
@@ -32,6 +32,7 @@
#include <AK/Span.h>
#include <AK/StdLibExtras.h>
#include <AK/StringUtils.h>
+#include <AK/Vector.h>
namespace AK {
@@ -108,6 +109,29 @@ public:
[[nodiscard]] Vector<StringView> split_view(char, bool keep_empty = false) const;
[[nodiscard]] Vector<StringView> split_view(const StringView&, bool keep_empty = false) const;
+ template<typename UnaryPredicate>
+ [[nodiscard]] Vector<StringView> split_view_if(UnaryPredicate&& predicate, bool keep_empty = false) const
+ {
+ if (is_empty())
+ return {};
+
+ Vector<StringView> v;
+ size_t substart = 0;
+ for (size_t i = 0; i < length(); ++i) {
+ char ch = characters_without_null_termination()[i];
+ if (predicate(ch)) {
+ size_t sublen = i - substart;
+ if (sublen != 0 || keep_empty)
+ v.append(substring_view(substart, sublen));
+ substart = i + 1;
+ }
+ }
+ size_t taillen = length() - substart;
+ if (taillen != 0 || keep_empty)
+ v.append(substring_view(substart, taillen));
+ return v;
+ }
+
// Create a Vector of StringViews split by line endings. As of CommonMark
// 0.29, the spec defines a line ending as "a newline (U+000A), a carriage
// return (U+000D) not followed by a newline, or a carriage return and a
diff --git a/AK/Tests/TestStringView.cpp b/AK/Tests/TestStringView.cpp
index a95be835bd..3a69070073 100644
--- a/AK/Tests/TestStringView.cpp
+++ b/AK/Tests/TestStringView.cpp
@@ -183,6 +183,13 @@ TEST_CASE(split_view)
test_string_view = "axxbcxxdxx";
EXPECT_EQ(test_string_view.split_view("xx"), Vector<StringView>({ "a", "bc", "d" }));
EXPECT_EQ(test_string_view.split_view("xx", true), Vector<StringView>({ "a", "bc", "d", "" }));
+
+ test_string_view = "ax_b_cxd";
+ auto predicate = [](char ch) { return ch == 'x' || ch == '_'; };
+ EXPECT_EQ(test_string_view.split_view_if(predicate), Vector<StringView>({ "a", "b", "c", "d" }));
+ EXPECT_EQ(test_string_view.split_view_if(predicate, true), Vector<StringView>({ "a", "", "b", "c", "d" }));
+ EXPECT_EQ(test_string_view.split_view_if(predicate), Vector<StringView>({ "a", "b", "c", "d" }));
+ EXPECT_EQ(test_string_view.split_view_if(predicate, true), Vector<StringView>({ "a", "", "b", "c", "d" }));
}
TEST_MAIN(StringView)