mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
AK+Everywhere: Turn bool keep_empty to an enum in split* functions
This commit is contained in:
parent
f485db2501
commit
3e8b5ac920
Notes:
sideshowbarker
2024-07-17 07:09:53 +09:00
Author: https://github.com/demostanis Commit: https://github.com/SerenityOS/serenity/commit/3e8b5ac920 Pull-request: https://github.com/SerenityOS/serenity/pull/15750 Reviewed-by: https://github.com/AtkinsSJ Reviewed-by: https://github.com/davidot Reviewed-by: https://github.com/linusg ✅
44 changed files with 96 additions and 81 deletions
|
@ -125,7 +125,7 @@ public:
|
|||
if (string.is_null())
|
||||
return {};
|
||||
|
||||
auto const parts = string.split_view(':', true);
|
||||
auto const parts = string.split_view(':', SplitBehavior::KeepEmpty);
|
||||
if (parts.is_empty())
|
||||
return {};
|
||||
if (parts.size() > 9) {
|
||||
|
|
|
@ -97,18 +97,19 @@ StringView String::substring_view(size_t start) const
|
|||
return { characters() + start, length() - start };
|
||||
}
|
||||
|
||||
Vector<String> String::split(char separator, bool keep_empty) const
|
||||
Vector<String> String::split(char separator, SplitBehavior split_behavior) const
|
||||
{
|
||||
return split_limit(separator, 0, keep_empty);
|
||||
return split_limit(separator, 0, split_behavior);
|
||||
}
|
||||
|
||||
Vector<String> String::split_limit(char separator, size_t limit, bool keep_empty) const
|
||||
Vector<String> String::split_limit(char separator, size_t limit, SplitBehavior split_behavior) const
|
||||
{
|
||||
if (is_empty())
|
||||
return {};
|
||||
|
||||
Vector<String> v;
|
||||
size_t substart = 0;
|
||||
bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty);
|
||||
for (size_t i = 0; i < length() && (v.size() + 1) != limit; ++i) {
|
||||
char ch = characters()[i];
|
||||
if (ch == separator) {
|
||||
|
@ -124,13 +125,14 @@ Vector<String> String::split_limit(char separator, size_t limit, bool keep_empty
|
|||
return v;
|
||||
}
|
||||
|
||||
Vector<StringView> String::split_view(Function<bool(char)> separator, bool keep_empty) const
|
||||
Vector<StringView> String::split_view(Function<bool(char)> separator, SplitBehavior split_behavior) const
|
||||
{
|
||||
if (is_empty())
|
||||
return {};
|
||||
|
||||
Vector<StringView> v;
|
||||
size_t substart = 0;
|
||||
bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty);
|
||||
for (size_t i = 0; i < length(); ++i) {
|
||||
char ch = characters()[i];
|
||||
if (separator(ch)) {
|
||||
|
@ -146,9 +148,9 @@ Vector<StringView> String::split_view(Function<bool(char)> separator, bool keep_
|
|||
return v;
|
||||
}
|
||||
|
||||
Vector<StringView> String::split_view(char const separator, bool keep_empty) const
|
||||
Vector<StringView> String::split_view(char const separator, SplitBehavior split_behavior) const
|
||||
{
|
||||
return split_view([separator](char ch) { return ch == separator; }, keep_empty);
|
||||
return split_view([separator](char ch) { return ch == separator; }, split_behavior);
|
||||
}
|
||||
|
||||
ByteBuffer String::to_byte_buffer() const
|
||||
|
|
|
@ -150,10 +150,10 @@ public:
|
|||
[[nodiscard]] bool contains(StringView, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
|
||||
[[nodiscard]] bool contains(char, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
|
||||
|
||||
[[nodiscard]] Vector<String> split_limit(char separator, size_t limit, bool keep_empty = false) const;
|
||||
[[nodiscard]] Vector<String> split(char separator, bool keep_empty = false) const;
|
||||
[[nodiscard]] Vector<StringView> split_view(char separator, bool keep_empty = false) const;
|
||||
[[nodiscard]] Vector<StringView> split_view(Function<bool(char)> separator, bool keep_empty = false) const;
|
||||
[[nodiscard]] Vector<String> split_limit(char separator, size_t limit, SplitBehavior = SplitBehavior::Nothing) const;
|
||||
[[nodiscard]] Vector<String> split(char separator, SplitBehavior = SplitBehavior::Nothing) const;
|
||||
[[nodiscard]] Vector<StringView> split_view(char separator, SplitBehavior = SplitBehavior::Nothing) const;
|
||||
[[nodiscard]] Vector<StringView> split_view(Function<bool(char)> separator, SplitBehavior = SplitBehavior::Nothing) const;
|
||||
|
||||
[[nodiscard]] Optional<size_t> find(char needle, size_t start = 0) const { return StringUtils::find(*this, needle, start); }
|
||||
[[nodiscard]] Optional<size_t> find(StringView needle, size_t start = 0) const { return StringUtils::find(*this, needle, start); }
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Concepts.h>
|
||||
#include <AK/EnumBits.h>
|
||||
#include <AK/Forward.h>
|
||||
|
||||
namespace AK {
|
||||
|
@ -38,6 +39,14 @@ enum class TrimWhitespace {
|
|||
No,
|
||||
};
|
||||
|
||||
enum class SplitBehavior : unsigned {
|
||||
Nothing = 0,
|
||||
// If two separators follow each other without any characters
|
||||
// in between, keep a "" in the resulting vector.
|
||||
KeepEmpty = 1,
|
||||
};
|
||||
AK_ENUM_BITWISE_OPERATORS(SplitBehavior);
|
||||
|
||||
struct MaskSpan {
|
||||
size_t start;
|
||||
size_t length;
|
||||
|
@ -99,5 +108,6 @@ size_t count(StringView, StringView needle);
|
|||
|
||||
using AK::CaseSensitivity;
|
||||
using AK::ReplaceMode;
|
||||
using AK::SplitBehavior;
|
||||
using AK::TrimMode;
|
||||
using AK::TrimWhitespace;
|
||||
|
|
|
@ -40,16 +40,16 @@ StringView::StringView(ByteBuffer const& buffer)
|
|||
{
|
||||
}
|
||||
|
||||
Vector<StringView> StringView::split_view(char const separator, bool keep_empty) const
|
||||
Vector<StringView> StringView::split_view(char const separator, SplitBehavior split_behavior) const
|
||||
{
|
||||
StringView seperator_view { &separator, 1 };
|
||||
return split_view(seperator_view, keep_empty);
|
||||
return split_view(seperator_view, split_behavior);
|
||||
}
|
||||
|
||||
Vector<StringView> StringView::split_view(StringView separator, bool keep_empty) const
|
||||
Vector<StringView> StringView::split_view(StringView separator, SplitBehavior split_behavior) const
|
||||
{
|
||||
Vector<StringView> parts;
|
||||
for_each_split_view(separator, keep_empty, [&](StringView view) {
|
||||
for_each_split_view(separator, split_behavior, [&](StringView view) {
|
||||
parts.append(view);
|
||||
});
|
||||
return parts;
|
||||
|
@ -61,7 +61,7 @@ Vector<StringView> StringView::lines(bool consider_cr) const
|
|||
return {};
|
||||
|
||||
if (!consider_cr)
|
||||
return split_view('\n', true);
|
||||
return split_view('\n', SplitBehavior::KeepEmpty);
|
||||
|
||||
Vector<StringView> v;
|
||||
size_t substart = 0;
|
||||
|
@ -264,13 +264,14 @@ Vector<size_t> StringView::find_all(StringView needle) const
|
|||
return StringUtils::find_all(*this, needle);
|
||||
}
|
||||
|
||||
Vector<StringView> StringView::split_view_if(Function<bool(char)> const& predicate, bool keep_empty) const
|
||||
Vector<StringView> StringView::split_view_if(Function<bool(char)> const& predicate, SplitBehavior split_behavior) const
|
||||
{
|
||||
if (is_empty())
|
||||
return {};
|
||||
|
||||
Vector<StringView> v;
|
||||
size_t substart = 0;
|
||||
bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty);
|
||||
for (size_t i = 0; i < length(); ++i) {
|
||||
char ch = characters_without_null_termination()[i];
|
||||
if (predicate(ch)) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/Checked.h>
|
||||
#include <AK/EnumBits.h>
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/Span.h>
|
||||
|
@ -129,10 +130,10 @@ public:
|
|||
return substring_view(start, length() - start);
|
||||
}
|
||||
|
||||
[[nodiscard]] Vector<StringView> split_view(char, bool keep_empty = false) const;
|
||||
[[nodiscard]] Vector<StringView> split_view(StringView, bool keep_empty = false) const;
|
||||
[[nodiscard]] Vector<StringView> split_view(char, SplitBehavior = SplitBehavior::Nothing) const;
|
||||
[[nodiscard]] Vector<StringView> split_view(StringView, SplitBehavior = SplitBehavior::Nothing) const;
|
||||
|
||||
[[nodiscard]] Vector<StringView> split_view_if(Function<bool(char)> const& predicate, bool keep_empty = false) const;
|
||||
[[nodiscard]] Vector<StringView> split_view_if(Function<bool(char)> const& predicate, SplitBehavior = SplitBehavior::Nothing) const;
|
||||
|
||||
[[nodiscard]] StringView find_last_split_view(char separator) const
|
||||
{
|
||||
|
@ -151,14 +152,14 @@ public:
|
|||
}
|
||||
|
||||
template<VoidFunction<StringView> Callback>
|
||||
void for_each_split_view(char separator, bool keep_empty, Callback callback) const
|
||||
void for_each_split_view(char separator, SplitBehavior split_behavior, Callback callback) const
|
||||
{
|
||||
StringView seperator_view { &separator, 1 };
|
||||
for_each_split_view(seperator_view, keep_empty, callback);
|
||||
for_each_split_view(seperator_view, split_behavior, callback);
|
||||
}
|
||||
|
||||
template<VoidFunction<StringView> Callback>
|
||||
void for_each_split_view(StringView separator, bool keep_empty, Callback callback) const
|
||||
void for_each_split_view(StringView separator, SplitBehavior split_behavior, Callback callback) const
|
||||
{
|
||||
VERIFY(!separator.is_empty());
|
||||
|
||||
|
@ -168,6 +169,7 @@ public:
|
|||
StringView view { *this };
|
||||
|
||||
auto maybe_separator_index = find(separator);
|
||||
bool keep_empty = has_flag(split_behavior, SplitBehavior::KeepEmpty);
|
||||
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());
|
||||
|
|
|
@ -65,7 +65,7 @@ UNMAP_AFTER_INIT void CommandLine::add_arguments(Vector<StringView> const& args)
|
|||
continue;
|
||||
}
|
||||
|
||||
auto pair = str.split_view('=', false);
|
||||
auto pair = str.split_view('=');
|
||||
VERIFY(pair.size() == 2 || pair.size() == 1);
|
||||
|
||||
if (pair.size() == 1) {
|
||||
|
|
|
@ -642,7 +642,7 @@ private:
|
|||
TRY(obj.add("hypervisor_vendor_id"sv, info.hypervisor_vendor_id_string()));
|
||||
|
||||
auto features_array = TRY(obj.add_array("features"sv));
|
||||
auto keep_empty = false;
|
||||
auto keep_empty = SplitBehavior::KeepEmpty;
|
||||
|
||||
ErrorOr<void> result; // FIXME: Make this nicer
|
||||
info.features_string().for_each_split_view(' ', keep_empty, [&](StringView feature) {
|
||||
|
|
|
@ -213,7 +213,7 @@ UNMAP_AFTER_INIT Array<unsigned, 3> StorageManagement::extract_boot_device_addre
|
|||
auto parameters_view = m_boot_argument.substring_view(device_prefix.length()).find_first_split_view(';');
|
||||
size_t parts_count = 0;
|
||||
bool parse_failure = false;
|
||||
parameters_view.for_each_split_view(':', false, [&](StringView parameter_view) {
|
||||
parameters_view.for_each_split_view(':', SplitBehavior::Nothing, [&](StringView parameter_view) {
|
||||
if (parse_failure)
|
||||
return;
|
||||
if (parts_count > 2)
|
||||
|
|
|
@ -29,7 +29,7 @@ ErrorOr<FlatPtr> Process::sys$pledge(Userspace<Syscall::SC_pledge_params const*>
|
|||
|
||||
auto parse_pledge = [&](auto pledge_spec, u32& mask) {
|
||||
auto found_invalid_pledge = true;
|
||||
pledge_spec.for_each_split_view(' ', false, [&mask, &found_invalid_pledge](auto const& part) {
|
||||
pledge_spec.for_each_split_view(' ', SplitBehavior::Nothing, [&mask, &found_invalid_pledge](auto const& part) {
|
||||
#define __ENUMERATE_PLEDGE_PROMISE(x) \
|
||||
if (part == #x##sv) { \
|
||||
mask |= (1u << (u32)Pledge::x); \
|
||||
|
|
|
@ -91,7 +91,7 @@ static ErrorOr<String> decode_html_entities(StringView const& str)
|
|||
|
||||
static ErrorOr<ApprovalDate> parse_approval_date(StringView const& str)
|
||||
{
|
||||
auto parts = str.trim_whitespace().split_view('/', true);
|
||||
auto parts = str.trim_whitespace().split_view('/', SplitBehavior::KeepEmpty);
|
||||
if (parts.size() != 3)
|
||||
return Error::from_string_literal("Failed to parse approval date parts (mm/dd/yyyy)");
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ static Relation parse_relation(StringView relation)
|
|||
parsed.symbol = lhs[0];
|
||||
}
|
||||
|
||||
rhs.for_each_split_view(set_operator, false, [&](auto set) {
|
||||
rhs.for_each_split_view(set_operator, SplitBehavior::Nothing, [&](auto set) {
|
||||
if (auto index = set.find(range_operator); index.has_value()) {
|
||||
auto range_begin = set.substring_view(0, *index).to_uint();
|
||||
VERIFY(range_begin.has_value());
|
||||
|
@ -313,10 +313,10 @@ static void parse_condition(StringView category, StringView rule, Conditions& ru
|
|||
// and_condition = relation ('and' relation)*
|
||||
//
|
||||
// This affords some simplicity in that disjunctions are never embedded within a conjunction.
|
||||
condition.for_each_split_view(disjunction_keyword, false, [&](auto disjunction) {
|
||||
condition.for_each_split_view(disjunction_keyword, SplitBehavior::Nothing, [&](auto disjunction) {
|
||||
Vector<Relation> conjunctions;
|
||||
|
||||
disjunction.for_each_split_view(conjunction_keyword, false, [&](auto relation) {
|
||||
disjunction.for_each_split_view(conjunction_keyword, SplitBehavior::Nothing, [&](auto relation) {
|
||||
conjunctions.append(parse_relation(relation));
|
||||
});
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ static ErrorOr<void> parse_time_zone_coordinates(Core::Stream::BufferedFile& fil
|
|||
|
||||
time_zone_data.time_zone_coordinates.set(zone, { latitude, longitude });
|
||||
|
||||
regions.for_each_split_view(',', false, [&](auto region) {
|
||||
regions.for_each_split_view(',', SplitBehavior::Nothing, [&](auto region) {
|
||||
auto index = time_zone_data.unique_strings.ensure(zone);
|
||||
time_zone_data.time_zone_regions.ensure(region).append(index);
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ static ErrorOr<void> parse_emoji_serenity_data(Core::Stream::BufferedFile& file,
|
|||
emoji.group = Unicode::EmojiGroup::SerenityOS;
|
||||
emoji.display_order = display_order++;
|
||||
|
||||
line.for_each_split_view(' ', false, [&](auto segment) {
|
||||
line.for_each_split_view(' ', SplitBehavior::Nothing, [&](auto segment) {
|
||||
if (segment.starts_with(code_point_header)) {
|
||||
segment = segment.substring_view(code_point_header.length());
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ static ErrorOr<void> parse_special_casing(Core::Stream::BufferedFile& file, Unic
|
|||
if (auto index = line.find('#'); index.has_value())
|
||||
line = line.substring_view(0, *index);
|
||||
|
||||
auto segments = line.split_view(';', true);
|
||||
auto segments = line.split_view(';', SplitBehavior::KeepEmpty);
|
||||
VERIFY(segments.size() == 5 || segments.size() == 6);
|
||||
|
||||
SpecialCasing casing {};
|
||||
|
@ -233,7 +233,7 @@ static ErrorOr<void> parse_special_casing(Core::Stream::BufferedFile& file, Unic
|
|||
casing.uppercase_mapping = parse_code_point_list(segments[3]);
|
||||
|
||||
if (auto condition = segments[4].trim_whitespace(); !condition.is_empty()) {
|
||||
auto conditions = condition.split_view(' ', true);
|
||||
auto conditions = condition.split_view(' ', SplitBehavior::KeepEmpty);
|
||||
VERIFY(conditions.size() == 1 || conditions.size() == 2);
|
||||
|
||||
if (conditions.size() == 2) {
|
||||
|
@ -294,7 +294,7 @@ static ErrorOr<void> parse_prop_list(Core::Stream::BufferedFile& file, PropList&
|
|||
if (auto index = line.find('#'); index.has_value())
|
||||
line = line.substring_view(0, *index);
|
||||
|
||||
auto segments = line.split_view(';', true);
|
||||
auto segments = line.split_view(';', SplitBehavior::KeepEmpty);
|
||||
VERIFY(segments.size() == 2);
|
||||
|
||||
auto code_point_range = parse_code_point_range(segments[0].trim_whitespace());
|
||||
|
@ -344,7 +344,7 @@ static ErrorOr<void> parse_alias_list(Core::Stream::BufferedFile& file, PropList
|
|||
if (current_property != "Binary Properties"sv)
|
||||
continue;
|
||||
|
||||
auto segments = line.split_view(';', true);
|
||||
auto segments = line.split_view(';', SplitBehavior::KeepEmpty);
|
||||
VERIFY((segments.size() == 2) || (segments.size() == 3));
|
||||
|
||||
auto alias = segments[0].trim_whitespace();
|
||||
|
@ -370,7 +370,7 @@ static ErrorOr<void> parse_name_aliases(Core::Stream::BufferedFile& file, Unicod
|
|||
if (line.is_empty() || line.starts_with('#'))
|
||||
continue;
|
||||
|
||||
auto segments = line.split_view(';', true);
|
||||
auto segments = line.split_view(';', SplitBehavior::KeepEmpty);
|
||||
VERIFY(segments.size() == 3);
|
||||
|
||||
auto code_point = AK::StringUtils::convert_to_uint_from_hex<u32>(segments[0].trim_whitespace());
|
||||
|
@ -417,7 +417,7 @@ static ErrorOr<void> parse_value_alias_list(Core::Stream::BufferedFile& file, St
|
|||
if (auto index = line.find('#'); index.has_value())
|
||||
line = line.substring_view(0, *index);
|
||||
|
||||
auto segments = line.split_view(';', true);
|
||||
auto segments = line.split_view(';', SplitBehavior::KeepEmpty);
|
||||
auto category = segments[0].trim_whitespace();
|
||||
|
||||
if (category != desired_category)
|
||||
|
@ -450,7 +450,7 @@ static ErrorOr<void> parse_normalization_props(Core::Stream::BufferedFile& file,
|
|||
if (auto index = line.find('#'); index.has_value())
|
||||
line = line.substring_view(0, *index);
|
||||
|
||||
auto segments = line.split_view(';', true);
|
||||
auto segments = line.split_view(';', SplitBehavior::KeepEmpty);
|
||||
VERIFY((segments.size() == 2) || (segments.size() == 3));
|
||||
|
||||
auto code_point_range = parse_code_point_range(segments[0].trim_whitespace());
|
||||
|
@ -579,7 +579,7 @@ static ErrorOr<void> parse_block_display_names(Core::Stream::BufferedFile& file,
|
|||
if (line.is_empty() || line.starts_with('#'))
|
||||
continue;
|
||||
|
||||
auto segments = line.split_view(';', true);
|
||||
auto segments = line.split_view(';', SplitBehavior::KeepEmpty);
|
||||
VERIFY(segments.size() == 2);
|
||||
|
||||
auto code_point_range = parse_code_point_range(segments[0].trim_whitespace());
|
||||
|
@ -610,7 +610,7 @@ static ErrorOr<void> parse_unicode_data(Core::Stream::BufferedFile& file, Unicod
|
|||
if (line.is_empty())
|
||||
continue;
|
||||
|
||||
auto segments = line.split_view(';', true);
|
||||
auto segments = line.split_view(';', SplitBehavior::KeepEmpty);
|
||||
VERIFY(segments.size() == 15);
|
||||
|
||||
CodePointData data {};
|
||||
|
|
|
@ -195,7 +195,7 @@ static Result<Vector<String>, int> run_whiptail(WhiptailMode mode, Vector<Whipta
|
|||
auto file = Core::File::construct();
|
||||
file->open(read_fd, Core::OpenMode::ReadOnly, Core::File::ShouldCloseFileDescriptor::Yes);
|
||||
auto data = String::copy(file->read_all());
|
||||
return data.split('\n', false);
|
||||
return data.split('\n');
|
||||
}
|
||||
|
||||
static bool run_system_command(String const& command, StringView command_name)
|
||||
|
|
|
@ -233,7 +233,7 @@ TEST_CASE(split)
|
|||
EXPECT_EQ(parts[0], "a");
|
||||
EXPECT_EQ(parts[1], "b");
|
||||
|
||||
parts = test.split(' ', true);
|
||||
parts = test.split(' ', SplitBehavior::KeepEmpty);
|
||||
EXPECT_EQ(parts.size(), 5u);
|
||||
EXPECT_EQ(parts[0], "a");
|
||||
EXPECT_EQ(parts[1], "");
|
||||
|
@ -243,9 +243,9 @@ TEST_CASE(split)
|
|||
|
||||
test = "axxbx";
|
||||
EXPECT_EQ(test.split('x').size(), 2u);
|
||||
EXPECT_EQ(test.split('x', true).size(), 4u);
|
||||
EXPECT_EQ(test.split('x', SplitBehavior::KeepEmpty).size(), 4u);
|
||||
EXPECT_EQ(test.split_view('x').size(), 2u);
|
||||
EXPECT_EQ(test.split_view('x', true).size(), 4u);
|
||||
EXPECT_EQ(test.split_view('x', SplitBehavior::KeepEmpty).size(), 4u);
|
||||
}
|
||||
|
||||
TEST_CASE(builder_zero_initial_capacity)
|
||||
|
|
|
@ -143,26 +143,26 @@ TEST_CASE(split_view)
|
|||
{
|
||||
StringView test_string_view = "axxbxcxd"sv;
|
||||
EXPECT_EQ(test_string_view.split_view('x'), Vector({ "a"sv, "b"sv, "c"sv, "d"sv }));
|
||||
EXPECT_EQ(test_string_view.split_view('x', true), Vector({ "a"sv, ""sv, "b"sv, "c"sv, "d"sv }));
|
||||
EXPECT_EQ(test_string_view.split_view('x', SplitBehavior::KeepEmpty), Vector({ "a"sv, ""sv, "b"sv, "c"sv, "d"sv }));
|
||||
EXPECT_EQ(test_string_view.split_view("x"sv), Vector({ "a"sv, "b"sv, "c"sv, "d"sv }));
|
||||
EXPECT_EQ(test_string_view.split_view("x"sv, true), Vector({ "a"sv, ""sv, "b"sv, "c"sv, "d"sv }));
|
||||
EXPECT_EQ(test_string_view.split_view("x"sv, SplitBehavior::KeepEmpty), Vector({ "a"sv, ""sv, "b"sv, "c"sv, "d"sv }));
|
||||
|
||||
test_string_view = "axxbx"sv;
|
||||
EXPECT_EQ(test_string_view.split_view('x'), Vector({ "a"sv, "b"sv }));
|
||||
EXPECT_EQ(test_string_view.split_view('x', true), Vector({ "a"sv, ""sv, "b"sv, ""sv }));
|
||||
EXPECT_EQ(test_string_view.split_view('x', SplitBehavior::KeepEmpty), Vector({ "a"sv, ""sv, "b"sv, ""sv }));
|
||||
EXPECT_EQ(test_string_view.split_view("x"sv), Vector({ "a"sv, "b"sv }));
|
||||
EXPECT_EQ(test_string_view.split_view("x"sv, true), Vector({ "a"sv, ""sv, "b"sv, ""sv }));
|
||||
EXPECT_EQ(test_string_view.split_view("x"sv, SplitBehavior::KeepEmpty), Vector({ "a"sv, ""sv, "b"sv, ""sv }));
|
||||
|
||||
test_string_view = "axxbcxxdxx"sv;
|
||||
EXPECT_EQ(test_string_view.split_view("xx"sv), Vector({ "a"sv, "bc"sv, "d"sv }));
|
||||
EXPECT_EQ(test_string_view.split_view("xx"sv, true), Vector({ "a"sv, "bc"sv, "d"sv, ""sv }));
|
||||
EXPECT_EQ(test_string_view.split_view("xx"sv, SplitBehavior::KeepEmpty), Vector({ "a"sv, "bc"sv, "d"sv, ""sv }));
|
||||
|
||||
test_string_view = "ax_b_cxd"sv;
|
||||
Function<bool(char)> predicate = [](char ch) { return ch == 'x' || ch == '_'; };
|
||||
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, true), Vector({ "a"sv, ""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 }));
|
||||
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, true), Vector({ "a"sv, ""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_CASE(constexpr_stuff)
|
||||
|
|
|
@ -87,7 +87,7 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
|
|||
auto normal_indices = FixedArray<GLuint>::must_create_but_fixme_should_propagate_errors(number_of_vertices);
|
||||
|
||||
for (size_t i = 0; i < number_of_vertices; ++i) {
|
||||
auto vertex_parts = face_line.at(i).split_view('/', true);
|
||||
auto vertex_parts = face_line.at(i).split_view('/', SplitBehavior::KeepEmpty);
|
||||
vertex_indices[i] = get_index_value(vertex_parts[0]);
|
||||
tex_coord_indices[i] = (vertex_parts.size() >= 2) ? get_index_value(vertex_parts[1]) : 0;
|
||||
normal_indices[i] = (vertex_parts.size() >= 3) ? get_index_value(vertex_parts[2]) : 0;
|
||||
|
|
|
@ -343,7 +343,7 @@ void Emulator::handle_repl()
|
|||
line = m_editor->history().last().entry;
|
||||
}
|
||||
|
||||
auto parts = line.split_view(' ', false);
|
||||
auto parts = line.split_view(' ');
|
||||
m_editor->add_to_history(line);
|
||||
|
||||
if (parts[0].is_one_of("s"sv, "step"sv)) {
|
||||
|
|
|
@ -138,7 +138,7 @@ int OptionParser::getopt()
|
|||
|
||||
bool OptionParser::lookup_short_option(char option, int& needs_value) const
|
||||
{
|
||||
Vector<StringView> parts = m_short_options.split_view(option, true);
|
||||
Vector<StringView> parts = m_short_options.split_view(option, SplitBehavior::KeepEmpty);
|
||||
|
||||
VERIFY(parts.size() <= 2);
|
||||
if (parts.size() < 2) {
|
||||
|
|
|
@ -73,7 +73,7 @@ struct group* getgrnam(char const* name)
|
|||
|
||||
static bool parse_grpdb_entry(String const& line)
|
||||
{
|
||||
auto parts = line.split_view(':', true);
|
||||
auto parts = line.split_view(':', SplitBehavior::KeepEmpty);
|
||||
if (parts.size() != 4) {
|
||||
warnln("getgrent(): Malformed entry on line {}: '{}' has {} parts", s_line_number, line, parts.size());
|
||||
return false;
|
||||
|
|
|
@ -73,7 +73,7 @@ struct passwd* getpwnam(char const* name)
|
|||
|
||||
static bool parse_pwddb_entry(String const& line)
|
||||
{
|
||||
auto parts = line.split_view(':', true);
|
||||
auto parts = line.split_view(':', SplitBehavior::KeepEmpty);
|
||||
if (parts.size() != 7) {
|
||||
dbgln("getpwent(): Malformed entry on line {}", s_line_number);
|
||||
return false;
|
||||
|
|
|
@ -64,7 +64,7 @@ struct spwd* getspnam(char const* name)
|
|||
|
||||
static bool parse_shadow_entry(String const& line)
|
||||
{
|
||||
auto parts = line.split_view(':', true);
|
||||
auto parts = line.split_view(':', SplitBehavior::KeepEmpty);
|
||||
if (parts.size() != 9) {
|
||||
dbgln("getspent(): Malformed entry on line {}", s_line_number);
|
||||
return false;
|
||||
|
|
|
@ -117,7 +117,7 @@ size_t ShellComprehensionEngine::resolve(ShellComprehensionEngine::DocumentData
|
|||
if (position.line() > 0) {
|
||||
auto first = true;
|
||||
size_t line = 0;
|
||||
for (auto& line_view : document.text.split_limit('\n', position.line() + 1, true)) {
|
||||
for (auto& line_view : document.text.split_limit('\n', position.line() + 1, SplitBehavior::KeepEmpty)) {
|
||||
if (line == position.line())
|
||||
break;
|
||||
if (first)
|
||||
|
|
|
@ -554,7 +554,7 @@ void ArgsParser::add_option(Vector<size_t>& values, char const* help_string, cha
|
|||
[&values, separator](char const* s) {
|
||||
bool parsed_all_values = true;
|
||||
|
||||
StringView { s, strlen(s) }.for_each_split_view(separator, false, [&](auto value) {
|
||||
StringView { s, strlen(s) }.for_each_split_view(separator, SplitBehavior::Nothing, [&](auto value) {
|
||||
if (auto maybe_value = AK::StringUtils::convert_to_uint<size_t>(value); maybe_value.has_value())
|
||||
values.append(*maybe_value);
|
||||
else
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
namespace Diff {
|
||||
String generate_only_additions(String const& text)
|
||||
{
|
||||
auto lines = text.split('\n', true); // Keep empty
|
||||
auto lines = text.split('\n', SplitBehavior::KeepEmpty);
|
||||
StringBuilder builder;
|
||||
builder.appendff("@@ -0,0 +1,{} @@\n", lines.size());
|
||||
for (auto const& line : lines) {
|
||||
|
|
|
@ -179,7 +179,7 @@ auto EmojiInputDialog::supported_emoji() -> Vector<Emoji>
|
|||
StringBuilder builder;
|
||||
Vector<u32> code_points;
|
||||
|
||||
basename.for_each_split_view('_', false, [&](auto segment) {
|
||||
basename.for_each_split_view('_', SplitBehavior::Nothing, [&](auto segment) {
|
||||
auto code_point = AK::StringUtils::convert_to_uint_from_hex<u32>(segment.substring_view(2));
|
||||
VERIFY(code_point.has_value());
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ Optional<HttpRequest> HttpRequest::from_raw_request(ReadonlyBytes raw_request)
|
|||
return {};
|
||||
|
||||
request.m_headers = move(headers);
|
||||
auto url_parts = resource.split_limit('?', 2, true);
|
||||
auto url_parts = resource.split_limit('?', 2, SplitBehavior::KeepEmpty);
|
||||
|
||||
request.m_url.set_cannot_be_a_base_url(true);
|
||||
if (url_parts.size() == 2) {
|
||||
|
|
|
@ -453,7 +453,7 @@ void Job::on_socket_connected()
|
|||
finish_up();
|
||||
break;
|
||||
} else {
|
||||
auto chunk = size_lines[0].split_view(';', true);
|
||||
auto chunk = size_lines[0].split_view(';', SplitBehavior::KeepEmpty);
|
||||
String size_string = chunk[0];
|
||||
char* endptr;
|
||||
auto size = strtoul(size_string.characters(), &endptr, 16);
|
||||
|
|
|
@ -192,7 +192,7 @@ public:
|
|||
// line terminators to \n is easier than splitting using all different LT characters.
|
||||
String source_string = source.replace("\r\n"sv, "\n"sv, ReplaceMode::All).replace("\r"sv, "\n"sv, ReplaceMode::All).replace(LINE_SEPARATOR_STRING, "\n"sv, ReplaceMode::All).replace(PARAGRAPH_SEPARATOR_STRING, "\n"sv, ReplaceMode::All);
|
||||
StringBuilder builder;
|
||||
builder.append(source_string.split_view('\n', true)[position.value().line - 1]);
|
||||
builder.append(source_string.split_view('\n', SplitBehavior::KeepEmpty)[position.value().line - 1]);
|
||||
builder.append('\n');
|
||||
for (size_t i = 0; i < position.value().column - 1; ++i)
|
||||
builder.append(spacer);
|
||||
|
|
|
@ -965,7 +965,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
|
|||
|
||||
// 19. Repeat, while q < size,
|
||||
while (next_search_from < string.length_in_code_units()) {
|
||||
// a. Perform ? Set(splitter, "lastIndex", 𝔽(q), true).
|
||||
// a. Perform ? Set(splitter, "lastIndex", 𝔽(q), SplitBehavior::KeepEmpty).
|
||||
TRY(splitter->set(vm.names.lastIndex, Value(next_search_from), Object::ShouldThrowExceptions::Yes));
|
||||
|
||||
// b. Let z be ? RegExpExec(splitter, S).
|
||||
|
|
|
@ -138,8 +138,8 @@ OwnPtr<Table> Table::parse(LineIterator& lines)
|
|||
if (peek_it.is_end())
|
||||
return {};
|
||||
|
||||
auto header_segments = first_line.split_view('|', true);
|
||||
auto header_delimiters = peek_it->split_view('|', true);
|
||||
auto header_segments = first_line.split_view('|', SplitBehavior::KeepEmpty);
|
||||
auto header_delimiters = peek_it->split_view('|', SplitBehavior::KeepEmpty);
|
||||
|
||||
if (!header_segments.is_empty())
|
||||
header_segments.take_first();
|
||||
|
@ -214,7 +214,7 @@ OwnPtr<Table> Table::parse(LineIterator& lines)
|
|||
|
||||
++lines;
|
||||
|
||||
auto segments = line.split_view('|', true);
|
||||
auto segments = line.split_view('|', SplitBehavior::KeepEmpty);
|
||||
segments.take_first();
|
||||
if (!segments.is_empty() && segments.last().is_empty())
|
||||
segments.take_last();
|
||||
|
|
|
@ -522,7 +522,7 @@ inline void TestRunner::print_file_result(JSFileResult const& file_result) const
|
|||
#endif
|
||||
outln();
|
||||
print_modifiers({ FG_GRAY });
|
||||
for (auto& message : test_error.hint.split('\n', true)) {
|
||||
for (auto& message : test_error.hint.split('\n', SplitBehavior::KeepEmpty)) {
|
||||
outln(" {}", message);
|
||||
}
|
||||
print_modifiers({ FG_RED });
|
||||
|
|
|
@ -96,7 +96,7 @@ void LookupServer::load_etc_hosts()
|
|||
break;
|
||||
auto trimmed_line = original_line.view().trim_whitespace();
|
||||
auto replaced_line = trimmed_line.replace(" "sv, "\t"sv, ReplaceMode::All);
|
||||
auto fields = replaced_line.split_view('\t', false);
|
||||
auto fields = replaced_line.split_view('\t');
|
||||
|
||||
if (fields.size() < 2) {
|
||||
dbgln("Failed to parse line {} from '/etc/hosts': '{}'", line_number, original_line);
|
||||
|
|
|
@ -252,7 +252,7 @@ ErrorOr<Client::RoutingResult, WebDriverError> Client::match_route(HTTP::HttpReq
|
|||
if (!resource.starts_with(m_prefix))
|
||||
return WebDriverError::from_code(ErrorCode::UnknownCommand, "The resource doesn't start with the prefix.");
|
||||
|
||||
Vector<StringView> resource_split = resource.substring_view(m_prefix.length()).split_view('/', true);
|
||||
Vector<StringView> resource_split = resource.substring_view(m_prefix.length()).split_view('/', SplitBehavior::KeepEmpty);
|
||||
Vector<StringView> parameters;
|
||||
|
||||
bool matched_path = false;
|
||||
|
|
|
@ -3577,7 +3577,7 @@ String StringValue::resolve_as_string(RefPtr<Shell> shell)
|
|||
Vector<String> StringValue::resolve_as_list(RefPtr<Shell> shell)
|
||||
{
|
||||
if (is_list()) {
|
||||
auto parts = StringView(m_string).split_view(m_split, m_keep_empty);
|
||||
auto parts = StringView(m_string).split_view(m_split, m_keep_empty ? SplitBehavior::KeepEmpty : SplitBehavior::Nothing);
|
||||
Vector<String> result;
|
||||
result.ensure_capacity(parts.size());
|
||||
for (auto& part : parts)
|
||||
|
|
|
@ -57,7 +57,7 @@ int Shell::builtin_alias(int argc, char const** argv)
|
|||
|
||||
bool fail = false;
|
||||
for (auto& argument : arguments) {
|
||||
auto parts = argument.split_limit('=', 2, true);
|
||||
auto parts = argument.split_limit('=', 2, SplitBehavior::KeepEmpty);
|
||||
if (parts.size() == 1) {
|
||||
auto alias = m_aliases.get(parts[0]);
|
||||
if (alias.has_value()) {
|
||||
|
|
|
@ -349,7 +349,7 @@ RefPtr<AST::Node> Shell::immediate_split(AST::ImmediateExpression& invoking_node
|
|||
builder.clear();
|
||||
}
|
||||
} else {
|
||||
auto split = StringView { value }.split_view(delimiter_str, options.inline_exec_keep_empty_segments);
|
||||
auto split = StringView { value }.split_view(delimiter_str, options.inline_exec_keep_empty_segments ? SplitBehavior::KeepEmpty : SplitBehavior::Nothing);
|
||||
split_strings.ensure_capacity(split.size());
|
||||
for (auto& entry : split)
|
||||
split_strings.append(entry);
|
||||
|
|
|
@ -39,7 +39,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
uid_t new_uid = -1;
|
||||
gid_t new_gid = -1;
|
||||
|
||||
auto parts = spec.split_view(':', true);
|
||||
auto parts = spec.split_view(':', SplitBehavior::KeepEmpty);
|
||||
if (parts[0].is_empty() || (parts.size() == 2 && parts[1].is_empty()) || parts.size() > 2) {
|
||||
warnln("Invalid uid/gid spec");
|
||||
return 1;
|
||||
|
|
|
@ -39,7 +39,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
|
||||
bool values_ok = true;
|
||||
|
||||
StringView { s, strlen(s) }.for_each_split_view(',', false, [&](StringView value) {
|
||||
StringView { s, strlen(s) }.for_each_split_view(',', SplitBehavior::Nothing, [&](StringView value) {
|
||||
if (value == "mode"sv) {
|
||||
preserve |= Core::File::PreserveMode::Permissions;
|
||||
} else if (value == "ownership"sv) {
|
||||
|
|
|
@ -38,7 +38,7 @@ enum Status {
|
|||
|
||||
static StringView split_at_equals(StringView argument)
|
||||
{
|
||||
auto values = argument.split_view('=', true);
|
||||
auto values = argument.split_view('=', SplitBehavior::KeepEmpty);
|
||||
if (values.size() < 2) {
|
||||
warnln("Unable to parse: {}", argument);
|
||||
return {};
|
||||
|
|
|
@ -730,7 +730,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
if (maybe_section.has_value()) {
|
||||
outln("String dump of section \'{}\':", string_dump_section);
|
||||
StringView data(maybe_section->raw_data(), maybe_section->size());
|
||||
data.for_each_split_view('\0', false, [&data](auto string) {
|
||||
data.for_each_split_view('\0', SplitBehavior::Nothing, [&data](auto string) {
|
||||
auto offset = string.characters_without_null_termination() - data.characters_without_null_termination();
|
||||
outln("[{:6x}] {}", offset, string);
|
||||
});
|
||||
|
|
|
@ -245,7 +245,7 @@ ParsedInitialArguments::ParsedInitialArguments(Vector<String>& arguments, String
|
|||
if (placeholder.is_empty()) {
|
||||
m_all_parts.append({ arg });
|
||||
} else {
|
||||
auto parts = arg.view().split_view(placeholder, true);
|
||||
auto parts = arg.view().split_view(placeholder, SplitBehavior::KeepEmpty);
|
||||
some_argument_has_placeholder = some_argument_has_placeholder || parts.size() > 1;
|
||||
m_all_parts.append(move(parts));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue