aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-10-02 17:17:33 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-10-02 17:17:33 +0200
commitf652d85c8e5f635b67bcb57d4143568d1216cf6d (patch)
treeb39f85d80cea642138f947ea8e1dea6dc824c833
parentcaf47befa014c9f2d6a5503527198ac736db2456 (diff)
downloadkernel-f652d85c8e5f635b67bcb57d4143568d1216cf6d.tar.xz
kernel-f652d85c8e5f635b67bcb57d4143568d1216cf6d.zip
kstd: ring_buffer: implement comparison
-rw-r--r--libs/kstd/kstd/ring_buffer.hpp28
-rw-r--r--libs/kstd/kstd/ring_buffer.tests.cpp127
2 files changed, 154 insertions, 1 deletions
diff --git a/libs/kstd/kstd/ring_buffer.hpp b/libs/kstd/kstd/ring_buffer.hpp
index 10f45d72..9cd533c4 100644
--- a/libs/kstd/kstd/ring_buffer.hpp
+++ b/libs/kstd/kstd/ring_buffer.hpp
@@ -382,6 +382,34 @@ namespace kstd
//! @}
+ //! @name Comparison
+ //! @{
+
+ //! Lexicographically compare two ring buffers.
+ //!
+ //! @param lhs The left-hand side ring buffer to compare.
+ //! @param rhs The right-hand side ring buffer to compare.
+ //! @return A value indicating the lexicographical comparison result.
+ constexpr auto friend operator<=>(ring_buffer const & lhs, ring_buffer const & rhs) noexcept
+ {
+ auto const lhs_common = lhs | std::views::common;
+ auto const rhs_common = rhs | std::views::common;
+ return std::lexicographical_compare_three_way(std::ranges::begin(lhs_common), std::ranges::end(lhs_common),
+ std::ranges::begin(rhs_common), std::ranges::end(rhs_common));
+ }
+
+ //! Check if two ring buffers are equal.
+ //!
+ //! @param lhs The left-hand side ring buffer to compare.
+ //! @param rhs The right-hand side ring buffer to compare.
+ //! @return `true` if the ring buffers are equal, `false` otherwise.
+ constexpr auto friend operator==(ring_buffer const & lhs, ring_buffer const & rhs) noexcept -> bool
+ {
+ return std::ranges::equal(lhs, rhs);
+ }
+
+ //! @}
+
//! @name Element Access
//! @{
diff --git a/libs/kstd/kstd/ring_buffer.tests.cpp b/libs/kstd/kstd/ring_buffer.tests.cpp
index 453713ee..3476179e 100644
--- a/libs/kstd/kstd/ring_buffer.tests.cpp
+++ b/libs/kstd/kstd/ring_buffer.tests.cpp
@@ -222,6 +222,17 @@ SCENARIO("Ring Buffer interface types", "[kstd][ring_buffer]")
{
STATIC_REQUIRE(std::is_same_v<buffer::const_reference, decltype(std::declval<buffer const &>().back())>);
}
+
+ THEN("the return type of operator== is `bool`")
+ {
+ STATIC_REQUIRE(std::is_same_v<bool, decltype(std::declval<buffer const &>() == std::declval<buffer const &>())>);
+ }
+
+ THEN("the return type of operator<=> is the same as for the value_type")
+ {
+ STATIC_REQUIRE(std::is_same_v<decltype(std::declval<buffer::value_type>() <=> std::declval<buffer::value_type>()),
+ decltype(std::declval<buffer const &>() <=> std::declval<buffer const &>())>);
+ }
}
}
@@ -1618,7 +1629,7 @@ SCENARIO("Ring Buffer modifiers", "[kstd][ring_buffer]")
}
}
-SCENARIO("Ring Buffer zero capacity", "[kstd][rin_buffer]")
+SCENARIO("Ring Buffer zero capacity", "[kstd][ring_buffer]")
{
GIVEN("A ring buffer with a capacity of 0")
{
@@ -1830,4 +1841,118 @@ SCENARIO("Ring Buffer zero capacity", "[kstd][rin_buffer]")
}
}
}
+}
+
+SCENARIO("Ring Buffer comparison", "[kstd][ring_buffer]")
+{
+ GIVEN("Two ring buffers with the same content, constructed the same way")
+ {
+ auto lhs = kstd::ring_buffer<int, 5>{3, 1};
+ auto rhs = kstd::ring_buffer<int, 5>{3, 1};
+
+ THEN("they compare equal")
+ {
+ REQUIRE(lhs == rhs);
+ }
+
+ THEN("neither is less than the other")
+ {
+ REQUIRE_FALSE(lhs < rhs);
+ REQUIRE_FALSE(rhs < lhs);
+ }
+
+ THEN("they are equivalent under <=>")
+ {
+ REQUIRE((lhs <=> rhs) == 0);
+ }
+ }
+
+ GIVEN("A ring buffer compares equal to itself")
+ {
+ auto buffer = kstd::ring_buffer<int, 5>{3, 1};
+
+ THEN("it compares equal to itself")
+ {
+ REQUIRE(buffer == buffer);
+ }
+ }
+
+ GIVEN("Two empty ring buffers")
+ {
+ auto lhs = kstd::ring_buffer<int, 5>{};
+ auto rhs = kstd::ring_buffer<int, 5>{};
+
+ THEN("they compare equal")
+ {
+ REQUIRE(lhs == rhs);
+ }
+ }
+
+ GIVEN("Two ring buffers with different content")
+ {
+ auto smaller = kstd::ring_buffer<int, 5>{3, 1};
+ auto larger = kstd::ring_buffer<int, 5>{3, 2};
+
+ THEN("they do not compare equal")
+ {
+ REQUIRE_FALSE(smaller == larger);
+ }
+
+ THEN("the one with the smaller elements orders first")
+ {
+ REQUIRE(smaller < larger);
+ REQUIRE_FALSE(larger < smaller);
+ }
+ }
+
+ GIVEN("Two ring buffers holding the same elements with different sizes")
+ {
+ auto shorter = kstd::ring_buffer<int, 5>{2, 1};
+ auto longer = kstd::ring_buffer<int, 5>{3, 1};
+
+ THEN("they do not compare equal")
+ {
+ REQUIRE_FALSE(shorter == longer);
+ }
+
+ THEN("the shorter buffer, being a prefix of the longer one, orders first")
+ {
+ REQUIRE(shorter < longer);
+ }
+ }
+
+ GIVEN("Two ring buffers with the same logical content but different physical layouts")
+ {
+ auto wrapped = kstd::ring_buffer<int, 3>{};
+ wrapped.push_back(1);
+ wrapped.push_back(2);
+ wrapped.push_back(3);
+ wrapped.push_back(4);
+
+ auto fresh = kstd::ring_buffer<int, 3>{};
+ fresh.push_back(2);
+ fresh.push_back(3);
+ fresh.push_back(4);
+
+ THEN("they compare equal despite differing internal layouts")
+ {
+ REQUIRE(wrapped == fresh);
+ }
+
+ THEN("they are equivalent under <=>")
+ {
+ REQUIRE((wrapped <=> fresh) == 0);
+ }
+ }
+
+ GIVEN("Two zero-capacity ring buffers")
+ {
+ auto lhs = kstd::ring_buffer<int, 0>{};
+ auto rhs = kstd::ring_buffer<int, 0>{};
+
+ THEN("they compare equal")
+ {
+ REQUIRE(lhs == rhs);
+ }
+ }
} \ No newline at end of file