diff options
author | demostanis <demostanis@protonmail.com> | 2022-10-22 16:31:59 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-10-24 23:29:18 +0100 |
commit | 7c33f8f7df321e2406f324f9aaa3890620a192e5 (patch) | |
tree | d3a7059d254b78456d0b3c1de81dc65542ec33bd | |
parent | 3e8b5ac92012e19847e536a20a3f0ec7e5c787d3 (diff) | |
download | serenity-7c33f8f7df321e2406f324f9aaa3890620a192e5.zip |
AK: Add SplitBehavior::KeepTrailingSeparator with tests
-rw-r--r-- | AK/String.cpp | 6 | ||||
-rw-r--r-- | AK/StringUtils.h | 9 | ||||
-rw-r--r-- | AK/StringView.cpp | 3 | ||||
-rw-r--r-- | AK/StringView.h | 9 | ||||
-rw-r--r-- | Tests/AK/TestStringView.cpp | 5 |
5 files changed, 26 insertions, 6 deletions
diff --git a/AK/String.cpp b/AK/String.cpp index 2497e8c8b4..3c63b70b62 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -110,12 +110,13 @@ Vector<String> String::split_limit(char separator, size_t limit, SplitBehavior s Vector<String> v; size_t substart = 0; bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty); + bool keep_separator = has_flag(split_behavior, SplitBehavior::KeepTrailingSeparator); for (size_t i = 0; i < length() && (v.size() + 1) != limit; ++i) { char ch = characters()[i]; if (ch == separator) { size_t sublen = i - substart; if (sublen != 0 || keep_empty) - v.append(substring(substart, sublen)); + v.append(substring(substart, keep_separator ? sublen + 1 : sublen)); substart = i + 1; } } @@ -133,12 +134,13 @@ Vector<StringView> String::split_view(Function<bool(char)> separator, SplitBehav Vector<StringView> v; size_t substart = 0; bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty); + bool keep_separator = has_flag(split_behavior, SplitBehavior::KeepTrailingSeparator); for (size_t i = 0; i < length(); ++i) { char ch = characters()[i]; if (separator(ch)) { size_t sublen = i - substart; if (sublen != 0 || keep_empty) - v.append(substring_view(substart, sublen)); + v.append(substring_view(substart, keep_separator ? sublen + 1 : sublen)); substart = i + 1; } } diff --git a/AK/StringUtils.h b/AK/StringUtils.h index 60dde9c359..883196ecfb 100644 --- a/AK/StringUtils.h +++ b/AK/StringUtils.h @@ -40,10 +40,17 @@ enum class TrimWhitespace { }; enum class SplitBehavior : unsigned { + // Neither keep empty substrings nor keep the trailing separator. + // This is the default behavior if unspecified. Nothing = 0, + // If two separators follow each other without any characters - // in between, keep a "" in the resulting vector. + // in between, keep a "" in the resulting vector. (or only the + // separator if KeepTrailingSeparator is used) KeepEmpty = 1, + + // Do not strip off the separator at the end of the string. + KeepTrailingSeparator = 2, }; AK_ENUM_BITWISE_OPERATORS(SplitBehavior); diff --git a/AK/StringView.cpp b/AK/StringView.cpp index 1b906d7970..3840e7c7f5 100644 --- a/AK/StringView.cpp +++ b/AK/StringView.cpp @@ -272,12 +272,13 @@ Vector<StringView> StringView::split_view_if(Function<bool(char)> const& predica Vector<StringView> v; size_t substart = 0; bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty); + bool keep_separator = has_flag(split_behavior, SplitBehavior::KeepTrailingSeparator); 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)); + v.append(substring_view(substart, keep_separator ? sublen + 1 : sublen)); substart = i + 1; } } diff --git a/AK/StringView.h b/AK/StringView.h index e9d58c3198..8e65691e5a 100644 --- a/AK/StringView.h +++ b/AK/StringView.h @@ -170,11 +170,16 @@ public: auto maybe_separator_index = find(separator); bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty); + bool keep_separator = has_flag(split_behavior, SplitBehavior::KeepTrailingSeparator); while (maybe_separator_index.has_value()) { auto separator_index = maybe_separator_index.value(); auto part_with_separator = view.substring_view(0, separator_index + separator.length()); - if (keep_empty || separator_index > 0) - callback(part_with_separator.substring_view(0, separator_index)); + if (keep_empty || separator_index > 0) { + if (keep_separator) + callback(part_with_separator); + else + callback(part_with_separator.substring_view(0, separator_index)); + } view = view.substring_view_starting_after_substring(part_with_separator); maybe_separator_index = view.find(separator); } diff --git a/Tests/AK/TestStringView.cpp b/Tests/AK/TestStringView.cpp index 6aafffe82b..9d5bc18e0a 100644 --- a/Tests/AK/TestStringView.cpp +++ b/Tests/AK/TestStringView.cpp @@ -163,6 +163,11 @@ TEST_CASE(split_view) EXPECT_EQ(test_string_view.split_view_if(predicate, SplitBehavior::KeepEmpty), Vector({ "a"sv, ""sv, "b"sv, "c"sv, "d"sv })); EXPECT_EQ(test_string_view.split_view_if(predicate), Vector({ "a"sv, "b"sv, "c"sv, "d"sv })); EXPECT_EQ(test_string_view.split_view_if(predicate, SplitBehavior::KeepEmpty), Vector({ "a"sv, ""sv, "b"sv, "c"sv, "d"sv })); + + test_string_view = "a,,,b"sv; + EXPECT_EQ(test_string_view.split_view(","sv, SplitBehavior::KeepEmpty), Vector({ "a"sv, ""sv, ""sv, "b"sv })); + EXPECT_EQ(test_string_view.split_view(","sv, SplitBehavior::KeepTrailingSeparator), Vector({ "a,"sv, "b"sv })); + EXPECT_EQ(test_string_view.split_view(","sv, SplitBehavior::KeepTrailingSeparator | SplitBehavior::KeepEmpty), Vector({ "a,"sv, ","sv, ","sv, "b"sv })); } TEST_CASE(constexpr_stuff) |