From e2b4e4160a2ef87db8d84328ef62d19d00c29e22 Mon Sep 17 00:00:00 2001 From: Joshua DeWeese Date: Tue, 29 Aug 2023 14:48:38 -0400 Subject: [PATCH 1/4] core/lib/cib: apply doc best practice This patch updates the doxygen comments to follow suggested practice of using retval. --- core/lib/include/cib.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/lib/include/cib.h b/core/lib/include/cib.h index 5e304e55106e..c807b6049b48 100644 --- a/core/lib/include/cib.h +++ b/core/lib/include/cib.h @@ -107,7 +107,8 @@ static inline unsigned int cib_full(const cib_t *cib) * * @param[in,out] cib corresponding *cib* to buffer. * Must not be NULL. - * @return index of next item, -1 if the buffer is empty + * @return index of next item + * @retval -1 if the buffer is empty */ static inline int cib_get(cib_t *__restrict cib) { @@ -153,7 +154,8 @@ static inline int cib_get_unsafe(cib_t *cib) * * @param[in,out] cib corresponding *cib* to buffer. * Must not be NULL. - * @return index of item to put to, -1 if the buffer is full + * @return index of item to put to + * @retval -1 if the buffer is full */ static inline int cib_put(cib_t *__restrict cib) { From 45f865965f048fb0c07f7a4b00150a6c2440e53a Mon Sep 17 00:00:00 2001 From: Joshua DeWeese Date: Tue, 29 Aug 2023 14:50:44 -0400 Subject: [PATCH 2/4] core/lib/cib: remove magic number from unit test --- tests/unittests/tests-core/tests-core-cib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unittests/tests-core/tests-core-cib.c b/tests/unittests/tests-core/tests-core-cib.c index b0c685d7fd5f..155c58d4ef14 100644 --- a/tests/unittests/tests-core/tests-core-cib.c +++ b/tests/unittests/tests-core/tests-core-cib.c @@ -45,8 +45,8 @@ static void test_cib_get__overflow(void) cib.read_count = UINT_MAX; cib.write_count = UINT_MAX; - TEST_ASSERT_EQUAL_INT(3, cib_put(&cib)); - TEST_ASSERT_EQUAL_INT(3, cib_get(&cib)); + TEST_ASSERT_EQUAL_INT(TEST_CIB_SIZE-1, cib_put(&cib)); + TEST_ASSERT_EQUAL_INT(TEST_CIB_SIZE-1, cib_get(&cib)); } static void test_cib_peek(void) @@ -69,8 +69,8 @@ static void test_cib_peek__overflow(void) cib.read_count = UINT_MAX; cib.write_count = UINT_MAX; - TEST_ASSERT_EQUAL_INT(3, cib_put(&cib)); - TEST_ASSERT_EQUAL_INT(3, cib_peek(&cib)); + TEST_ASSERT_EQUAL_INT(TEST_CIB_SIZE-1, cib_put(&cib)); + TEST_ASSERT_EQUAL_INT(TEST_CIB_SIZE-1, cib_peek(&cib)); } static void test_cib_avail(void) From 45752a300207ea8230069dc892f5a4c0a8478368 Mon Sep 17 00:00:00 2001 From: Joshua DeWeese Date: Tue, 29 Aug 2023 14:51:57 -0400 Subject: [PATCH 3/4] core/lib/cib: remove superfluous init This patch removes a superfluous init of the cib. The struct is already initialized by the test fixture's setup function. --- tests/unittests/tests-core/tests-core-cib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unittests/tests-core/tests-core-cib.c b/tests/unittests/tests-core/tests-core-cib.c index 155c58d4ef14..40d3a69ea69d 100644 --- a/tests/unittests/tests-core/tests-core-cib.c +++ b/tests/unittests/tests-core/tests-core-cib.c @@ -51,7 +51,6 @@ static void test_cib_get__overflow(void) static void test_cib_peek(void) { - cib_init(&cib, TEST_CIB_SIZE); TEST_ASSERT_EQUAL_INT(-1, cib_peek(&cib)); TEST_ASSERT_EQUAL_INT(0, cib_put(&cib)); TEST_ASSERT_EQUAL_INT(0, cib_peek(&cib)); From b6481654ba03bdcbffd260e052a12a3fef7a0906 Mon Sep 17 00:00:00 2001 From: Joshua DeWeese Date: Tue, 29 Aug 2023 14:39:37 -0400 Subject: [PATCH 4/4] core/lib/cib: add several new peek functions This patch adds calls to be able to peek at items other than just the oldest item in a cib based FIFO. It also adds an "unsafe" peek to match the existing "unsafe" put and get functions. --- core/lib/include/cib.h | 65 +++++++++++++++-- tests/unittests/tests-core/tests-core-cib.c | 78 +++++++++++++++++++++ 2 files changed, 138 insertions(+), 5 deletions(-) diff --git a/core/lib/include/cib.h b/core/lib/include/cib.h index c807b6049b48..9d3b8e98dc9e 100644 --- a/core/lib/include/cib.h +++ b/core/lib/include/cib.h @@ -120,21 +120,76 @@ static inline int cib_get(cib_t *__restrict cib) } /** - * @brief Get the index of the next item in buffer without removing it. + * @brief Get the index of an item in the buffer without removing anything. + * + * Offset 0 is the next item in the buffer that would be returned by + * `cip_get()`, offset 1 would be the following, and so on. + * + * Unsafe version, *must not* pass an offset that is larger than the number of + * items currently in the buffer! * * @param[in,out] cib corresponding *cib* to buffer. * Must not be NULL. - * @return index of next item, -1 if the buffer is empty + * @param[in] offset offset from front of buffer + * + * @return index of item + * @retval -1 if no item at @p offset exists in the buffer */ -static inline int cib_peek(cib_t *__restrict cib) +static inline int cib_peek_at_unsafe(cib_t *__restrict cib, unsigned offset) { - if (cib_avail(cib)) { - return (int)(cib->read_count & cib->mask); + return (cib->read_count + offset) & cib->mask; +} + +/** + * @brief Get the index of an item in the buffer without removing anything. + * + * Offset 0 is the next item in the buffer that would be returned by + * `cip_get()`, offset 1 would be the following, and so on. + * + * @param[in,out] cib corresponding *cib* to buffer. + * Must not be NULL. + * @param[in] offset offset from front of buffer + * + * @return index of item + * @retval -1 if no item at @p offset exists in the buffer + */ +static inline int cib_peek_at(cib_t *__restrict cib, unsigned offset) +{ + if (offset < cib_avail(cib)) { + return cib_peek_at_unsafe(cib, offset); } return -1; } +/** + * @brief Get the index of the next item in buffer without removing it. + * + * Unsafe version, *must not* be called if buffer is empty! + * + * @param[in,out] cib corresponding *cib* to buffer. + * Must not be NULL. + * @return index of next item + * @retval -1 if the buffer is empty + */ +static inline int cib_peek_unsafe(cib_t *__restrict cib) +{ + return cib_peek_at_unsafe(cib, 0); +} + +/** + * @brief Get the index of the next item in buffer without removing it. + * + * @param[in,out] cib corresponding *cib* to buffer. + * Must not be NULL. + * @return index of next item + * @retval -1 if the buffer is empty + */ +static inline int cib_peek(cib_t *__restrict cib) +{ + return cib_peek_at(cib, 0); +} + /** * @brief Get the index of the next item in buffer. * diff --git a/tests/unittests/tests-core/tests-core-cib.c b/tests/unittests/tests-core/tests-core-cib.c index 40d3a69ea69d..7c5d70ddbfe9 100644 --- a/tests/unittests/tests-core/tests-core-cib.c +++ b/tests/unittests/tests-core/tests-core-cib.c @@ -72,6 +72,83 @@ static void test_cib_peek__overflow(void) TEST_ASSERT_EQUAL_INT(TEST_CIB_SIZE-1, cib_peek(&cib)); } +static void test_cib_peek_at(void) +{ + /* Peeking an empty cib should give an error */ + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 0)); + + /* Put 1 item in cib and check that we can peek it */ + TEST_ASSERT_EQUAL_INT( 0, cib_put(&cib)); + TEST_ASSERT_EQUAL_INT( 0, cib_peek(&cib)); + TEST_ASSERT_EQUAL_INT( 0, cib_peek_at(&cib, 0)); + + /* Peek past the end should give an error. */ + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 1)); + + /* Put another item in cib. */ + TEST_ASSERT_EQUAL_INT( 1, cib_put(&cib)); + + /* cib should now hold the indices { 0, 1 }. Test this. */ + TEST_ASSERT_EQUAL_INT( 0, cib_peek(&cib)); + TEST_ASSERT_EQUAL_INT( 0, cib_peek_at(&cib, 0)); + TEST_ASSERT_EQUAL_INT( 1, cib_peek_at(&cib, 1)); + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 2)); + + /* Put another item in cib. */ + TEST_ASSERT_EQUAL_INT( 2, cib_put(&cib)); + + /* cib should now hold the indices { 0, 1, 2 }. Test this. */ + TEST_ASSERT_EQUAL_INT( 0, cib_peek(&cib)); + TEST_ASSERT_EQUAL_INT( 0, cib_peek_at(&cib, 0)); + TEST_ASSERT_EQUAL_INT( 1, cib_peek_at(&cib, 1)); + TEST_ASSERT_EQUAL_INT( 2, cib_peek_at(&cib, 2)); + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 3)); + + /* Put another item in cib. */ + TEST_ASSERT_EQUAL_INT( 3, cib_put(&cib)); + + /* cib should now hold the indices { 0, 1, 2, 3 }. Test this. */ + TEST_ASSERT_EQUAL_INT( 0, cib_peek(&cib)); + TEST_ASSERT_EQUAL_INT( 0, cib_peek_at(&cib, 0)); + TEST_ASSERT_EQUAL_INT( 1, cib_peek_at(&cib, 1)); + TEST_ASSERT_EQUAL_INT( 2, cib_peek_at(&cib, 2)); + TEST_ASSERT_EQUAL_INT( 3, cib_peek_at(&cib, 3)); + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 4)); + + /* Remove an item from cib. */ + TEST_ASSERT_EQUAL_INT( 0, cib_get(&cib)); + + /* cib should now hold the indices { 1, 2, 3 }. Test this. */ + TEST_ASSERT_EQUAL_INT( 1, cib_peek(&cib)); + TEST_ASSERT_EQUAL_INT( 1, cib_peek_at(&cib, 0)); + TEST_ASSERT_EQUAL_INT( 2, cib_peek_at(&cib, 1)); + TEST_ASSERT_EQUAL_INT( 3, cib_peek_at(&cib, 2)); + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 3)); + + /* Remove another item from cib. */ + TEST_ASSERT_EQUAL_INT( 1, cib_get(&cib)); + + /* cib should now hold the indices { 2, 3 }. Test this. */ + TEST_ASSERT_EQUAL_INT( 2, cib_peek(&cib)); + TEST_ASSERT_EQUAL_INT( 2, cib_peek_at(&cib, 0)); + TEST_ASSERT_EQUAL_INT( 3, cib_peek_at(&cib, 1)); + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 2)); + + /* Remove another item from cib. */ + TEST_ASSERT_EQUAL_INT( 2, cib_get(&cib)); + + /* cib should now hold the indices { 3 }. Test this. */ + TEST_ASSERT_EQUAL_INT( 3, cib_peek(&cib)); + TEST_ASSERT_EQUAL_INT( 3, cib_peek_at(&cib, 0)); + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 1)); + + /* Remove last item from cib. */ + TEST_ASSERT_EQUAL_INT( 3, cib_get(&cib)); + + /* Peeking an empty cib should give an error */ + TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 0)); +} + static void test_cib_avail(void) { TEST_ASSERT_EQUAL_INT(0, cib_avail(&cib)); @@ -111,6 +188,7 @@ Test *tests_core_cib_tests(void) new_TestFixture(test_singleton_cib), new_TestFixture(test_cib_peek), new_TestFixture(test_cib_peek__overflow), + new_TestFixture(test_cib_peek_at), }; EMB_UNIT_TESTCALLER(core_cib_tests, set_up, NULL, fixtures);