31#ifndef ETL_INTRUSIVE_LIST_INCLUDED
32#define ETL_INTRUSIVE_LIST_INCLUDED
40#include "static_assert.h"
59 intrusive_list_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
60 :
exception(reason_, file_name_, line_number_)
69 class intrusive_list_empty :
public intrusive_list_exception
73 intrusive_list_empty(string_type file_name_, numeric_type line_number_)
74 : intrusive_list_exception(ETL_ERROR_TEXT(
"intrusive_list:empty", ETL_INTRUSIVE_LIST_FILE_ID
"A"), file_name_, line_number_)
83 class intrusive_list_iterator_exception :
public intrusive_list_exception
87 intrusive_list_iterator_exception(string_type file_name_, numeric_type line_number_)
88 : intrusive_list_exception(ETL_ERROR_TEXT(
"intrusive_list:iterator", ETL_INTRUSIVE_LIST_FILE_ID
"B"), file_name_, line_number_)
97 class intrusive_list_unsorted :
public intrusive_list_exception
101 intrusive_list_unsorted(string_type file_name_, numeric_type line_number_)
102 : intrusive_list_exception(ETL_ERROR_TEXT(
"intrusive_list:unsorted", ETL_INTRUSIVE_LIST_FILE_ID
"C"), file_name_, line_number_)
111 class intrusive_list_value_is_already_linked :
public intrusive_list_exception
115 intrusive_list_value_is_already_linked(string_type file_name_, numeric_type line_number_)
116 : intrusive_list_exception(ETL_ERROR_TEXT(
"intrusive_list:value is already linked", ETL_INTRUSIVE_LIST_FILE_ID
"D"), file_name_, line_number_)
125 template <
typename TLink>
131 typedef TLink link_type;
138 template <
typename TIterator>
139 void assign(TIterator first, TIterator last)
141#if ETL_IS_DEBUG_BUILD
142 intmax_t d = etl::distance(first, last);
151 while (first != last)
153 link_type& link = *first++;
154 etl::link_splice<link_type>(p_last_link, link);
210 link_type* p_next = p_unlink->etl_next;
233 pnode = pnode->etl_previous;
302 etl::link_splice<link_type>(previous, new_link);
312 etl::link_splice<link_type>(previous, new_link);
322 etl::link_splice<link_type>(previous, new_link);
332 etl::link_splice<link_type>(previous, new_link);
341 etl::unlink<link_type>(link);
350 etl::unlink<link_type>(*link);
404 if (search_link == p_link)
409 p_link = p_link->link_type::etl_next;
421 link_type* result = ETL_NULLPTR;
425 link_type* p_next = link->etl_next;
444 etl::link<link_type>(p_first->etl_previous, p_last);
446 while (p_first != p_last)
448 link_type* p_next = p_first->etl_next;
469 template <
typename TValue,
typename TLink>
475 typedef typename etl::intrusive_list_base<TLink>::link_type link_type;
479 typedef TValue node_type;
482 typedef TValue value_type;
483 typedef value_type* pointer;
484 typedef const value_type* const_pointer;
485 typedef value_type& reference;
486 typedef const value_type& const_reference;
487 typedef size_t size_type;
492 class iterator :
public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, value_type>
496 friend class intrusive_list;
497 friend class const_iterator;
500 : p_value(ETL_NULLPTR)
504 iterator(
const iterator& other)
505 : p_value(other.p_value)
509 iterator& operator ++()
512 p_value = p_value->etl_next;
516 iterator operator ++(
int)
518 iterator temp(*
this);
520 p_value = p_value->etl_next;
524 iterator& operator --()
527 p_value = p_value->etl_previous;
531 iterator operator --(
int)
533 iterator temp(*
this);
535 p_value = p_value->etl_previous;
539 iterator& operator =(
const iterator& other)
541 p_value = other.p_value;
548 return *
static_cast<pointer
>(p_value);
552 pointer operator &()
const
554 return static_cast<pointer
>(p_value);
557 pointer operator ->()
const
559 return static_cast<pointer
>(p_value);
562 friend bool operator == (
const iterator& lhs,
const iterator& rhs)
564 return lhs.p_value == rhs.p_value;
567 friend bool operator != (
const iterator& lhs,
const iterator& rhs)
569 return !(lhs == rhs);
574 iterator(link_type* value)
585 class const_iterator :
public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const value_type>
589 friend class intrusive_list;
592 : p_value(ETL_NULLPTR)
597 : p_value(other.p_value)
601 const_iterator(
const const_iterator& other)
602 : p_value(other.p_value)
606 const_iterator& operator ++()
609 p_value = p_value->etl_next;
613 const_iterator operator ++(
int)
615 const_iterator temp(*
this);
617 p_value = p_value->etl_next;
621 const_iterator& operator --()
624 p_value = p_value->etl_previous;
628 const_iterator operator --(
int)
630 const_iterator temp(*
this);
632 p_value = p_value->etl_previous;
636 const_iterator& operator =(
const const_iterator& other)
638 p_value = other.p_value;
642 const_reference operator *()
const
644 return *
static_cast<const_pointer
>(p_value);
647 const_pointer operator &()
const
649 return static_cast<const_pointer
>(p_value);
652 const_pointer operator ->()
const
654 return static_cast<const_pointer
>(p_value);
657 friend bool operator == (
const const_iterator& lhs,
const const_iterator& rhs)
659 return lhs.p_value == rhs.p_value;
662 friend bool operator != (
const const_iterator& lhs,
const const_iterator& rhs)
664 return !(lhs == rhs);
669 const_iterator(
const link_type* value)
674 const link_type* p_value;
677 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
698 template <
typename TIterator>
701 this->
assign(first, last);
708 template <
typename... TLinks>
711 ETL_STATIC_ASSERT((etl::is_base_of_all<link_type, TLinks...>::value),
"Mixed link types");
775 return *
static_cast<pointer
>(this->
get_head());
783 return *
static_cast<const_pointer
>(this->
get_head());
791 return *
static_cast<pointer
>(this->
get_tail());
799 return *
static_cast<const_pointer
>(this->
get_tail());
807 this->
insert_link(position.p_value->link_type::etl_previous, value);
814 template <
typename TIterator>
817 while (first != last)
820 this->
insert_link(*position.p_value->link_type::etl_previous, *first);
857 const link_type* cp_first = first.p_value;
858 const link_type* cp_last = last.p_value;
860 link_type* p_first =
const_cast<link_type*
>(cp_first);
861 link_type* p_last =
const_cast<link_type*
>(cp_last);
867 if (p_last == ETL_NULLPTR)
873 return iterator(
static_cast<pointer
>(p_last));
880 node_type*
erase(
const node_type& node)
882 return static_cast<node_type*
>(this->
remove_link(
const_cast<node_type*
>(&node)));
888 node_type*
erase(
const node_type* p_node)
890 return static_cast<node_type*
>(this->
remove_link(
const_cast<node_type*
>(p_node)));
897 template <
typename TIsEqual>
909 while (i_item !=
end())
911 if (isEqual(*i_previous, *i_item))
913 i_item =
erase(i_item);
956 template <
typename TCompare>
965 int number_of_merges;
980 number_of_merges = 0;
982 while (i_left !=
end())
989 for (
int i = 0; i < list_size; ++i)
994 if (i_right ==
end())
1001 right_size = list_size;
1004 while (left_size > 0 || (right_size > 0 && i_right !=
end()))
1013 else if (right_size == 0 || i_right ==
end())
1019 else if (!
compare(*i_right, *i_left))
1034 if (i_head ==
end())
1036 etl::link<link_type>(i_head.p_value, i_node.p_value);
1042 etl::link<link_type>(i_tail.p_value, i_node.p_value);
1046 etl::link<link_type>(i_tail.p_value, this->terminal_link);
1054 if (number_of_merges <= 1)
1067 void remove(const_reference value)
1071 while (i_item !=
end())
1073 if (*i_item == value)
1075 i_item =
erase(i_item);
1087 template <
typename TPredicate>
1092 while (i_item !=
end())
1094 if (predicate(*i_item))
1096 i_item =
erase(i_item);
1115 link_type& first = *other.
get_head();
1116 link_type& last = *other.
get_tail();
1123 link_type& after = *position.p_value;
1124 link_type& before = *after.etl_previous;
1126 etl::link<link_type>(before, first);
1127 etl::link<link_type>(last, after);
1139 link_type& before = *position.p_value->link_type::etl_previous;
1141 etl::unlink<link_type>(*isource.p_value);
1142 etl::link_splice<link_type>(before, *isource.p_value);
1160 size_t n = etl::distance(begin_, end_);
1165 link_type& first = *begin_.p_value;
1166 link_type& last = *end_.p_value->link_type::etl_previous;
1169 etl::unlink(first, last);
1172 link_type& before = *position.p_value->link_type::etl_previous;
1174 etl::link_splice<link_type>(before, first, last);
1189 template <
typename TCompare>
1192 if ((
this != &other) && !other.
empty())
1194#if ETL_IS_DEBUG_BUILD
1199 link_type* other_begin = other.
get_head();
1202 link_type* this_begin = this->
get_head();
1205 while ((this_begin != this_end) && (other_begin != other_end))
1208 while ((this_begin != this_end) && !(
compare(*
static_cast<pointer
>(other_begin), *
static_cast<pointer
>(this_begin))))
1210 this_begin = this_begin->etl_next;
1214 if (this_begin != this_end)
1216 while ((other_begin != other_end) && (
compare(*
static_cast<pointer
>(other_begin), *
static_cast<pointer
>(this_begin))))
1218 link_type* value = other_begin;
1219 other_begin = other_begin->etl_next;
1220 etl::link_splice<link_type>(*this_begin->etl_previous, *value);
1226 if ((this_begin == this_end) && (other_begin != other_end))
1228 etl::link_splice<link_type>(*this->
get_tail(), *other_begin, *other_end->etl_previous);
1245 while (i_item !=
end())
1247 if (*i_item == value)
1264 template <
typename... TLinks>
1267 TLink* current = &first;
1269 ((current->etl_next = &links,
static_cast<TLink&
>(links).etl_previous = current, current = &links, ++count), ...);
1273#elif ETL_USING_CPP11
1277 link_type* make_linked_list(
size_t& count, link_type& first)
1287 template <
typename... TLinks>
1288 link_type* make_linked_list(
size_t& count, link_type& first, link_type& next, TLinks&... links)
1291 first.etl_next = &next;
1292 next.etl_previous = &first;
1294 return make_linked_list(count, next,
static_cast<link_type&
>(links)...);
const_iterator
Definition intrusive_list.h:586
iterator.
Definition intrusive_list.h:493
Definition intrusive_list.h:127
void disconnect_link(link_type *link)
Remove a link.
Definition intrusive_list.h:348
size_t size() const
Returns the number of elements.
Definition intrusive_list.h:251
link_type * get_tail()
Get the tail link.
Definition intrusive_list.h:373
void insert_link(link_type &previous, link_type &new_link)
Insert a link.
Definition intrusive_list.h:299
~intrusive_list_base()
Destructor.
Definition intrusive_list.h:284
void assign(TIterator first, TIterator last)
Definition intrusive_list.h:139
bool contains_node(const link_type *search_link) const
Definition intrusive_list.h:269
size_t current_size
Definition intrusive_list.h:279
bool is_link_in_list(const link_type *search_link) const
Tests if the link is in this list.
Definition intrusive_list.h:398
void disconnect_link(link_type &link)
Remove a link.
Definition intrusive_list.h:339
void insert_link(link_type &previous, link_type *new_link)
Insert a link.
Definition intrusive_list.h:319
void pop_back()
Removes a value from the back of the intrusive_list.
Definition intrusive_list.h:193
link_type * get_head()
Get the head link.
Definition intrusive_list.h:357
bool empty() const
Returns true if the list has no elements.
Definition intrusive_list.h:243
link_type * remove_link_range(link_type *p_first, link_type *p_last)
Removes a range of links.
Definition intrusive_list.h:441
void initialise()
Initialise the intrusive_list.
Definition intrusive_list.h:389
void reverse()
Reverses the list.
Definition intrusive_list.h:221
void insert_link(link_type *previous, link_type *new_link)
Insert a link.
Definition intrusive_list.h:329
const link_type * get_head() const
Get the head link.
Definition intrusive_list.h:365
link_type terminal_link
Definition intrusive_list.h:277
void insert_link(link_type *previous, link_type &new_link)
Insert a link.
Definition intrusive_list.h:309
void clear()
Clears the intrusive_list.
Definition intrusive_list.h:203
void push_front(link_type &value)
Pushes a value to the front of the intrusive_list.
Definition intrusive_list.h:163
void push_back(link_type &value)
Pushes a value to the back of the intrusive_list.
Definition intrusive_list.h:183
void pop_front()
Removes a value from the front of the intrusive_list.
Definition intrusive_list.h:173
bool contains_node(const link_type &search_link) const
Definition intrusive_list.h:260
const link_type * get_tail() const
Get the tail link.
Definition intrusive_list.h:381
bool is_trivial_list() const
Is the intrusive_list a trivial length?
Definition intrusive_list.h:291
link_type * remove_link(link_type *link)
Definition intrusive_list.h:419
Definition intrusive_list.h:70
Definition intrusive_list.h:84
Definition intrusive_list.h:98
Definition intrusive_list.h:112
~intrusive_list()
Destructor.
Definition intrusive_list.h:690
const_iterator end() const
Gets the end of the intrusive_list.
Definition intrusive_list.h:757
reference back()
Gets a reference to the last element.
Definition intrusive_list.h:789
iterator begin()
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:725
node_type * erase(const node_type &node)
Erases the specified node.
Definition intrusive_list.h:880
void unique(TIsEqual isEqual)
Definition intrusive_list.h:898
const_iterator begin() const
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:733
void splice(iterator position, list_type &other)
Splice another list into this one.
Definition intrusive_list.h:1108
iterator erase(const_iterator position)
Erases the value at the specified position.
Definition intrusive_list.h:841
void splice(iterator position, list_type &other, iterator begin_, iterator end_)
Splice a range of elements from another list into this one.
Definition intrusive_list.h:1154
reference front()
Gets a reference to the first element.
Definition intrusive_list.h:773
void insert(const_iterator position, TIterator first, TIterator last)
Inserts a range of values to the intrusive_list after the specified position.
Definition intrusive_list.h:815
void merge(list_type &other, TCompare compare)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_list.h:1190
bool contains(const_reference value) const
Definition intrusive_list.h:1241
void sort(TCompare compare)
Definition intrusive_list.h:957
void splice(iterator position, list_type &other, iterator isource)
Splice an element from another list into this one.
Definition intrusive_list.h:1137
intrusive_list()
Constructor.
Definition intrusive_list.h:682
iterator erase(const_iterator first, const_iterator last)
Definition intrusive_list.h:855
const_iterator cend() const
Gets the end of the intrusive_list.
Definition intrusive_list.h:765
iterator erase(iterator position)
Erases the value at the specified position.
Definition intrusive_list.h:828
const_iterator cbegin() const
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:741
void remove_if(TPredicate predicate)
Removes according to a predicate.
Definition intrusive_list.h:1088
void sort()
Sort using in-place merge sort algorithm.
Definition intrusive_list.h:926
iterator insert(const_iterator position, value_type &value)
Inserts a value to the intrusive_list before the specified position.
Definition intrusive_list.h:805
const_reference front() const
Gets a const reference to the first element.
Definition intrusive_list.h:781
iterator end()
Gets the end of the intrusive_list.
Definition intrusive_list.h:749
node_type * erase(const node_type *p_node)
Erases the specified node.
Definition intrusive_list.h:888
intrusive_list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Constructor from range.
Definition intrusive_list.h:699
const_reference back() const
Gets a const reference to the last element.
Definition intrusive_list.h:797
void merge(list_type &other)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_list.h:1181
ETL_CONSTEXPR14 bool operator==(const etl::expected< TValue, TError > &lhs, const etl::expected< TValue2, TError2 > &rhs)
Equivalence operators.
Definition expected.h:962
ETL_NODISCARD ETL_CONSTEXPR14 bool is_sorted(TIterator begin, TIterator end)
Definition algorithm.h:1709
ETL_CONSTEXPR14 TIterator remove(TIterator first, TIterator last, const T &value)
Definition algorithm.h:2300
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition exception.h:69
enable_if
Definition type_traits_generator.h:1254
bitset_ext
Definition absolute.h:39
ETL_CONSTEXPR14 enable_if<!etl::is_specialization< TRep2, etl::chrono::duration >::value, etl::chrono::duration< typenameetl::common_type< TRep1, TRep2 >::type, TPeriod1 > >::type operator*(const etl::chrono::duration< TRep1, TPeriod1 > &lhs, const TRep2 &rhs) ETL_NOEXCEPT
Operator *.
Definition duration.h:545
iterator
Definition iterator.h:399
Definition functional.h:170