AK: Make String::count not use strstr and take a StringView

This was needlessly copying StringView arguments, and was also using
strstr internally, which meant it was doing a bunch of unnecessary
strlen calls on it. This also moves the implementation to StringUtils
to allow API consistency between String and StringView.
This commit is contained in:
Idan Horowitz 2021-09-11 01:02:24 +03:00
parent 4e40eaf34c
commit 6d2b003b6e
Notes: sideshowbarker 2024-07-18 04:15:09 +09:00
5 changed files with 19 additions and 17 deletions

View file

@ -382,22 +382,6 @@ int String::replace(const String& needle, const String& replacement, bool all_oc
return positions.size(); 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 String String::reverse() const
{ {
StringBuilder reversed_string(length()); StringBuilder reversed_string(length());

View file

@ -286,7 +286,7 @@ 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);
[[nodiscard]] size_t count(const String& needle) const; [[nodiscard]] size_t count(StringView const& needle) const { return StringUtils::count(*this, needle); }
[[nodiscard]] String reverse() const; [[nodiscard]] String reverse() const;
template<typename... Ts> template<typename... Ts>

View file

@ -427,6 +427,20 @@ String to_titlecase(StringView const& str)
return builder.to_string(); return builder.to_string();
} }
// TODO: Benchmark against KMP (AK/MemMem.h) and switch over if it's faster for short strings too
size_t count(StringView const& str, StringView const& needle)
{
if (needle.is_empty())
return str.length();
size_t count = 0;
for (size_t i = 0; i < str.length() - needle.length() + 1; ++i) {
if (str.substring_view(i).starts_with(needle))
count++;
}
return count;
}
} }
} }

View file

@ -71,6 +71,8 @@ Optional<size_t> find_any_of(StringView const& haystack, StringView const& needl
String to_snakecase(const StringView&); String to_snakecase(const StringView&);
String to_titlecase(StringView const&); String to_titlecase(StringView const&);
size_t count(StringView const&, StringView const& needle);
} }
} }

View file

@ -220,6 +220,8 @@ public:
[[nodiscard]] bool is_whitespace() const { return StringUtils::is_whitespace(*this); } [[nodiscard]] bool is_whitespace() const { return StringUtils::is_whitespace(*this); }
[[nodiscard]] size_t count(StringView const& needle) const { return StringUtils::count(*this, needle); }
template<typename... Ts> template<typename... Ts>
[[nodiscard]] ALWAYS_INLINE constexpr bool is_one_of(Ts&&... strings) const [[nodiscard]] ALWAYS_INLINE constexpr bool is_one_of(Ts&&... strings) const
{ {