Browse Source

AK+Everywhere: Consolidate String::index_of() and String::find()

We had two functions for doing mostly the same thing. Combine both
of them into String::find() and use that everywhere.

Also add some tests to cover basic behavior.
Andreas Kling 4 years ago
parent
commit
de395a3df2

+ 7 - 16
AK/String.cpp

@@ -286,18 +286,6 @@ bool String::contains(const StringView& needle, CaseSensitivity case_sensitivity
     return StringUtils::contains(*this, needle, case_sensitivity);
 }
 
-Optional<size_t> String::index_of(const String& needle, size_t start) const
-{
-    if (is_null() || needle.is_null())
-        return {};
-
-    const char* self_characters = characters();
-    const char* result = strstr(self_characters + start, needle.characters());
-    if (!result)
-        return {};
-    return Optional<size_t> { result - self_characters };
-}
-
 bool String::equals_ignoring_case(const StringView& other) const
 {
     return StringUtils::equals_ignoring_case(view(), other);
@@ -491,14 +479,17 @@ String String::vformatted(StringView fmtstr, TypeErasedFormatParams params)
     return builder.to_string();
 }
 
-Optional<size_t> String::find(char c) const
+Optional<size_t> String::find(char c, size_t start) const
 {
-    return find(StringView { &c, 1 });
+    return find(StringView { &c, 1 }, start);
 }
 
-Optional<size_t> String::find(const StringView& view) const
+Optional<size_t> String::find(StringView const& view, size_t start) const
 {
-    return StringUtils::find(*this, view);
+    auto index = StringUtils::find(substring_view(start), view);
+    if (!index.has_value())
+        return {};
+    return index.value() + start;
 }
 
 }

+ 2 - 3
AK/String.h

@@ -127,13 +127,12 @@ public:
     [[nodiscard]] bool equals_ignoring_case(const StringView&) const;
 
     [[nodiscard]] bool contains(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
-    [[nodiscard]] Optional<size_t> index_of(const String&, size_t start = 0) const;
 
     [[nodiscard]] Vector<String> split_limit(char separator, size_t limit, bool keep_empty = false) const;
     [[nodiscard]] Vector<String> split(char separator, bool keep_empty = false) const;
 
-    [[nodiscard]] Optional<size_t> find(char) const;
-    [[nodiscard]] Optional<size_t> find(const StringView&) 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]] String substring(size_t start) const;
     [[nodiscard]] String substring(size_t start, size_t length) const;

+ 16 - 0
Tests/AK/TestString.cpp

@@ -255,3 +255,19 @@ TEST_CASE(sprintf)
     EXPECT_EQ(String(buf1), String("+12"));
     EXPECT_EQ(String(buf2), String("-12"));
 }
+
+TEST_CASE(find)
+{
+    String a = "foobarbar";
+    EXPECT_EQ(a.find("bar"sv), Optional<size_t> { 3 });
+    EXPECT_EQ(a.find("baz"sv), Optional<size_t> {});
+    EXPECT_EQ(a.find("bar"sv, 4), Optional<size_t> { 6 });
+    EXPECT_EQ(a.find("bar"sv, 9), Optional<size_t> {});
+
+    EXPECT_EQ(a.find('f'), Optional<size_t> { 0 });
+    EXPECT_EQ(a.find('x'), Optional<size_t> {});
+    EXPECT_EQ(a.find('f', 1), Optional<size_t> {});
+    EXPECT_EQ(a.find('b'), Optional<size_t> { 3 });
+    EXPECT_EQ(a.find('b', 4), Optional<size_t> { 6 });
+    EXPECT_EQ(a.find('b', 9), Optional<size_t> {});
+}

+ 1 - 1
Userland/DevTools/UserspaceEmulator/Emulator.cpp

@@ -278,7 +278,7 @@ String Emulator::create_backtrace_line(FlatPtr address)
     const auto* region = find_text_region(address);
     if (!region)
         return minimal;
-    auto separator_index = region->name().index_of(":");
+    auto separator_index = region->name().find(':');
     if (!separator_index.has_value())
         return minimal;
 

+ 1 - 1
Userland/Libraries/LibDiff/Hunks.cpp

