aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-06-26 16:56:46 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-06-26 17:13:28 +0200
commitd0d7b1253d6c93a2a0bda57bc52fa40169dfad50 (patch)
tree9667c454e1dd84070da0919e55a3160cdf6b4477 /libs
parent8583e53229e7b6cbe8b28d615ba8a02e4732d65b (diff)
downloadkernel-d0d7b1253d6c93a2a0bda57bc52fa40169dfad50.tar.xz
kernel-d0d7b1253d6c93a2a0bda57bc52fa40169dfad50.zip
kstd: add some basic_string::compare overloads
Diffstat (limited to 'libs')
-rw-r--r--libs/kstd/kstd/bits/basic_string.hpp110
-rw-r--r--libs/kstd/kstd/string.test.cpp305
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]")