diff --git a/AK/String.cpp b/AK/String.cpp index c718858d37d..76ce98b4b5f 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -320,6 +320,41 @@ 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_occurences) +{ + if (is_empty()) + return 0; + + Vector positions; + size_t start = 0, pos; + for (;;) { + const char* ptr = strstr(characters() + start, needle.characters()); + if (!ptr) + break; + + pos = ptr - characters(); + positions.append(pos); + if (!all_occurences) + break; + + start = pos + 1; + } + + if (!positions.size()) + return 0; + + StringBuilder b; + size_t lastpos = 0; + for (auto& pos : positions) { + b.append(substring_view(lastpos, pos - lastpos)); + b.append(replacement); + lastpos = pos + needle.length(); + } + b.append(substring_view(lastpos, length() - lastpos)); + m_impl = StringImpl::create(b.build().characters()); + return positions.size(); +} + String escape_html_entities(const StringView& html) { StringBuilder builder; diff --git a/AK/String.h b/AK/String.h index 22a4ed1dfe4..e184476186f 100644 --- a/AK/String.h +++ b/AK/String.h @@ -214,6 +214,8 @@ public: StringView view() const; + int replace(const String& needle, const String& replacement, bool all_occurences = false); + private: RefPtr m_impl; }; diff --git a/AK/Tests/TestString.cpp b/AK/Tests/TestString.cpp index 7377db0acc5..eb82d4ccd67 100644 --- a/AK/Tests/TestString.cpp +++ b/AK/Tests/TestString.cpp @@ -159,4 +159,29 @@ TEST_CASE(flystring) } } +TEST_CASE(replace) +{ + String test_string = "Well, hello Friends!"; + u32 replacements = test_string.replace("Friends", "Testers"); + EXPECT(replacements == 1); + EXPECT(test_string == "Well, hello Testers!"); + + replacements = test_string.replace("ell", "e're", true); + EXPECT(replacements == 2); + EXPECT(test_string == "We're, he'reo Testers!"); + + replacements = test_string.replace("!", " :^)"); + EXPECT(replacements == 1); + EXPECT(test_string == "We're, he'reo Testers :^)"); + + test_string = String("111._.111._.111"); + replacements = test_string.replace("111", "|||", true); + EXPECT(replacements == 3); + EXPECT(test_string == "|||._.|||._.|||"); + + replacements = test_string.replace("|||", "111"); + EXPECT(replacements == 1); + EXPECT(test_string == "111._.|||._.|||"); +} + TEST_MAIN(String)