diff --git a/AK/String.cpp b/AK/String.cpp index 4a70da2d07..0ed9343d29 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -303,11 +303,8 @@ bool String::equals_ignoring_case(const StringView& other) const return StringUtils::equals_ignoring_case(view(), other); } -int String::replace(const String& needle, const String& replacement, bool all_occurrences) +Vector String::find_all(const String& needle) const { - if (is_empty()) - return 0; - Vector positions; size_t start = 0, pos; for (;;) { @@ -317,11 +314,26 @@ int String::replace(const String& needle, const String& replacement, bool all_oc pos = ptr - characters(); positions.append(pos); - if (!all_occurrences) - break; start = pos + 1; } + return positions; +} + +int String::replace(const String& needle, const String& replacement, bool all_occurrences) +{ + if (is_empty()) + return 0; + + Vector positions; + if (all_occurrences) { + positions = find_all(needle); + } else { + auto pos = find(needle); + if (!pos.has_value()) + return 0; + positions.append(pos.value()); + } if (!positions.size()) return 0; @@ -338,6 +350,22 @@ int String::replace(const String& needle, const String& replacement, bool all_oc return positions.size(); } +size_t String::count(const String& needle) const +{ + size_t count = 0; + size_t start = 0, pos; + for (;;) { + const char* ptr = strstr(characters() + start, needle.characters()); + if (!ptr) + break; + + pos = ptr - characters(); + count++; + start = pos + 1; + } + return count; +} + String String::reverse() const { StringBuilder reversed_string; diff --git a/AK/String.h b/AK/String.h index ff729558cd..c84574615e 100644 --- a/AK/String.h +++ b/AK/String.h @@ -262,6 +262,8 @@ public: [[nodiscard]] StringView view() const; int replace(const String& needle, const String& replacement, bool all_occurrences = false); + size_t count(const String& needle) const; + Vector find_all(const String& needle) const; [[nodiscard]] String reverse() const; template diff --git a/Tests/AK/TestString.cpp b/Tests/AK/TestString.cpp index b61828199e..40953ec418 100644 --- a/Tests/AK/TestString.cpp +++ b/Tests/AK/TestString.cpp @@ -168,6 +168,26 @@ TEST_CASE(replace) EXPECT(test_string == "111._.|||._.|||"); } +TEST_CASE(count) +{ + String test_string = "Well, hello Friends!"; + u32 count = test_string.count("Friends"); + EXPECT(count == 1); + + count = test_string.count("ell"); + EXPECT(count == 2); + + count = test_string.count("!"); + EXPECT(count == 1); + + test_string = String("111._.111._.111"); + count = test_string.count("111"); + EXPECT(count == 3); + + count = test_string.count("._."); + EXPECT(count == 2); +} + TEST_CASE(substring) { String test = "abcdef";