diff --git a/AK/StringView.cpp b/AK/StringView.cpp index e9e7a86fd8c..88a4d9217b9 100644 --- a/AK/StringView.cpp +++ b/AK/StringView.cpp @@ -222,4 +222,46 @@ bool StringView::operator==(const String& string) const return !__builtin_memcmp(m_characters, string.characters(), m_length); } +Optional 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 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 StringView::find_last_of(char c) const +{ + for (size_t pos = m_length; --pos >0;) { + if (m_characters[pos] == c) + return pos; + } + return {}; +} + +Optional 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 {}; +} + } diff --git a/AK/StringView.h b/AK/StringView.h index 491e1cf2c38..3d7105888d4 100644 --- a/AK/StringView.h +++ b/AK/StringView.h @@ -79,6 +79,12 @@ public: bool matches(const StringView& mask, CaseSensitivity = CaseSensitivity::CaseInsensitive) const; bool contains(char) const; + Optional find_first_of(char) const; + Optional find_first_of(const StringView&) const; + + Optional find_last_of(char) const; + Optional find_last_of(const StringView&) const; + StringView substring_view(size_t start, size_t length) const; Vector split_view(char, bool keep_empty = false) const; diff --git a/AK/Tests/TestStringView.cpp b/AK/Tests/TestStringView.cpp index 53f2704b460..e26fa65f631 100644 --- a/AK/Tests/TestStringView.cpp +++ b/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)