Selaa lähdekoodia

AK: Implement StringView::find_all()

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.
Max Wipfli 4 vuotta sitten
vanhempi
commit
d7a104c27c
4 muutettua tiedostoa jossa 19 lisäystä ja 18 poistoa
  1. 0 17
      AK/String.cpp
  2. 1 1
      AK/String.h
  3. 16 0
      AK/StringUtils.cpp
  4. 2 0
      AK/StringView.h

+ 0 - 17
AK/String.cpp

@@ -293,23 +293,6 @@ bool String::equals_ignoring_case(const StringView& other) const
     return StringUtils::equals_ignoring_case(view(), other);
     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)
 int String::replace(const String& needle, const String& replacement, bool all_occurrences)
 {
 {
     if (is_empty())
     if (is_empty())

+ 1 - 1
AK/String.h

@@ -143,6 +143,7 @@ public:
 
 
     [[nodiscard]] Optional<size_t> find(char, size_t start = 0) const;
     [[nodiscard]] Optional<size_t> find(char, size_t start = 0) const;
     [[nodiscard]] Optional<size_t> find(StringView const&, 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) const;
     [[nodiscard]] String substring(size_t start, size_t length) const;
     [[nodiscard]] String substring(size_t start, size_t length) const;
@@ -279,7 +280,6 @@ public:
 
 
     int replace(const String& needle, const String& replacement, bool all_occurrences = false);
     int replace(const String& needle, const String& replacement, bool all_occurrences = false);
     size_t count(const String& needle) const;
     size_t count(const String& needle) const;
-    Vector<size_t> find_all(const String& needle) const;
     [[nodiscard]] String reverse() const;
     [[nodiscard]] String reverse() const;
 
 
     template<typename... Ts>
     template<typename... Ts>

+ 16 - 0
AK/StringUtils.cpp

@@ -362,6 +362,22 @@ Optional<size_t> find_last(StringView const& haystack, char needle)
     return {};
     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)
 String to_snakecase(const StringView& str)
 {
 {
     auto should_insert_underscore = [&](auto i, auto current_char) {
     auto should_insert_underscore = [&](auto i, auto current_char) {

+ 2 - 0
AK/StringView.h

@@ -91,6 +91,8 @@ public:
     [[nodiscard]] Optional<size_t> find_last(char needle) const { return StringUtils::find_last(*this, needle); }
     [[nodiscard]] Optional<size_t> find_last(char needle) const { return StringUtils::find_last(*this, needle); }
     // FIXME: Implement find_last(StringView const&) for API symmetry.
     // 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_first_of(StringView const&) const;
     [[nodiscard]] Optional<size_t> find_last_of(StringView const&) const;
     [[nodiscard]] Optional<size_t> find_last_of(StringView const&) const;