diff options
| -rw-r--r-- | libs/kstd/kstd/bits/basic_string.hpp | 110 | ||||
| -rw-r--r-- | libs/kstd/kstd/string.test.cpp | 305 |
2 files changed, 411 insertions, 4 deletions
diff --git a/libs/kstd/kstd/bits/basic_string.hpp b/libs/kstd/kstd/bits/basic_string.hpp index 0509e33a..212aa8ac 100644 --- a/libs/kstd/kstd/bits/basic_string.hpp +++ b/libs/kstd/kstd/bits/basic_string.hpp @@ -981,6 +981,87 @@ namespace kstd swap(m_length, other.m_length); } + //! Lexicographically compare this string to another string + //! + //! @param other The string to compare this string with. + //! @return a negative value if this string is ordered lexicographically before the given string, zero if both + //! strings are equal, or a positive value if this string is ordered lexicographically before the given string. + [[nodiscard]] constexpr auto compare(basic_string const & other) const noexcept -> int + { + return do_compare(*this, other); + } + + //! Lexicographically compare a substring of this string with a given string. + //! + //! @param position The start position of this substring. + //! @param count The length of this substring. + //! @param other The string to compare to the substring of this string. + //! @return a negative value if this string is ordered lexicographically before the given string, zero if both + //! strings are equal, or a positive value if this string is ordered lexicographically before the given string. + [[nodiscard]] constexpr auto compare(size_type position, size_type count, basic_string const & other) const noexcept + -> int + { + auto view = static_cast<std::basic_string_view<value_type, traits_type>>(*this); + return do_compare(view.substr(position, count), other); + } + + //! Lexicographically compare a substring of this string with a substring of another string. + //! + //! @param position The start position of this substring. + //! @param count The length of this substring. + //! @param other The string, a substring of which to compare to the substring of this string. + //! @param other_position The start position of the substring of @p other. + //! @param other_count The length of the substring of @p other. + //! @return a negative value if this string is ordered lexicographically before the given string, zero if both + //! strings are equal, or a positive value if this string is ordered lexicographically before the given string. + [[nodiscard]] constexpr auto compare(size_type position, size_type count, basic_string const & other, + size_type other_position, size_type other_count = npos) const noexcept -> int + { + auto view = static_cast<std::basic_string_view<value_type, traits_type>>(*this); + auto other_view = static_cast<std::basic_string_view<value_type, traits_type>>(other); + return do_compare(view.substr(position, count), other_view.substr(other_position, other_count)); + } + + //! Lexicographically compare this string to a C-style string. + //! + //! @param string The C-style string to compare this string with. + //! @return a negative value if this string is ordered lexicographically before the given string, zero if both + //! strings are equal, or a positive value if this string is ordered lexicographically before the given string. + [[nodiscard]] constexpr auto compare(CharacterType const * string) const noexcept -> int + { + return do_compare(*this, {string, traits_type::length(string)}); + } + + //! Lexicographically compare a substring of this string with a given C-style string. + //! + //! @param position The start position of this substring. + //! @param count The length of this substring. + //! @param string The C-style string to compare to the substring of this string. + //! @return a negative value if this string is ordered lexicographically before the given string, zero if both + //! strings are equal, or a positive value if this string is ordered lexicographically before the given string. + [[nodiscard]] constexpr auto compare(size_type position, size_type count, + CharacterType const * string) const noexcept -> int + { + auto view = static_cast<std::basic_string_view<value_type, traits_type>>(*this); + return do_compare(view.substr(position, count), {string, traits_type::length(string)}); + } + + //! Lexicographically compare a substring of this string with a substring of a C-style string. + //! + //! @param position The start position of this substring. + //! @param count The length of this substring. + //! @param string The C-style string, a substring of which to compare to the substring of this string. + //! @param string_count The length of the substring of @p other. + //! @return a negative value if this string is ordered lexicographically before the given string, zero if both + //! strings are equal, or a positive value if this string is ordered lexicographically before the given string. + [[nodiscard]] constexpr auto compare(size_type position, size_type count, CharacterType const * string, + size_type string_count) const noexcept -> int + { + auto view = static_cast<std::basic_string_view<value_type, traits_type>>(*this); + auto other_view = static_cast<std::basic_string_view<value_type, traits_type>>(string, string_count); + return do_compare(view.substr(position, count), other_view); + } + //! Concatenate two string. //! //! @param lhs The left hand side string. @@ -1017,7 +1098,7 @@ namespace kstd return result; } - //! Contcatenate a C-style string and a string. + //! Concatenate a C-style string and a string. //! //! @param lhs The left hand side C-style string. //! @param rhs The right hand side string. @@ -1041,7 +1122,7 @@ namespace kstd return result; } - //! Contcatenate two strings. + //! Concatenate two strings. //! //! @param lhs The left hand side string. //! @param rhs The right hand side string. @@ -1052,7 +1133,7 @@ namespace kstd return std::move(lhs); } - //! Contcatenate two strings. + //! Concatenate two strings. //! //! @param lhs The left hand side string. //! @param rhs The right hand side string. @@ -1063,7 +1144,7 @@ namespace kstd return std::move(lhs); } - //! Contcatenate a string and a C-style string. + //! Concatenate a string and a C-style string. //! //! @param lhs The left hand side string. //! @param rhs The right hand side C-style string. @@ -1300,6 +1381,27 @@ namespace kstd return *this; } + [[nodiscard]] constexpr auto static do_compare(std::basic_string_view<value_type, traits_type> lhs, + std::basic_string_view<value_type, traits_type> rhs) noexcept + { + // clang-tidy is not smart enough to see that whe are, in essence, passing the correct length. + // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) + if (auto result = traits_type::compare(lhs.data(), rhs.data(), std::min(lhs.size(), rhs.size()))) + { + return result; + } + else if (lhs.size() < rhs.size()) + { + return -1; + } + else if (lhs.size() > rhs.size()) + { + return 1; + } + + return 0; + } + //! Copy elements from a range described by an input iterator pair. //! //! @param first An iterator pointing to the first element to copy. diff --git a/libs/kstd/kstd/string.test.cpp b/libs/kstd/kstd/string.test.cpp index 74be1f0b..3fbf6c0c 100644 --- a/libs/kstd/kstd/string.test.cpp +++ b/libs/kstd/kstd/string.test.cpp @@ -2533,6 +2533,311 @@ SCENARIO("String conversion and comparison", "[string]") REQUIRE_FALSE(view != str); } } + + GIVEN("The string 'abc'") + { + auto s1 = kstd::string{"abc"}; + + WHEN("comparing with the string 'def'") + { + auto result = s1.compare(kstd::string{"def"}); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing with the string 'abb'") + { + auto result = s1.compare(kstd::string{"abb"}); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing with the string 'abc'") + { + auto result = s1.compare(kstd::string{"abc"}); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing substring [1,2] with the string 'def'") + { + auto result = s1.compare(1, 2, kstd::string{"def"}); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing substring [1,2] with the string 'abb'") + { + auto result = s1.compare(1, 2, kstd::string{"abb"}); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing substring [1,2] with the string 'cc'") + { + auto result = s1.compare(1, 2, kstd::string{"bc"}); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing substring [1,npos] with the string 'ef'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"ef"}); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing substring [1,npos] with the string 'bb'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"bb"}); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing substring [1,npos] with the string 'bc'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"bc"}); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing substring [1,2] with the substring [1,2] of 'def'") + { + auto result = s1.compare(1, 2, kstd::string{"def"}, 1, 2); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing substring [1,2] with the substring [1,2] of 'abb'") + { + auto result = s1.compare(1, 2, kstd::string{"abb"}, 1, 2); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing substring [1,2] with the substring [1,2] of 'abc'") + { + auto result = s1.compare(1, 2, kstd::string{"abc"}, 1, 2); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing substring [1,npos] with the substring [1,2] of 'def'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"def"}, 1, 2); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing substring [1,npos] with the substring [1,2] of 'abb'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"abb"}, 1, 2); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing substring [1,npos] with the substring [1,2] of 'abc'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"abc"}, 1, 2); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing substring [1,2] with the substring [1,npos] of 'def'") + { + auto result = s1.compare(1, 2, kstd::string{"def"}, 1, kstd::string::npos); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing substring [1,2] with the substring [1,npos] of 'abb'") + { + auto result = s1.compare(1, 2, kstd::string{"abb"}, 1, kstd::string::npos); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing substring [1,2] with the substring [1,npos] of 'abc'") + { + auto result = s1.compare(1, 2, kstd::string{"abc"}, 1, kstd::string::npos); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing substring [1,npos] with the substring [1,npos] of 'def'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"def"}, 1, kstd::string::npos); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing substring [1,npos] with the substring [1,npos] of 'abb'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"abb"}, 1, kstd::string::npos); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing substring [1,npos] with the substring [1,npos] of 'abc'") + { + auto result = s1.compare(1, kstd::string::npos, kstd::string{"abc"}, 1, kstd::string::npos); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing with the C-style string 'def'") + { + auto result = s1.compare("def"); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing with the C-style string 'abb'") + { + auto result = s1.compare("abb"); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing with the C-style string 'abc'") + { + auto result = s1.compare("abc"); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing substring [1,2] with the C-style string 'def'") + { + auto result = s1.compare(1, 2, "def"); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing substring [1,2] with the C-style string 'abb'") + { + auto result = s1.compare(1, 2, "abb"); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing substring [1,2] with the C-style string 'bc'") + { + auto result = s1.compare(1, 2, "bc"); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + + WHEN("comparing substring [1,npos] with the C-style string 'def'") + { + auto result = s1.compare(1, 2, "ef"); + + THEN("the result is negative") + { + REQUIRE(result < 0); + } + } + + WHEN("comparing substring [1,npos] with the C-style string 'abb'") + { + auto result = s1.compare(1, 2, "abb"); + + THEN("the result is positive") + { + REQUIRE(result > 0); + } + } + + WHEN("comparing substring [1,npos] with the C-style string 'bc'") + { + auto result = s1.compare(1, 2, "bc"); + + THEN("the result is zero") + { + REQUIRE(result == 0); + } + } + } } SCENARIO("String iteration", "[string]") |
