From 64ae22a093ce1c4df7d6d287aff6e99d41069dec Mon Sep 17 00:00:00 2001 From: rolandreichweinbmw Date: Sat, 1 Mar 2025 19:24:30 +0100 Subject: [PATCH 1/3] Intrusive forward list add remove by pointer (#1026) * Add intrusive_forward_list::remove() element by pointer * Add test --- include/etl/intrusive_forward_list.h | 23 ++++++++++++++++++++++ test/test_intrusive_forward_list.cpp | 29 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/etl/intrusive_forward_list.h b/include/etl/intrusive_forward_list.h index 12e3c3d3..307f110b 100644 --- a/include/etl/intrusive_forward_list.h +++ b/include/etl/intrusive_forward_list.h @@ -1011,6 +1011,29 @@ namespace etl } } + //************************************************************************* + // Removes the element specified by pointer. + //************************************************************************* + void remove(const_pointer element) + { + iterator i_item = begin(); + iterator i_last_item = before_begin(); + + while (i_item != end()) + { + if (&i_item == element) + { + i_item = erase_after(i_last_item); + return; + } + else + { + ++i_item; + ++i_last_item; + } + } + } + //************************************************************************* /// Removes according to a predicate. //************************************************************************* diff --git a/test/test_intrusive_forward_list.cpp b/test/test_intrusive_forward_list.cpp index 84bfa139..a7d21da8 100644 --- a/test/test_intrusive_forward_list.cpp +++ b/test/test_intrusive_forward_list.cpp @@ -966,6 +966,35 @@ namespace CHECK_EQUAL(sorted_data.size(), size_t(std::distance(data1.begin(), data1.end()))); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_remove_by_pointer) + { + std::forward_list compare_data(sorted_data.begin(), sorted_data.end()); + DataNDC0 data0(sorted_data.begin(), sorted_data.end()); + DataNDC1 data1(sorted_data.begin(), sorted_data.end()); + + auto it = data0.begin(); + for (int i = 0; i < 7; ++i) + { + it++; + } + ItemNDCNode* element = ⁢ + + compare_data.remove(ItemNDCNode("7")); + data0.remove(*element); + + bool are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin()); + + CHECK(are_equal); + CHECK_EQUAL(size_t(std::distance(compare_data.begin(), compare_data.end())), data0.size()); + CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end())); + + are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin()); + CHECK(are_equal); + CHECK_EQUAL(sorted_data.size(), data1.size()); + CHECK_EQUAL(sorted_data.size(), size_t(std::distance(data1.begin(), data1.end()))); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_remove_if) { From 12743be9e29127686f1c1c66a951700ac1ba687a Mon Sep 17 00:00:00 2001 From: rolandreichweinbmw Date: Sun, 2 Mar 2025 12:09:32 +0100 Subject: [PATCH 2/3] Add contains() and contains_node() to etl::intrusive_forward_list and etl::intrusive_list (#1036) Co-authored-by: John Wellbelove --- include/etl/intrusive_forward_list.h | 42 ++++++++++++++++ include/etl/intrusive_list.h | 44 ++++++++++++++++- test/test_intrusive_forward_list.cpp | 72 ++++++++++++++++++++++++++++ test/test_intrusive_list.cpp | 72 ++++++++++++++++++++++++++++ 4 files changed, 229 insertions(+), 1 deletion(-) diff --git a/include/etl/intrusive_forward_list.h b/include/etl/intrusive_forward_list.h index 307f110b..238aca10 100644 --- a/include/etl/intrusive_forward_list.h +++ b/include/etl/intrusive_forward_list.h @@ -253,6 +253,27 @@ namespace etl return current_size; } + //************************************************************************* + /// Detects existence of specified node in list. + ///\param search_link The node to find in list + //************************************************************************* + bool contains_node(const link_type& search_link) const + { + const link_type* p_link = start.etl_next; + + while (p_link != ETL_NULLPTR) + { + if (&search_link == p_link) + { + return true; + } + + p_link = p_link->link_type::etl_next; + } + + return false; + } + protected: link_type start; ///< The link pointer that acts as the intrusive_forward_list start. @@ -1210,6 +1231,27 @@ namespace etl } } + //************************************************************************* + /// Detects existence of specified value in list. + ///\param value The value to find in list + //************************************************************************* + bool contains(const_reference value) const + { + const_iterator i_item = begin(); + + while (i_item != end()) + { + if (*i_item == value) + { + return true; + } + + ++i_item; + } + + return false; + } + private: #if ETL_USING_CPP17 diff --git a/include/etl/intrusive_list.h b/include/etl/intrusive_list.h index 49bfea05..673852c1 100644 --- a/include/etl/intrusive_list.h +++ b/include/etl/intrusive_list.h @@ -255,6 +255,27 @@ namespace etl return current_size; } + //************************************************************************* + /// Detects existence of specified node in list. + ///\param search_link The node to find in list + //************************************************************************* + bool contains_node(link_type& search_link) const + { + link_type* p_link = terminal_link.link_type::etl_next; + + while (p_link != &terminal_link) + { + if (&search_link == p_link) + { + return true; + } + + p_link = p_link->link_type::etl_next; + } + + return false; + } + protected: /// The link that acts as the intrusive_list start & end. @@ -404,7 +425,7 @@ namespace etl { link_type* result = ETL_NULLPTR; - if (is_link_in_list(link)) + if (contains_node(link)) { link_type* p_next = link->etl_next; @@ -1218,6 +1239,27 @@ namespace etl } } + //************************************************************************* + /// Detects existence of specified value in list. + ///\param value The value to find in list + //************************************************************************* + bool contains(const_reference value) const + { + const_iterator i_item = begin(); + + while (i_item != end()) + { + if (*i_item == value) + { + return true; + } + + ++i_item; + } + + return false; + } + private: #if ETL_USING_CPP17 diff --git a/test/test_intrusive_forward_list.cpp b/test/test_intrusive_forward_list.cpp index a7d21da8..d39ca7dc 100644 --- a/test/test_intrusive_forward_list.cpp +++ b/test/test_intrusive_forward_list.cpp @@ -1302,5 +1302,77 @@ namespace CHECK_EQUAL(size_t(std::distance(compare0.begin(), compare0.end())), data0.size()); CHECK_EQUAL(size_t(std::distance(compare1.begin(), compare1.end())), data1.size()); } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_contains_node) + { + static ItemNDCNode node0("0"); + static ItemNDCNode node1("1"); + static ItemNDCNode node2("2"); + static ItemNDCNode node3("3"); + static ItemNDCNode node4("4"); + static ItemNDCNode node5("5"); + static ItemNDCNode node6("6"); + static ItemNDCNode node7("7"); + static ItemNDCNode node8("8"); + static ItemNDCNode node9("9"); + + DataNDC0 data0; + + data0.push_front(node0); + data0.push_front(node1); + data0.push_front(node2); + data0.push_front(node3); + data0.push_front(node4); + data0.push_front(node5); + + CHECK_TRUE(data0.contains_node(node0)); + CHECK_TRUE(data0.contains_node(node1)); + CHECK_TRUE(data0.contains_node(node2)); + CHECK_TRUE(data0.contains_node(node3)); + CHECK_TRUE(data0.contains_node(node4)); + CHECK_TRUE(data0.contains_node(node5)); + + CHECK_FALSE(data0.contains_node(node6)); + CHECK_FALSE(data0.contains_node(node7)); + CHECK_FALSE(data0.contains_node(node8)); + CHECK_FALSE(data0.contains_node(node9)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_contains) + { + static ItemNDCNode node0("0"); + static ItemNDCNode node1("1"); + static ItemNDCNode node2("2"); + static ItemNDCNode node3("3"); + static ItemNDCNode node4("4"); + static ItemNDCNode node5("5"); + static ItemNDCNode node6("6"); + static ItemNDCNode node7("7"); + static ItemNDCNode node8("8"); + static ItemNDCNode node9("9"); + + DataNDC0 data0; + + data0.push_front(node0); + data0.push_front(node1); + data0.push_front(node2); + data0.push_front(node3); + data0.push_front(node4); + data0.push_front(node5); + + CHECK_TRUE(data0.contains(ItemNDCNode("0"))); + + ItemNDCNode compare_node1("1"); + + CHECK_TRUE(data0.contains(compare_node1)); + + CHECK_FALSE(data0.contains(ItemNDCNode("6"))); + + ItemNDCNode compare_node2("7"); + + CHECK_FALSE(data0.contains(compare_node2)); + } }; } diff --git a/test/test_intrusive_list.cpp b/test/test_intrusive_list.cpp index 8006af29..9d5a08db 100644 --- a/test/test_intrusive_list.cpp +++ b/test/test_intrusive_list.cpp @@ -1519,5 +1519,77 @@ namespace CHECK_EQUAL(data0.size(), compare0.size()); CHECK_EQUAL(data1.size(), compare1.size()); } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_contains_node) + { + static ItemNDCNode node0("0"); + static ItemNDCNode node1("1"); + static ItemNDCNode node2("2"); + static ItemNDCNode node3("3"); + static ItemNDCNode node4("4"); + static ItemNDCNode node5("5"); + static ItemNDCNode node6("6"); + static ItemNDCNode node7("7"); + static ItemNDCNode node8("8"); + static ItemNDCNode node9("9"); + + DataNDC0 data0; + + data0.push_front(node0); + data0.push_front(node1); + data0.push_front(node2); + data0.push_front(node3); + data0.push_front(node4); + data0.push_front(node5); + + CHECK_TRUE(data0.contains_node(node0)); + CHECK_TRUE(data0.contains_node(node1)); + CHECK_TRUE(data0.contains_node(node2)); + CHECK_TRUE(data0.contains_node(node3)); + CHECK_TRUE(data0.contains_node(node4)); + CHECK_TRUE(data0.contains_node(node5)); + + CHECK_FALSE(data0.contains_node(node6)); + CHECK_FALSE(data0.contains_node(node7)); + CHECK_FALSE(data0.contains_node(node8)); + CHECK_FALSE(data0.contains_node(node9)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_contains) + { + static ItemNDCNode node0("0"); + static ItemNDCNode node1("1"); + static ItemNDCNode node2("2"); + static ItemNDCNode node3("3"); + static ItemNDCNode node4("4"); + static ItemNDCNode node5("5"); + static ItemNDCNode node6("6"); + static ItemNDCNode node7("7"); + static ItemNDCNode node8("8"); + static ItemNDCNode node9("9"); + + DataNDC0 data0; + + data0.push_front(node0); + data0.push_front(node1); + data0.push_front(node2); + data0.push_front(node3); + data0.push_front(node4); + data0.push_front(node5); + + CHECK_TRUE(data0.contains(ItemNDCNode("0"))); + + ItemNDCNode compare_node1("1"); + + CHECK_TRUE(data0.contains(compare_node1)); + + CHECK_FALSE(data0.contains(ItemNDCNode("6"))); + + ItemNDCNode compare_node2("7"); + + CHECK_FALSE(data0.contains(compare_node2)); + } }; } From 6124367f2872be5597c08e6cfebc9122e8189abe Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 2 Mar 2025 12:51:17 +0000 Subject: [PATCH 3/3] Integration of contains and contains_node --- include/etl/intrusive_forward_list.h | 25 +++++++++++-------------- include/etl/intrusive_list.h | 25 +++++++++++-------------- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/include/etl/intrusive_forward_list.h b/include/etl/intrusive_forward_list.h index 238aca10..6cb44280 100644 --- a/include/etl/intrusive_forward_list.h +++ b/include/etl/intrusive_forward_list.h @@ -259,19 +259,16 @@ namespace etl //************************************************************************* bool contains_node(const link_type& search_link) const { - const link_type* p_link = start.etl_next; + return is_link_in_list(&search_link); + } - while (p_link != ETL_NULLPTR) - { - if (&search_link == p_link) - { - return true; - } - - p_link = p_link->link_type::etl_next; - } - - return false; + //************************************************************************* + /// Detects existence of specified node in list. + ///\param search_link The node to find in list + //************************************************************************* + bool contains_node(const link_type* search_link) const + { + return is_link_in_list(search_link); } protected: @@ -359,10 +356,10 @@ namespace etl /// Tests if the link is in this list. /// Returns the previous link to it, if found, otherwise ETL_NULLPTR. //************************************************************************* - link_type* is_link_in_list(const link_type* search_link) + link_type* is_link_in_list(const link_type* search_link) const { link_type* p_link = start.etl_next; - link_type* p_previous = &start; + link_type* p_previous = const_cast(&start); while (p_link != ETL_NULLPTR) { diff --git a/include/etl/intrusive_list.h b/include/etl/intrusive_list.h index 673852c1..563fadfa 100644 --- a/include/etl/intrusive_list.h +++ b/include/etl/intrusive_list.h @@ -259,21 +259,18 @@ namespace etl /// Detects existence of specified node in list. ///\param search_link The node to find in list //************************************************************************* - bool contains_node(link_type& search_link) const + bool contains_node(const link_type& search_link) const { - link_type* p_link = terminal_link.link_type::etl_next; + return is_link_in_list(&search_link);; + } - while (p_link != &terminal_link) - { - if (&search_link == p_link) - { - return true; - } - - p_link = p_link->link_type::etl_next; - } - - return false; + //************************************************************************* + /// Detects existence of specified node in list. + ///\param search_link The node to find in list + //************************************************************************* + bool contains_node(const link_type* search_link) const + { + return is_link_in_list(search_link);; } protected: @@ -425,7 +422,7 @@ namespace etl { link_type* result = ETL_NULLPTR; - if (contains_node(link)) + if (is_link_in_list(link)) { link_type* p_next = link->etl_next;