diff options
Diffstat (limited to 'libs/kstd')
| -rw-r--r-- | libs/kstd/kstd/ring_buffer.hpp | 55 | ||||
| -rw-r--r-- | libs/kstd/kstd/ring_buffer.tests.cpp | 29 |
2 files changed, 84 insertions, 0 deletions
diff --git a/libs/kstd/kstd/ring_buffer.hpp b/libs/kstd/kstd/ring_buffer.hpp index 0e54c070..151ab994 100644 --- a/libs/kstd/kstd/ring_buffer.hpp +++ b/libs/kstd/kstd/ring_buffer.hpp @@ -1,6 +1,9 @@ #ifndef KSTD_RING_BUFFER_HPP #define KSTD_RING_BUFFER_HPP +#include <kstd/os/error.hpp> + +#include <array> #include <cstddef> namespace kstd @@ -13,8 +16,38 @@ namespace kstd template<typename ValueType, std::size_t Capacity> struct ring_buffer { + using value_type = ValueType; + using pointer = value_type *; + using const_pointer = value_type const *; + using reference = value_type &; + using const_reference = value_type const &; using size_type = std::size_t; + //! @name Element Access + //! @{ + + //! Get the element at the specified index. + //! + //! @param position The zero-based index of the element to get. + //! @return A reference to the element at the given position. + [[nodiscard]] constexpr auto at(size_type position) -> reference + { + panic_on_invalid_index(position); + return *element_at_index(position); + } + + //! Get the element at the specified index. + //! + //! @param position The zero-based index of the element to get. + //! @return A reference to the element at the given position. + [[nodiscard]] constexpr auto at(size_type position) const -> const_reference + { + panic_on_invalid_index(position); + return *element_at_index(position); + } + + //! @} + //! @name Capacity //! @{ @@ -61,6 +94,28 @@ namespace kstd //! @} private: + constexpr auto element_at_index(size_type index) noexcept -> pointer + { + auto base_pointer = reinterpret_cast<pointer>(m_storage.data()); + auto storage_index = (m_tail + index) % capacity(); + return base_pointer + storage_index; + } + + constexpr auto element_at_index(size_type index) const noexcept -> const_pointer + { + return const_cast<ring_buffer *>(this)->element_at_index(index); + } + + constexpr auto panic_on_invalid_index(size_type index) const -> void + { + if (index >= size()) + { + os::panic("[KSTD] Index out-of-bounds in ring_buffer element access!"); + } + } + + //! The underlying storage for the elements of this ring buffer. + alignas(ValueType) std::array<std::byte, sizeof(value_type) * Capacity> m_storage{}; //! The index of the element that was most recently added to this ring buffer. size_type m_head{}; //! The index of the element that was least recently added to this ring buffer. diff --git a/libs/kstd/kstd/ring_buffer.tests.cpp b/libs/kstd/kstd/ring_buffer.tests.cpp index 6e936248..86ff4b30 100644 --- a/libs/kstd/kstd/ring_buffer.tests.cpp +++ b/libs/kstd/kstd/ring_buffer.tests.cpp @@ -1,6 +1,10 @@ #include <kstd/ring_buffer.hpp> +#include <kstd/test_support/os_panic.hpp> + #include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers.hpp> +#include <catch2/matchers/catch_matchers_exception.hpp> SCENARIO("Ring Buffer initialization and construction", "[ring_buffer]") { @@ -31,4 +35,29 @@ SCENARIO("Ring Buffer initialization and construction", "[ring_buffer]") } } } +} + +SCENARIO("Ring Buffer element access", "[kstd][ring_buffer]") +{ + GIVEN("An empty ring buffer") + { + auto buffer = kstd::ring_buffer<int, 5>{}; + + THEN("accessing element 0 panics") + { + REQUIRE_THROWS_MATCHES(buffer.at(0), kstd::tests::os_panic, + Catch::Matchers::Message("[KSTD] Index out-of-bounds in ring_buffer element access!")); + } + + WHEN("working through a const reference") + { + auto const & ref = buffer; + + THEN("accessing element 0 panics") + { + REQUIRE_THROWS_MATCHES(ref.at(0), kstd::tests::os_panic, + Catch::Matchers::Message("[KSTD] Index out-of-bounds in ring_buffer element access!")); + } + } + } }
\ No newline at end of file |
