Skip to content

Commit

Permalink
AK: Implement StringView::find_all()
Browse files Browse the repository at this point in the history
This implements the StringView::find_all() method by re-implemeting the
current method existing for String in StringUtils, and using that
implementation for both String and StringView.

The rewrite uses memmem() instead of strstr(), so the String::find_all()
argument type has been changed from String to StringView, as the null
byte is no longer required.
  • Loading branch information
MaxWipfli authored and awesomekling committed Jul 2, 2021
1 parent 3bdaed5 commit d7a104c
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 18 deletions.
17 changes: 0 additions & 17 deletions AK/String.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,23 +293,6 @@ bool String::equals_ignoring_case(const StringView& other) const
return StringUtils::equals_ignoring_case(view(), other);
}

Vector<size_t> String::find_all(const String& needle) const
{
Vector<size_t> positions;
size_t start = 0, pos;
for (;;) {
const char* ptr = strstr(characters() + start, needle.characters());
if (!ptr)
break;

pos = ptr - characters();
positions.append(pos);

start = pos + 1;
}
return positions;
}

int String::replace(const String& needle, const String& replacement, bool all_occurrences)
{
if (is_empty())
Expand Down
2 changes: 1 addition & 1 deletion AK/String.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class String {

[[nodiscard]] Optional<size_t> find(char, size_t start = 0) const;
[[nodiscard]] Optional<size_t> find(StringView const&, size_t start = 0) const;
[[nodiscard]] Vector<size_t> find_all(StringView const& needle) const { return StringUtils::find_all(*this, needle); }

[[nodiscard]] String substring(size_t start) const;
[[nodiscard]] String substring(size_t start, size_t length) const;
Expand Down Expand Up @@ -279,7 +280,6 @@ class String {

int replace(const String& needle, const String& replacement, bool all_occurrences = false);
size_t count(const String& needle) const;
Vector<size_t> find_all(const String& needle) const;
[[nodiscard]] String reverse() const;

template<typename... Ts>
Expand Down
16 changes: 16 additions & 0 deletions AK/StringUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,22 @@ Optional<size_t> find_last(StringView const& haystack, char needle)
return {};
}

Vector<size_t> find_all(StringView const& haystack, StringView const& needle)
{
Vector<size_t> positions;
size_t current_position = 0;
while (current_position <= haystack.length()) {
auto maybe_position = AK::memmem_optional(
haystack.characters_without_null_termination() + current_position, haystack.length() - current_position,
needle.characters_without_null_termination(), needle.length());
if (!maybe_position.has_value())
break;
positions.append(current_position + *maybe_position);
current_position += *maybe_position + 1;
}
return positions;
}

String to_snakecase(const StringView& str)
{
auto should_insert_underscore = [&](auto i, auto current_char) {
Expand Down
2 changes: 2 additions & 0 deletions AK/StringView.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class StringView {
[[nodiscard]] Optional<size_t> find_last(char needle) const { return StringUtils::find_last(*this, needle); }
// FIXME: Implement find_last(StringView const&) for API symmetry.

[[nodiscard]] Vector<size_t> find_all(StringView const& needle) const { return StringUtils::find_all(*this, needle); }

[[nodiscard]] Optional<size_t> find_first_of(StringView const&) const;
[[nodiscard]] Optional<size_t> find_last_of(StringView const&) const;

Expand Down

0 comments on commit d7a104c

Please sign in to comment.