瀏覽代碼

AK: Add StringView::find_first/last_of

These methods search from the beginning or end of a string for the
first character in the input StringView and returns the position in
the string of the first match. Note that this is not a substring match.
Each comes with single char overloads for efficiency.
Andrew Kaster 5 年之前
父節點
當前提交
3eb3c2477f
共有 3 個文件被更改,包括 91 次插入0 次删除
  1. 42 0
      AK/StringView.cpp
  2. 6 0
      AK/StringView.h
  3. 43 0
      AK/Tests/TestStringView.cpp

+ 42 - 0
AK/StringView.cpp

@@ -222,4 +222,46 @@ bool StringView::operator==(const String& string) const
     return !__builtin_memcmp(m_characters, string.characters(), m_length);
 }
 
+Optional<size_t> StringView::find_first_of(char c) const
+{
+    for (size_t pos = 0; pos < m_length; ++pos) {
+        if (m_characters[pos] == c)
+            return pos;
+    }
+    return {};
+}
+
+Optional<size_t> StringView::find_first_of(const StringView& view) const
+{
+    for (size_t pos = 0; pos < m_length; ++pos) {
+        char c = m_characters[pos];
+        for (char view_char : view) {
+            if (c == view_char)
+                return pos;
+        }
+    }
+    return {};
+}
+
+Optional<size_t> StringView::find_last_of(char c) const
+{
+    for (size_t pos = m_length; --pos >0;) {
+        if (m_characters[pos] == c)
+            return pos;
+    }
+    return {};
+}
+
+Optional<size_t> StringView::find_last_of(const StringView& view) const
+{
+    for (size_t pos = m_length - 1; --pos > 0;) {
+        char c = m_characters[pos];
+        for (char view_char : view) {
+            if (c == view_char)
+                return pos;
+        }
+    }
+    return {};
+}
+
 }

+ 6 - 0
AK/StringView.h

@@ -79,6 +79,12 @@ public:
     bool matches(const StringView& mask, CaseSensitivity = CaseSensitivity::CaseInsensitive) const;
     bool contains(char) const;
 
+    Optional<size_t> find_first_of(char) const;
+    Optional<size_t> find_first_of(const StringView&) const;
+
+    Optional<size_t> find_last_of(char) const;
+    Optional<size_t> find_last_of(const StringView&) const;
+
     StringView substring_view(size_t start, size_t length) const;
     Vector<StringView> split_view(char, bool keep_empty = false) const;
 

+ 43 - 0
AK/Tests/TestStringView.cpp

@@ -111,4 +111,47 @@ TEST_CASE(lines)
     EXPECT_EQ(test_string_vector.at(2).is_empty(), true);
 }
 
+TEST_CASE(find_first_of)
+{
+    String test_string = "aabbcc_xy_ccbbaa";
+    StringView test_string_view = test_string.view();
+
+    EXPECT_EQ(test_string_view.find_first_of('b').has_value(), true);
+    EXPECT_EQ(test_string_view.find_first_of('b').value(), 2U);
+
+    EXPECT_EQ(test_string_view.find_first_of('_').has_value(), true);
+    EXPECT_EQ(test_string_view.find_first_of('_').value(), 6U);
+
+    EXPECT_EQ(test_string_view.find_first_of("bc").has_value(), true);
+    EXPECT_EQ(test_string_view.find_first_of("bc").value(), 2U);
+
+    EXPECT_EQ(test_string_view.find_first_of("yx").has_value(), true);
+    EXPECT_EQ(test_string_view.find_first_of("yx").value(), 7U);
+
+    EXPECT_EQ(test_string_view.find_first_of('n').has_value(), false);
+    EXPECT_EQ(test_string_view.find_first_of("defg").has_value(), false);
+}
+
+TEST_CASE(find_last_of)
+{
+    String test_string = "aabbcc_xy_ccbbaa";
+    StringView test_string_view = test_string.view();
+
+    EXPECT_EQ(test_string_view.find_last_of('b').has_value(), true);
+    EXPECT_EQ(test_string_view.find_last_of('b').value(), 13U);
+
+    EXPECT_EQ(test_string_view.find_last_of('_').has_value(), true);
+    EXPECT_EQ(test_string_view.find_last_of('_').value(), 9U);
+
+    EXPECT_EQ(test_string_view.find_last_of("bc").has_value(), true);
+    EXPECT_EQ(test_string_view.find_last_of("bc").value(), 13U);
+
+    EXPECT_EQ(test_string_view.find_last_of("yx").has_value(), true);
+    EXPECT_EQ(test_string_view.find_last_of("yx").value(), 8U);
+
+    EXPECT_EQ(test_string_view.find_last_of('3').has_value(), false);
+    EXPECT_EQ(test_string_view.find_last_of("fghi").has_value(), false);
+}
+
+
 TEST_MAIN(StringView)