mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
AK: Add a StringView method to count the number of lines in a string
We already have a helper to split a StringView by line while considering "\n", "\r", and "\r\n". Add an analagous method to just count the number of lines in the same manner.
This commit is contained in:
parent
07a27b2ec0
commit
82ea53cf10
Notes:
sideshowbarker
2024-07-17 01:10:58 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/82ea53cf10 Pull-request: https://github.com/SerenityOS/serenity/pull/23525 Reviewed-by: https://github.com/LucasChollet ✅
3 changed files with 79 additions and 30 deletions
|
@ -68,6 +68,48 @@ Vector<StringView> StringView::split_view(StringView separator, SplitBehavior sp
|
||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
static void for_each_line(StringView string, Callback&& callback)
|
||||||
|
{
|
||||||
|
char const* characters = string.characters_without_null_termination();
|
||||||
|
|
||||||
|
size_t substart = 0;
|
||||||
|
bool last_ch_was_cr = false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < string.length(); ++i) {
|
||||||
|
char ch = characters[i];
|
||||||
|
bool split_view = false;
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case '\n':
|
||||||
|
if (last_ch_was_cr)
|
||||||
|
substart = i + 1;
|
||||||
|
else
|
||||||
|
split_view = true;
|
||||||
|
|
||||||
|
last_ch_was_cr = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
split_view = true;
|
||||||
|
last_ch_was_cr = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
last_ch_was_cr = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split_view) {
|
||||||
|
callback(string.substring_view(substart, i - substart));
|
||||||
|
substart = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size_t taillen = string.length() - substart; taillen != 0)
|
||||||
|
callback(string.substring_view(substart, taillen));
|
||||||
|
}
|
||||||
|
|
||||||
Vector<StringView> StringView::lines(ConsiderCarriageReturn consider_carriage_return) const
|
Vector<StringView> StringView::lines(ConsiderCarriageReturn consider_carriage_return) const
|
||||||
{
|
{
|
||||||
if (is_empty())
|
if (is_empty())
|
||||||
|
@ -76,36 +118,24 @@ Vector<StringView> StringView::lines(ConsiderCarriageReturn consider_carriage_re
|
||||||
if (consider_carriage_return == ConsiderCarriageReturn::No)
|
if (consider_carriage_return == ConsiderCarriageReturn::No)
|
||||||
return split_view('\n', SplitBehavior::KeepEmpty);
|
return split_view('\n', SplitBehavior::KeepEmpty);
|
||||||
|
|
||||||
Vector<StringView> v;
|
Vector<StringView> lines;
|
||||||
size_t substart = 0;
|
for_each_line(*this, [&](auto line) { lines.append(line); });
|
||||||
bool last_ch_was_cr = false;
|
|
||||||
bool split_view = false;
|
return lines;
|
||||||
for (size_t i = 0; i < length(); ++i) {
|
|
||||||
char ch = characters_without_null_termination()[i];
|
|
||||||
if (ch == '\n') {
|
|
||||||
split_view = true;
|
|
||||||
if (last_ch_was_cr) {
|
|
||||||
substart = i + 1;
|
|
||||||
split_view = false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (ch == '\r') {
|
size_t StringView::count_lines(ConsiderCarriageReturn consider_carriage_return) const
|
||||||
split_view = true;
|
{
|
||||||
last_ch_was_cr = true;
|
if (is_empty())
|
||||||
} else {
|
return 1;
|
||||||
last_ch_was_cr = false;
|
|
||||||
}
|
if (consider_carriage_return == ConsiderCarriageReturn::No)
|
||||||
if (split_view) {
|
return count('\n') + 1;
|
||||||
size_t sublen = i - substart;
|
|
||||||
v.append(substring_view(substart, sublen));
|
size_t lines = 0;
|
||||||
substart = i + 1;
|
for_each_line(*this, [&](auto) { ++lines; });
|
||||||
}
|
|
||||||
split_view = false;
|
return lines;
|
||||||
}
|
|
||||||
size_t taillen = length() - substart;
|
|
||||||
if (taillen != 0)
|
|
||||||
v.append(substring_view(substart, taillen));
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringView::starts_with(char ch) const
|
bool StringView::starts_with(char ch) const
|
||||||
|
|
|
@ -240,6 +240,7 @@ public:
|
||||||
Yes,
|
Yes,
|
||||||
};
|
};
|
||||||
[[nodiscard]] Vector<StringView> lines(ConsiderCarriageReturn = ConsiderCarriageReturn::Yes) const;
|
[[nodiscard]] Vector<StringView> lines(ConsiderCarriageReturn = ConsiderCarriageReturn::Yes) const;
|
||||||
|
[[nodiscard]] size_t count_lines(ConsiderCarriageReturn = ConsiderCarriageReturn::Yes) const;
|
||||||
|
|
||||||
// Create a new substring view of this string view, starting either at the beginning of
|
// Create a new substring view of this string view, starting either at the beginning of
|
||||||
// the given substring view, or after its end, and continuing until the end of this string
|
// the given substring view, or after its end, and continuing until the end of this string
|
||||||
|
|
|
@ -105,6 +105,24 @@ TEST_CASE(lines)
|
||||||
EXPECT_EQ(test_string_vector.at(2).is_empty(), true);
|
EXPECT_EQ(test_string_vector.at(2).is_empty(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE(count_lines)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(""sv.count_lines(), 1u);
|
||||||
|
EXPECT_EQ("foo"sv.count_lines(), 1u);
|
||||||
|
|
||||||
|
EXPECT_EQ("foo\nbar"sv.count_lines(), 2u);
|
||||||
|
EXPECT_EQ("foo\rbar"sv.count_lines(), 2u);
|
||||||
|
EXPECT_EQ("foo\rbar"sv.count_lines(StringView::ConsiderCarriageReturn::No), 1u);
|
||||||
|
EXPECT_EQ("foo\r\nbar"sv.count_lines(), 2u);
|
||||||
|
EXPECT_EQ("foo\r\nbar"sv.count_lines(StringView::ConsiderCarriageReturn::No), 2u);
|
||||||
|
|
||||||
|
EXPECT_EQ("foo\nbar\nbax"sv.count_lines(), 3u);
|
||||||
|
EXPECT_EQ("foo\rbar\rbaz"sv.count_lines(), 3u);
|
||||||
|
EXPECT_EQ("foo\rbar\rbaz"sv.count_lines(StringView::ConsiderCarriageReturn::No), 1u);
|
||||||
|
EXPECT_EQ("foo\r\nbar\r\nbaz"sv.count_lines(), 3u);
|
||||||
|
EXPECT_EQ("foo\r\nbar\r\nbaz"sv.count_lines(StringView::ConsiderCarriageReturn::No), 3u);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE(find)
|
TEST_CASE(find)
|
||||||
{
|
{
|
||||||
auto test_string_view = "aabbcc_xy_ccbbaa"sv;
|
auto test_string_view = "aabbcc_xy_ccbbaa"sv;
|
||||||
|
|
Loading…
Reference in a new issue