From fc4c74721c1ca49a90d85ed205512bf6a6bf564a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 2 Mar 2025 08:31:14 +0000 Subject: [PATCH] Added erase from pointer to node --- include/etl/intrusive_list.h | 20 ++++++--- test/test_intrusive_list.cpp | 84 ++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/include/etl/intrusive_list.h b/include/etl/intrusive_list.h index a8da751e..30cf7d50 100644 --- a/include/etl/intrusive_list.h +++ b/include/etl/intrusive_list.h @@ -379,13 +379,13 @@ namespace etl //************************************************************************* /// Tests if the link is in this list. //************************************************************************* - bool is_link_in_list(link_type& search_link) const + bool is_link_in_list(const 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) + if (search_link == p_link) { return true; } @@ -400,13 +400,13 @@ namespace etl /// Remove the specified node from the list. /// Returns ETL_NULLPTR if the link was not in this list or was the last in the list. //************************************************************************* - link_type* remove_link(link_type& link) + link_type* remove_link(link_type* link) { link_type* result = ETL_NULLPTR; if (is_link_in_list(link)) { - link_type* p_next = link.etl_next; + link_type* p_next = link->etl_next; disconnect_link(link); @@ -859,9 +859,17 @@ namespace etl //************************************************************************* /// Erases the specified node. //************************************************************************* - node_type* erase(node_type& node) + node_type* erase(const node_type& node) { - return static_cast(this->remove_link(node)); + return static_cast(this->remove_link(const_cast(&node))); + } + + //************************************************************************* + /// Erases the specified node. + //************************************************************************* + node_type* erase(const node_type* p_node) + { + return static_cast(this->remove_link(const_cast(p_node))); } //************************************************************************* diff --git a/test/test_intrusive_list.cpp b/test/test_intrusive_list.cpp index 48081e35..8006af29 100644 --- a/test/test_intrusive_list.cpp +++ b/test/test_intrusive_list.cpp @@ -863,6 +863,90 @@ namespace CHECK(ETL_NULLPTR == p_next5); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_by_node_pointer) + { + bool are_equal; + + std::vector compare_data(sorted_data.begin(), sorted_data.end()); + DataNDC0 data0(sorted_data.begin(), sorted_data.end()); + DataNDC1 data1(sorted_data.begin(), sorted_data.end()); + + // Move to the third value and erase. + std::vector::iterator i_compare_data = compare_data.begin(); + std::advance(i_compare_data, 3); + + DataNDC0::iterator i_data = data0.begin(); + std::advance(i_data, 3); + + ItemNDCNode& node1 = *i_data; + ItemNDCNode* p_next1 = static_cast(node1.FirstLink::get_next()); + ItemNDCNode* p_node1 = data0.erase(&node1); + i_compare_data = compare_data.erase(i_compare_data); + + are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin()); + + CHECK(are_equal); + CHECK_EQUAL(p_next1, p_node1); + CHECK_EQUAL(compare_data.size(), data0.size()); + CHECK_EQUAL(compare_data.size(), size_t(std::distance(data0.begin(), data0.end()))); + + // Move to the first value and erase. + i_compare_data = compare_data.begin(); + i_compare_data = compare_data.erase(i_compare_data); + + i_data = data0.begin(); + + ItemNDCNode& node2 = *i_data; + ItemNDCNode* p_next2 = static_cast(node2.FirstLink::get_next()); + ItemNDCNode* p_node2 = data0.erase(&node2); + + are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin()); + + CHECK(are_equal); + CHECK_EQUAL(p_next2, p_node2); + CHECK_EQUAL(compare_data.size(), data0.size()); + CHECK_EQUAL(compare_data.size(), size_t(std::distance(data0.begin(), data0.end()))); + + // Move to the last value and erase. + i_compare_data = compare_data.begin(); + std::advance(i_compare_data, compare_data.size() - 1); + + i_data = data0.begin(); + std::advance(i_data, data0.size() - 1); + + ItemNDCNode& node3 = *i_data; + ItemNDCNode* p_next3 = static_cast(node3.FirstLink::get_next()); + ItemNDCNode* p_node3 = data0.erase(&node3); + i_compare_data = compare_data.erase(i_compare_data); + + are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin()); + + CHECK(are_equal); + CHECK_NOT_EQUAL(p_next3, p_node3); + CHECK(ETL_NULLPTR == p_node3); + CHECK_EQUAL(compare_data.size(), data0.size()); + CHECK_EQUAL(compare_data.size(), size_t(std::distance(data0.begin(), data0.end()))); + + // Try removing a node that isn't in the list. + auto node_not_in_list = ItemNDCNode("9"); + + ItemNDCNode* p_node4 = data0.erase(&node_not_in_list); + CHECK(p_node4 == ETL_NULLPTR); + + // Try removing the only node in the list. + while (data0.size() > 1) + { + data0.pop_back(); + } + + ItemNDCNode* p_node5 = &data0.front(); + + ItemNDCNode* p_next5 = static_cast(p_node5->FirstLink::get_next()); + p_next5 = data0.erase(p_node5); + CHECK(ETL_NULLPTR == p_next5); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) {