From 45a1f58d7e99fcb600616ddf6ae1754514d84858 Mon Sep 17 00:00:00 2001 From: Mike Bloom <91038685+mike919192@users.noreply.github.com> Date: Mon, 12 Oct 2026 13:40:56 -0400 Subject: [PATCH] Deque check index operator (#1617) * Add docs and tutorial for etl::intrusive_avl_tree (#1608) * Add docs and tutorial for etl::intrusive_avl_tree Documents the intrusive AVL tree added in PR #1425: a full API reference page under Containers/Trees, and a tutorial demonstrating ordered access to intrusively-linked objects with unpredictable lifetimes, including move support and destructor-driven automatic removal from the tree. Co-Authored-By: Claude Sonnet 5 * Add complexity shortcode and document its usage Introduces a {{< complexity >}} Hugo shortcode (with light/dark styling for constant/logarithmic/linear/linearithmic/polynomial/exponential classes) for rendering Big-O complexity inline, applies it throughout the intrusive_avl_tree API reference in place of raw "O(...)" text, and documents the Description/Complexity structure and supported classes in DOCUMENTATION.md. Co-Authored-By: Claude Sonnet 5 * Fix issues found by @CodeRabbit * Put complexity notes on their own lines in intrusive_avl_tree docs Move the complexity shortcode from the inline "**Complexity:**" label to its own line under a "**Complexity**" label. Notes that give several alternatives (e.g. amortized vs. worst-case) now show each one on a separate line. Update the guideline in DOCUMENTATION.md to match. * Update complexity examples in DOCUMENTATION.md Add the hard line break after the "**Complexity**" label in the example, and rewrite the list of supported complexity classes in the new two-line format, including an example with several alternatives. * Add logarithmic complexity example to DOCUMENTATION.md --------- Co-authored-by: Claude Sonnet 5 Co-authored-by: John Wellbelove * Updated sponsors pages * Refactor the documentation css to group styles for light and dark themes * Update Codacy badge in README.md Updated Codacy badge link to reflect new project status. * Fix Codacy badge display * refresh codacy integration status * deque check index operator * Revert format * Update documentation * Change word 'array' to 'deque' * Add checked index for circular buffer * Fix doc --------- Co-authored-by: Sergei Co-authored-by: Claude Sonnet 5 Co-authored-by: John Wellbelove Co-authored-by: John Wellbelove --- .../queues & stacks/circular-buffer.md | 1 + docs/containers/queues & stacks/deque.md | 3 +- include/etl/circular_buffer.h | 17 ++++++++++ include/etl/deque.h | 4 +++ test/test_circular_buffer.cpp | 4 +++ test/test_deque.cpp | 32 +++++++++++++++++++ 6 files changed, 60 insertions(+), 1 deletion(-) diff --git a/docs/containers/queues & stacks/circular-buffer.md b/docs/containers/queues & stacks/circular-buffer.md index 3c3faf2a..8bc2017c 100644 --- a/docs/containers/queues & stacks/circular-buffer.md +++ b/docs/containers/queues & stacks/circular-buffer.md @@ -123,6 +123,7 @@ const_reference operator[](size_t i) const ``` **Description** Returns a reference or const reference to the indexed element. +Emits an `etl::circular_buffer_out_of_bounds` if ETL_CHECK_INDEX_OPERATOR is defined and the index is out of range of the circular buffer. Undefined behaviour if asserts or exceptions are not enabled. --- diff --git a/docs/containers/queues & stacks/deque.md b/docs/containers/queues & stacks/deque.md index b0bb1ad1..9b124338 100644 --- a/docs/containers/queues & stacks/deque.md +++ b/docs/containers/queues & stacks/deque.md @@ -92,7 +92,7 @@ const T& at(size_t i) const ``` **Description** Returns a reference or const reference to the indexed element. -Emits an `etl::deque_out_of_range` if the index is out of range of the array. Undefined behaviour if asserts or exceptions are not enabled. +Emits an `etl::deque_out_of_bounds` if the index is out of range of the deque. Undefined behaviour if asserts or exceptions are not enabled. --- @@ -102,6 +102,7 @@ const T& operator[](size_t i) const ``` **Description** Returns a reference or const reference to the indexed element. +Emits an `etl::deque_out_of_bounds` if ETL_CHECK_INDEX_OPERATOR is defined and the index is out of range of the deque. Undefined behaviour if asserts or exceptions are not enabled. --- diff --git a/include/etl/circular_buffer.h b/include/etl/circular_buffer.h index b0586cfb..c820e09f 100644 --- a/include/etl/circular_buffer.h +++ b/include/etl/circular_buffer.h @@ -83,6 +83,19 @@ namespace etl } }; + //*************************************************************************** + /// circular_buffer out of bounds exception. + //*************************************************************************** + class circular_buffer_out_of_bounds : public etl::circular_buffer_exception + { + public: + + circular_buffer_out_of_bounds(string_type file_name_, numeric_type line_number_) + : etl::circular_buffer_exception(ETL_ERROR_TEXT("circular_buffer:bounds", ETL_CIRCULAR_BUFFER_FILE_ID"C"), file_name_, line_number_) + { + } + }; + //*************************************************************************** /// //*************************************************************************** @@ -888,6 +901,8 @@ namespace etl //************************************************************************* reference operator[](size_t index) { + ETL_ASSERT_CHECK_INDEX_OPERATOR(index < size(), ETL_ERROR(circular_buffer_out_of_bounds)); + return pbuffer[(out + index) % buffer_size]; } @@ -897,6 +912,8 @@ namespace etl //************************************************************************* const_reference operator[](size_t index) const { + ETL_ASSERT_CHECK_INDEX_OPERATOR(index < size(), ETL_ERROR(circular_buffer_out_of_bounds)); + return pbuffer[(out + index) % buffer_size]; } diff --git a/include/etl/deque.h b/include/etl/deque.h index c3ff33d9..918fa4ab 100644 --- a/include/etl/deque.h +++ b/include/etl/deque.h @@ -791,6 +791,8 @@ namespace etl //************************************************************************* reference operator[](size_t index) { + ETL_ASSERT_CHECK_INDEX_OPERATOR(index < current_size, ETL_ERROR(deque_out_of_bounds)); + iterator result(_begin); result += static_cast(index); @@ -803,6 +805,8 @@ namespace etl //************************************************************************* const_reference operator[](size_t index) const { + ETL_ASSERT_CHECK_INDEX_OPERATOR(index < current_size, ETL_ERROR(deque_out_of_bounds)); + iterator result(_begin); result += static_cast(index); diff --git a/test/test_circular_buffer.cpp b/test/test_circular_buffer.cpp index cdbd162d..bb48c636 100644 --- a/test/test_circular_buffer.cpp +++ b/test/test_circular_buffer.cpp @@ -647,6 +647,8 @@ namespace { CHECK_EQUAL(input2[i], data[i]); } + + CHECK_THROW(data[data.size()], etl::circular_buffer_out_of_bounds); } //************************************************************************* @@ -662,6 +664,8 @@ namespace { CHECK_EQUAL(input[i + 3], data[i]); } + + CHECK_THROW(data[data.size()], etl::circular_buffer_out_of_bounds); } //************************************************************************* diff --git a/test/test_deque.cpp b/test/test_deque.cpp index d03580bd..5b4c75ff 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -394,6 +394,14 @@ namespace CHECK_EQUAL(compare_data.at(5), data.at(5)); } + //************************************************************************* + TEST(test_at_out_of_bounds) + { + DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.at(data.size()), etl::deque_out_of_bounds); + } + //************************************************************************* TEST(test_at_const) { @@ -408,6 +416,14 @@ namespace CHECK_EQUAL(compare_data.at(5), data.at(5)); } + //************************************************************************* + TEST(test_at_const_out_of_bounds) + { + const DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.at(data.size()), etl::deque_out_of_bounds); + } + //************************************************************************* TEST(test_index_operator) { @@ -422,6 +438,14 @@ namespace CHECK_EQUAL(compare_data[5], data[5]); } + //************************************************************************* + TEST(test_index_operator_out_of_bounds) + { + DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data[data.size()], etl::deque_out_of_bounds); + } + //************************************************************************* TEST(test_index_operator_const) { @@ -436,6 +460,14 @@ namespace CHECK_EQUAL(compare_data[5], data[5]); } + //************************************************************************* + TEST(test_index_operator_const_out_of_bounds) + { + const DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data[data.size()], etl::deque_out_of_bounds); + } + //************************************************************************* TEST(test_front) {