AK+Everywhere: Turn bool keep_empty to an enum in split* functions

This commit is contained in:
demostanis 2022-10-22 15:38:21 +02:00 committed by Linus Groh
parent f485db2501
commit 3e8b5ac920
Notes: sideshowbarker 2024-07-17 07:09:53 +09:00
44 changed files with 96 additions and 81 deletions

View file

@ -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) {

View file

@ -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

View file

@ -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); }

View file

@ -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;

View file

@ -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)) {

View file

@ -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());

View file

@ -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) {

View file

@ -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) {

View file

@ -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)

View file

@ -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); \

View file

@ -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)");

View file

@ -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));
});

View file

@ -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);

View file

@ -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());

View file

@ -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 {};

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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;

View file

@ -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)) {

View file

@ -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) {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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) {

View file

@ -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());

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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).

View file

@ -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();

View file

@ -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 });

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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()) {

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -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 {};

View file

@ -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);
});

View file

@ -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));
}