diff --git a/core/include/clist.h b/core/include/clist.h index 33eb237d31..27853e0fcd 100644 --- a/core/include/clist.h +++ b/core/include/clist.h @@ -34,6 +34,8 @@ * clist_sort() | O(NlogN)| sort list (stable) * clist_count() | O(n) | count the number of elements in a list * clist_is_empty() | O(1) | returns true if the list contains no elements + * clist_exactly_one() | O(1) | returns true if the list contains one element + * clist_more_than_one()| O(1) | returns true if the list contains more than one element * * clist can be used as a traditional list, a queue (FIFO) and a stack (LIFO) using * fast O(1) operations. @@ -388,8 +390,8 @@ typedef int (*clist_cmp_func_t)(clist_node_t *a, clist_node_t *b); * * @internal * - * @param[in] list ptr to first element of list - * @param[in] cmp comparison function + * @param[in] list_head ptr to the first element inside a clist + * @param[in] cmp comparison function * * @returns ptr to *last* element in list */ @@ -447,7 +449,7 @@ static inline void clist_sort(clist_node_t *list, clist_cmp_func_t cmp) /** * @brief Count the number of items in the given list * - * @param[in] list ptr to the first element of the list + * @param[in] list ptr to the clist * * @return the number of elements in the given list */ @@ -466,6 +468,34 @@ static inline size_t clist_count(clist_node_t *list) return cnt; } +/** + * @brief Tells if a list has exactly one element + * + * @note Complexity: O(1) + * + * @param[in] list Pointer to the clist + * + * @retval true If list has exactly one element + */ +static inline bool clist_exactly_one(clist_node_t *list) +{ + return !clist_is_empty(list) && (list->next == list->next->next); +} + +/** + * @brief Tells if a list has more than one element + * + * @note Complexity: O(1) + * + * @param[in] list Pointer to the clist + * + * @retval true If list has more than one element + */ +static inline bool clist_more_than_one(clist_node_t *list) +{ + return !clist_is_empty(list) && (list->next != list->next->next); +} + #ifdef __cplusplus } #endif diff --git a/tests/unittests/tests-core/tests-core-clist.c b/tests/unittests/tests-core/tests-core-clist.c index 6c18384916..81a401a099 100644 --- a/tests/unittests/tests-core/tests-core-clist.c +++ b/tests/unittests/tests-core/tests-core-clist.c @@ -348,6 +348,45 @@ static void test_clist_is_empty(void) } } +static void test_clist_special_cardinality(void) +{ + unsigned i = 0; + TEST_ASSERT(clist_is_empty(&test_clist)); + TEST_ASSERT(!clist_exactly_one(&test_clist)); + TEST_ASSERT(!clist_more_than_one(&test_clist)); + + clist_rpush(&test_clist, &tests_clist_buf[i++]); + + TEST_ASSERT(!clist_is_empty(&test_clist)); + TEST_ASSERT(clist_exactly_one(&test_clist)); + TEST_ASSERT(!clist_more_than_one(&test_clist)); + + while (i < TEST_CLIST_LEN) { + clist_rpush(&test_clist, &tests_clist_buf[i++]); + + TEST_ASSERT(!clist_is_empty(&test_clist)); + TEST_ASSERT(!clist_exactly_one(&test_clist)); + TEST_ASSERT(clist_more_than_one(&test_clist)); + } + do { + TEST_ASSERT(!clist_is_empty(&test_clist)); + TEST_ASSERT(!clist_exactly_one(&test_clist)); + TEST_ASSERT(clist_more_than_one(&test_clist)); + + clist_lpop(&test_clist); + } while (--i > 1); + + TEST_ASSERT(!clist_is_empty(&test_clist)); + TEST_ASSERT(clist_exactly_one(&test_clist)); + TEST_ASSERT(!clist_more_than_one(&test_clist)); + + clist_lpop(&test_clist); + + TEST_ASSERT(clist_is_empty(&test_clist)); + TEST_ASSERT(!clist_exactly_one(&test_clist)); + TEST_ASSERT(!clist_more_than_one(&test_clist)); +} + Test *tests_core_clist_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { @@ -367,6 +406,7 @@ Test *tests_core_clist_tests(void) new_TestFixture(test_clist_sort), new_TestFixture(test_clist_count), new_TestFixture(test_clist_is_empty), + new_TestFixture(test_clist_special_cardinality), }; EMB_UNIT_TESTCALLER(core_clist_tests, set_up, NULL,