diff --git a/include/etl/intrusive_forward_list.h b/include/etl/intrusive_forward_list.h index 1e530d87..45bdd7bf 100644 --- a/include/etl/intrusive_forward_list.h +++ b/include/etl/intrusive_forward_list.h @@ -338,14 +338,14 @@ 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(link_type& search_link) + link_type* is_link_in_list(const link_type* search_link) { link_type* p_link = start.etl_next; link_type* p_previous = &start; while (p_link != ETL_NULLPTR) { - if (&search_link == p_link) + if (search_link == p_link) { return p_previous; } @@ -362,7 +362,7 @@ namespace etl /// Returns ETL_NULLPTR if the link was not in this list. /// Returns the next //************************************************************************* - link_type* remove_link(link_type& link) + link_type* remove_link(link_type* link) { link_type* result = ETL_NULLPTR; @@ -370,7 +370,7 @@ namespace etl if (p_previous != ETL_NULLPTR) { - link_type* p_next = link.etl_next; + link_type* p_next = link->etl_next; disconnect_link_after(*p_previous); @@ -632,9 +632,9 @@ namespace etl template intrusive_forward_list(link_type& first, TLinks&... links) { - current_size = 0; + this->current_size = 0; this->start.etl_next = &first; - link_type* last = make_linked_list(current_size, first, static_cast(links)...); + link_type* last = make_linked_list(this->current_size, first, static_cast(links)...); last->etl_next = &this->terminator; } #endif @@ -797,9 +797,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))); } //************************************************************************* @@ -1206,10 +1214,10 @@ namespace etl //*************************************************************************** /// Create a linked list from a number of forward_link nodes. //*************************************************************************** - template - TLink* make_linked_list(size_t& count, TLink& first, TLinks&... links) + template + link_type* make_linked_list(size_t& count, link_type& first, TLinks&... links) { - TLink* current = &first; + link_type* current = &first; ++count; ((current->etl_next = &links, current = &links, ++count), ...); diff --git a/test/test_intrusive_forward_list.cpp b/test/test_intrusive_forward_list.cpp index b9e22367..a7d21da8 100644 --- a/test/test_intrusive_forward_list.cpp +++ b/test/test_intrusive_forward_list.cpp @@ -722,6 +722,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_front(); + } + + 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_after_range) {