@@ -82,7 +82,7 @@ HunkLocation parse_hunk_location(const String& location_line)
         size_t length { 0 };
     };
     auto parse_start_and_length_pair = [](const String& raw) {
-        auto index_of_separator = raw.index_of(",").value();
+        auto index_of_separator = raw.find(',').value();
         auto start = raw.substring(0, index_of_separator);
         auto length = raw.substring(index_of_separator + 1, raw.length() - index_of_separator - 1);
         auto res = StartAndLength { start.to_uint().value() - 1, length.to_uint().value() - 1 };

+ 1 - 1
Userland/Libraries/LibELF/Image.cpp

@@ -297,7 +297,7 @@ Optional<Image::Symbol> Image::find_demangled_function(const String& name) const
         if (symbol.is_undefined())
             return IterationDecision::Continue;
         auto demangled = demangle(symbol.name());
-        auto index_of_paren = demangled.index_of("(");
+        auto index_of_paren = demangled.find('(');
         if (index_of_paren.has_value()) {
             demangled = demangled.substring(0, index_of_paren.value());
         }

+ 2 - 2
Userland/Libraries/LibJS/Runtime/StringPrototype.cpp

@@ -240,7 +240,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::index_of)
     auto needle = vm.argument(0).to_string(global_object);
     if (vm.exception())
         return {};
-    return Value((i32)string.index_of(needle).value_or(-1));
+    return Value((i32)string.find(needle).value_or(-1));
 }
 
 JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_lowercase)
@@ -692,7 +692,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace)
     auto search_string = search_value.to_string(global_object);
     if (vm.exception())
         return {};
-    Optional<size_t> position = string.index_of(search_string);
+    Optional<size_t> position = string.find(search_string);
     if (!position.has_value())
         return js_string(vm, string);
 

+ 1 - 1
Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp

@@ -389,7 +389,7 @@ public:
     {
         if (const auto start_pos = pseudo_name.find('('); start_pos.has_value()) {
             const auto start = start_pos.value() + 1;
-            if (const auto end_pos = pseudo_name.index_of(")", start); end_pos.has_value()) {
+            if (const auto end_pos = pseudo_name.find(')', start); end_pos.has_value()) {
                 return pseudo_name.substring_view(start, end_pos.value() - start).trim_whitespace();
             }
         }

+ 2 - 2
Userland/Libraries/LibWeb/Loader/Resource.cpp

@@ -43,7 +43,7 @@ void Resource::for_each_client(Function<void(ResourceClient&)> callback)
 
 static Optional<String> encoding_from_content_type(const String& content_type)
 {
-    auto offset = content_type.index_of("charset=");
+    auto offset = content_type.find("charset="sv);
     if (offset.has_value()) {
         auto encoding = content_type.substring(offset.value() + 8, content_type.length() - offset.value() - 8).to_lowercase();
         if (encoding.length() >= 2 && encoding.starts_with('"') && encoding.ends_with('"'))
@@ -58,7 +58,7 @@ static Optional<String> encoding_from_content_type(const String& content_type)
 
 static String mime_type_from_content_type(const String& content_type)
 {
-    auto offset = content_type.index_of(";");
+    auto offset = content_type.find(';');
     if (offset.has_value())
         return content_type.substring(0, offset.value()).to_lowercase();
 

+ 1 - 1
Userland/Shell/AST.cpp

@@ -611,7 +611,7 @@ void BarewordLiteral::highlight_in_editor(Line::Editor& editor, Shell& shell, Hi
             return;
 
         if (m_text.starts_with("--")) {
-            auto index = m_text.index_of("=").value_or(m_text.length() - 1) + 1;
+            auto index = m_text.find('=').value_or(m_text.length() - 1) + 1;
             editor.stylize({ m_position.start_offset, m_position.start_offset + index }, { Line::Style::Foreground(Line::Style::XtermColor::Cyan) });
         } else {
             editor.stylize({ m_position.start_offset, m_position.end_offset }, { Line::Style::Foreground(Line::Style::XtermColor::Cyan) });

+ 1 - 1
Userland/Shell/Parser.cpp

@@ -1772,7 +1772,7 @@ RefPtr<AST::Node> Parser::parse_bareword()
         String username;
         RefPtr<AST::Node> tilde, text;
 
-        auto first_slash_index = string.index_of("/");
+        auto first_slash_index = string.find('/');
         if (first_slash_index.has_value()) {
             username = string.substring_view(1, first_slash_index.value() - 1);
             string = string.substring_view(first_slash_index.value(), string.length() - first_slash_index.value());

+ 1 - 1
Userland/Utilities/expr.cpp

@@ -371,7 +371,7 @@ private:
         }
 
         if (m_op == StringOperation::Index) {
-            if (auto idx = m_str->string().index_of(m_pos_or_chars->string()); idx.has_value())
+            if (auto idx = m_str->string().find(m_pos_or_chars->string()); idx.has_value())
                 return idx.value() + 1;
             return 0;
         }