Embedded Template Library 1.0
Loading...
Searching...
No Matches
intrusive_list.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2016 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_INTRUSIVE_LIST_INCLUDED
32#define ETL_INTRUSIVE_LIST_INCLUDED
33
34#include "platform.h"
35#include "nullptr.h"
36#include "type_traits.h"
37#include "exception.h"
38#include "error_handler.h"
39#include "intrusive_links.h"
40#include "static_assert.h"
41#include "algorithm.h"
42#include "iterator.h"
43#include "functional.h"
44
45#include <stddef.h>
46
47#include "private/minmax_push.h"
48
49namespace etl
50{
51 //***************************************************************************
54 //***************************************************************************
56 {
57 public:
58
59 intrusive_list_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
61 {
62 }
63 };
64
65 //***************************************************************************
68 //***************************************************************************
70 {
71 public:
72
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_)
75 {
76 }
77 };
78
79 //***************************************************************************
82 //***************************************************************************
84 {
85 public:
86
88 : intrusive_list_exception(ETL_ERROR_TEXT("intrusive_list:iterator", ETL_INTRUSIVE_LIST_FILE_ID"B"), file_name_, line_number_)
89 {
90 }
91 };
92
93 //***************************************************************************
96 //***************************************************************************
98 {
99 public:
100
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_)
103 {
104 }
105 };
106
107 //***************************************************************************
110 //***************************************************************************
112 {
113 public:
114
116 : intrusive_list_exception(ETL_ERROR_TEXT("intrusive_list:value is already linked", ETL_INTRUSIVE_LIST_FILE_ID"D"), file_name_, line_number_)
117 {
118 }
119 };
120
121 //***************************************************************************
124 //***************************************************************************
125 template <typename TLink>
127 {
128 public:
129
130 // Node typedef.
131 typedef TLink link_type;
132
133 //*************************************************************************
137 //*************************************************************************
138 template <typename TIterator>
139 void assign(TIterator first, TIterator last)
140 {
141#if ETL_IS_DEBUG_BUILD
142 intmax_t d = etl::distance(first, last);
144#endif
145
146 initialise();
147
148 link_type* p_last_link = &terminal_link;
149
150 // Add all of the elements.
151 while (first != last)
152 {
153 link_type& link = *first++;
155 p_last_link = &link;
156 ++current_size;
157 }
158 }
159
160 //*************************************************************************
162 //*************************************************************************
163 void push_front(link_type& value)
164 {
165 ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_list_value_is_already_linked));
166
168 }
169
170 //*************************************************************************
172 //*************************************************************************
174 {
175#if defined(ETL_CHECK_PUSH_POP)
176 ETL_ASSERT(!empty(), ETL_ERROR(intrusive_list_empty));
177#endif
179 }
180
181 //*************************************************************************
183 //*************************************************************************
184 void push_back(link_type& value)
185 {
186 ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_list_value_is_already_linked));
187
188 insert_link(terminal_link.link_type::etl_previous, value);
189 }
190
191 //*************************************************************************
193 //*************************************************************************
194 void pop_back()
195 {
196#if defined(ETL_CHECK_PUSH_POP)
197 ETL_ASSERT(!empty(), ETL_ERROR(intrusive_list_empty));
198#endif
200 }
201
202 //*************************************************************************
204 //*************************************************************************
205 void clear()
206 {
207 // Unlink all of the items.
208 link_type* p_unlink = terminal_link.etl_next;
209
210 while (p_unlink != &terminal_link)
211 {
212 link_type* p_next = p_unlink->etl_next;
213 p_unlink->clear();
214 p_unlink = p_next;
215 }
216
217 initialise();
218 }
219
220 //*************************************************************************
222 //*************************************************************************
223 void reverse()
224 {
225 if (is_trivial_list())
226 {
227 return;
228 }
229
230 link_type* pnode = terminal_link.etl_next;
231
232 while (pnode != &terminal_link)
233 {
234 pnode->reverse();
235 pnode = pnode->etl_previous; // Now we've reversed it, we must go to the previous node.
236 }
237
238 // Terminal node.
239 pnode->reverse();
240 }
241
242 //*************************************************************************
244 //*************************************************************************
245 bool empty() const
246 {
247 return (terminal_link.link_type::etl_next == &terminal_link);
248 }
249
250 //*************************************************************************
252 //*************************************************************************
253 size_t size() const
254 {
255 return current_size;
256 }
257
258 //*************************************************************************
261 //*************************************************************************
262 bool contains_node(const link_type& search_link) const
263 {
265 }
266
267 //*************************************************************************
270 //*************************************************************************
271 bool contains_node(const link_type* search_link) const
272 {
274 }
275
276 protected:
277
279 link_type terminal_link;
280
282
283 //*************************************************************************
285 //*************************************************************************
287 {
288 }
289
290 //*************************************************************************
292 //*************************************************************************
293 bool is_trivial_list() const
294 {
295 return (terminal_link.link_type::etl_next == &terminal_link) || (terminal_link.link_type::etl_next->etl_next == &terminal_link);
296 }
297
298 //*************************************************************************
300 //*************************************************************************
301 void insert_link(link_type& previous, link_type& new_link)
302 {
303 // Connect to the intrusive_list.
305 ++current_size;
306 }
307
308 //*************************************************************************
310 //*************************************************************************
311 void insert_link(link_type* previous, link_type& new_link)
312 {
313 // Connect to the intrusive_list.
315 ++current_size;
316 }
317
318 //*************************************************************************
320 //*************************************************************************
321 void insert_link(link_type& previous, link_type* new_link)
322 {
323 // Connect to the intrusive_list.
325 ++current_size;
326 }
327
328 //*************************************************************************
330 //*************************************************************************
331 void insert_link(link_type* previous, link_type* new_link)
332 {
333 // Connect to the intrusive_list.
335 ++current_size;
336 }
337
338 //*************************************************************************
340 //*************************************************************************
341 void disconnect_link(link_type& link)
342 {
344 --current_size;
345 }
346
347 //*************************************************************************
349 //*************************************************************************
350 void disconnect_link(link_type* link)
351 {
353 --current_size;
354 }
355
356 //*************************************************************************
358 //*************************************************************************
359 link_type* get_head()
360 {
361 return terminal_link.etl_next;
362 }
363
364 //*************************************************************************
366 //*************************************************************************
367 const link_type* get_head() const
368 {
369 return terminal_link.etl_next;
370 }
371
372 //*************************************************************************
374 //*************************************************************************
375 link_type* get_tail()
376 {
377 return terminal_link.etl_previous;
378 }
379
380 //*************************************************************************
382 //*************************************************************************
383 const link_type* get_tail() const
384 {
385 return terminal_link.etl_previous;
386 }
387
388 //*************************************************************************
390 //*************************************************************************
392 {
393 etl::link(terminal_link, terminal_link);
394 current_size = 0;
395 }
396
397 //*************************************************************************
399 //*************************************************************************
400 bool is_link_in_list(const link_type* search_link) const
401 {
402 link_type* p_link = terminal_link.link_type::etl_next;
403
404 while (p_link != &terminal_link)
405 {
406 if (search_link == p_link)
407 {
408 return true;
409 }
410
411 p_link = p_link->link_type::etl_next;
412 }
413
414 return false;
415 }
416
417 //*************************************************************************
420 //*************************************************************************
421 link_type* remove_link(link_type* link)
422 {
423 link_type* result = ETL_NULLPTR;
424
425 if (is_link_in_list(link))
426 {
427 link_type* p_next = link->etl_next;
428
429 disconnect_link(link);
430
431 if (p_next != &terminal_link)
432 {
433 result = p_next;
434 }
435 }
436
437 return result;
438 }
439
440 //*************************************************************************
442 //*************************************************************************
443 link_type* remove_link_range(link_type* p_first, link_type* p_last)
444 {
445 // Join the ends.
446 etl::link<link_type>(p_first->etl_previous, p_last);
447
448 while (p_first != p_last)
449 {
450 link_type* p_next = p_first->etl_next;
451 p_first->clear();
452 p_first = p_next;
453 }
454
455 if (p_last == &terminal_link)
456 {
457 return ETL_NULLPTR;
458 }
459 else
460 {
461 return p_last;
462 }
463 }
464 };
465
466 //***************************************************************************
470 //***************************************************************************
471 template <typename TValue, typename TLink>
473 {
474 public:
475
476 // Node typedef.
477 typedef typename etl::intrusive_list_base<TLink>::link_type link_type;
478
480
481 typedef TValue node_type;
482
483 // STL style typedefs.
484 typedef TValue value_type;
485 typedef value_type* pointer;
486 typedef const value_type* const_pointer;
487 typedef value_type& reference;
488 typedef const value_type& const_reference;
489 typedef size_t size_type;
490
491 //*************************************************************************
493 //*************************************************************************
494 class iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, value_type>
495 {
496 public:
497
498 friend class intrusive_list;
499 friend class const_iterator;
500
501 iterator()
502 : p_value(ETL_NULLPTR)
503 {
504 }
505
506 iterator(const iterator& other)
507 : p_value(other.p_value)
508 {
509 }
510
511 iterator& operator ++()
512 {
513 // Read the appropriate 'etl_next'.
514 p_value = p_value->etl_next;
515 return *this;
516 }
517
518 iterator operator ++(int)
519 {
520 iterator temp(*this);
521 // Read the appropriate 'etl_next'.
522 p_value = p_value->etl_next;
523 return temp;
524 }
525
526 iterator& operator --()
527 {
528 // Read the appropriate 'etl_previous'.
529 p_value = p_value->etl_previous;
530 return *this;
531 }
532
533 iterator operator --(int)
534 {
535 iterator temp(*this);
536 // Read the appropriate 'etl_previous'.
537 p_value = p_value->etl_previous;
538 return temp;
539 }
540
541 iterator& operator =(const iterator& other)
542 {
543 p_value = other.p_value;
544 return *this;
545 }
546
547 reference operator *() const
548 {
550 return *static_cast<pointer>(p_value);
552 }
553
554 pointer operator &() const
555 {
556 return static_cast<pointer>(p_value);
557 }
558
559 pointer operator ->() const
560 {
561 return static_cast<pointer>(p_value);
562 }
563
564 friend bool operator == (const iterator& lhs, const iterator& rhs)
565 {
566 return lhs.p_value == rhs.p_value;
567 }
568
569 friend bool operator != (const iterator& lhs, const iterator& rhs)
570 {
571 return !(lhs == rhs);
572 }
573
574 private:
575
576 iterator(link_type* value)
577 : p_value(value)
578 {
579 }
580
581 link_type* p_value;
582 };
583
584 //*************************************************************************
586 //*************************************************************************
587 class const_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const value_type>
588 {
589 public:
590
591 friend class intrusive_list;
592
594 : p_value(ETL_NULLPTR)
595 {
596 }
597
599 : p_value(other.p_value)
600 {
601 }
602
604 : p_value(other.p_value)
605 {
606 }
607
608 const_iterator& operator ++()
609 {
610 // Read the appropriate 'etl_next'.
611 p_value = p_value->etl_next;
612 return *this;
613 }
614
615 const_iterator operator ++(int)
616 {
617 const_iterator temp(*this);
618 // Read the appropriate 'etl_next'.
619 p_value = p_value->etl_next;
620 return temp;
621 }
622
623 const_iterator& operator --()
624 {
625 // Read the appropriate 'etl_previous'.
626 p_value = p_value->etl_previous;
627 return *this;
628 }
629
630 const_iterator operator --(int)
631 {
632 const_iterator temp(*this);
633 // Read the appropriate 'etl_previous'.
634 p_value = p_value->etl_previous;
635 return temp;
636 }
637
638 const_iterator& operator =(const const_iterator& other)
639 {
640 p_value = other.p_value;
641 return *this;
642 }
643
644 const_reference operator *() const
645 {
646 return *static_cast<const_pointer>(p_value);
647 }
648
649 const_pointer operator &() const
650 {
651 return static_cast<const_pointer>(p_value);
652 }
653
654 const_pointer operator ->() const
655 {
656 return static_cast<const_pointer>(p_value);
657 }
658
659 friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
660 {
661 return lhs.p_value == rhs.p_value;
662 }
663
664 friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
665 {
666 return !(lhs == rhs);
667 }
668
669 private:
670
671 const_iterator(const link_type* value)
672 : p_value(value)
673 {
674 }
675
676 const link_type* p_value;
677 };
678
679 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
680
681 //*************************************************************************
683 //*************************************************************************
685 {
686 this->initialise();
687 }
688
689 //*************************************************************************
691 //*************************************************************************
693 {
694 this->clear();
695 }
696
697 //*************************************************************************
699 //*************************************************************************
700 template <typename TIterator>
702 {
703 this->assign(first, last);
704 }
705
706#if ETL_USING_CPP11
707 //*************************************************************************
709 //*************************************************************************
710 template <typename... TLinks>
711 intrusive_list(link_type& first, TLinks&... links)
712 {
713 ETL_STATIC_ASSERT((etl::is_base_of_all<link_type, TLinks...>::value), "Mixed link types");
714
715 this->current_size = 0;
716 this->terminal_link.etl_next = &first;
717 link_type* last = make_linked_list(this->current_size, first, static_cast<link_type&>(links)...);
718 first.etl_previous = &this->terminal_link;
719 last->etl_next = &this->terminal_link;
720 this->terminal_link.etl_previous = last;
721 }
722#endif
723
724 //*************************************************************************
726 //*************************************************************************
728 {
729 return iterator(this->get_head());
730 }
731
732 //*************************************************************************
734 //*************************************************************************
736 {
737 return const_iterator(this->get_head());
738 }
739
740 //*************************************************************************
742 //*************************************************************************
744 {
745 return const_iterator(this->get_head());
746 }
747
748 //*************************************************************************
750 //*************************************************************************
752 {
753 return iterator(&this->terminal_link);
754 }
755
756 //*************************************************************************
758 //*************************************************************************
760 {
761 return const_iterator(&this->terminal_link);
762 }
763
764 //*************************************************************************
766 //*************************************************************************
768 {
769 return const_iterator(&this->terminal_link);
770 }
771
772 //*************************************************************************
774 //*************************************************************************
775 reference front()
776 {
777 return *static_cast<pointer>(this->get_head());
778 }
779
780 //*************************************************************************
782 //*************************************************************************
783 const_reference front() const
784 {
785 return *static_cast<const_pointer>(this->get_head());
786 }
787
788 //*************************************************************************
790 //*************************************************************************
791 reference back()
792 {
793 return *static_cast<pointer>(this->get_tail());
794 }
795
796 //*************************************************************************
798 //*************************************************************************
799 const_reference back() const
800 {
801 return *static_cast<const_pointer>(this->get_tail());
802 }
803
804 //*************************************************************************
806 //*************************************************************************
807 iterator insert(const_iterator position, value_type& value)
808 {
809 this->insert_link(position.p_value->link_type::etl_previous, value);
810 return iterator(&value);
811 }
812
813 //*************************************************************************
815 //*************************************************************************
816 template <typename TIterator>
817 void insert(const_iterator position, TIterator first, TIterator last)
818 {
819 while (first != last)
820 {
821 // Set up the next free link.
822 this->insert_link(*position.p_value->link_type::etl_previous, *first);
823 ++first;
824 }
825 }
826
827 //*************************************************************************
829 //*************************************************************************
831 {
832 iterator next(position);
833 ++next;
834
835 this->disconnect_link(*position.p_value);
836
837 return next;
838 }
839
840 //*************************************************************************
842 //*************************************************************************
844 {
845 iterator next(position);
846 ++next;
847
848 this->disconnect_link(*position.p_value);
849
850 return next;
851 }
852
853 //*************************************************************************
856 //*************************************************************************
858 {
859 const link_type* cp_first = first.p_value;
860 const link_type* cp_last = last.p_value;
861
862 link_type* p_first = const_cast<link_type*>(cp_first);
863 link_type* p_last = const_cast<link_type*>(cp_last);
864
865 this->current_size -= etl::distance(first, last);
866
867 p_last = this->remove_link_range(p_first, p_last);
868
869 if (p_last == ETL_NULLPTR)
870 {
871 return end();
872 }
873 else
874 {
875 return iterator(static_cast<pointer>(p_last));
876 }
877 }
878
879 //*************************************************************************
881 //*************************************************************************
882 node_type* erase(const node_type& node)
883 {
884 return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(&node)));
885 }
886
887 //*************************************************************************
889 //*************************************************************************
890 node_type* erase(const node_type* p_node)
891 {
892 return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(p_node)));
893 }
894
895 //*************************************************************************
898 //*************************************************************************
899 template <typename TIsEqual>
901 {
902 if (this->empty())
903 {
904 return;
905 }
906
908 ++i_item;
910
911 while (i_item != end())
912 {
913 if (isEqual(*i_previous, *i_item))
914 {
916 }
917 else
918 {
920 ++i_item;
921 }
922 }
923 }
924
925 //*************************************************************************
927 //*************************************************************************
928 void sort()
929 {
931 }
932
933 //*************************************************************************
957 //*************************************************************************
958 template <typename TCompare>
960 {
966 int list_size = 1;
968 int left_size;
969 int right_size;
970
971 if (this->is_trivial_list())
972 {
973 return;
974 }
975
976 while (true)
977 {
978 i_left = begin();
979 i_head = end();
980 i_tail = end();
981
982 number_of_merges = 0; // Count the number of merges we do in this pass.
983
984 while (i_left != end())
985 {
986 ++number_of_merges; // There exists a merge to be done.
987 i_right = i_left;
988 left_size = 0;
989
990 // Step 'list_size' places along from left
991 for (int i = 0; i < list_size; ++i)
992 {
993 ++left_size;
994 ++i_right;
995
996 if (i_right == end())
997 {
998 break;
999 }
1000 }
1001
1002 // If right hasn't fallen off end, we have two lists to merge.
1004
1005 // Now we have two lists. Merge them.
1006 while (left_size > 0 || (right_size > 0 && i_right != end()))
1007 {
1008 // Decide whether the next node of merge comes from left or right.
1009 if (left_size == 0)
1010 {
1011 // Left is empty. The node must come from right.
1012 i_node = i_right++;
1013 --right_size;
1014 }
1015 else if (right_size == 0 || i_right == end())
1016 {
1017 // Right is empty. The node must come from left.
1018 i_node = i_left++;
1019 --left_size;
1020 }
1021 else if (!compare(*i_right, *i_left))
1022 {
1023 // First node of left is lower or same. The node must come from left.
1024 i_node = i_left++;
1025 --left_size;
1026 }
1027 else
1028 {
1029 // First node of right is lower. The node must come from right.
1030 i_node = i_right;
1031 ++i_right;
1032 --right_size;
1033 }
1034
1035 // Add the next node to the merged head.
1036 if (i_head == end())
1037 {
1038 etl::link<link_type>(i_head.p_value, i_node.p_value);
1039 i_head = i_node;
1040 i_tail = i_node;
1041 }
1042 else
1043 {
1044 etl::link<link_type>(i_tail.p_value, i_node.p_value);
1045 i_tail = i_node;
1046 }
1047
1048 etl::link<link_type>(i_tail.p_value, this->terminal_link);
1049 }
1050
1051 // Now left has stepped `list_size' places along, and right has too.
1052 i_left = i_right;
1053 }
1054
1055 // If we have done only one merge, we're finished.
1056 if (number_of_merges <= 1) // Allow for number_of_merges == 0, the empty head case
1057 {
1058 return;
1059 }
1060
1061 // Otherwise repeat, merging lists twice the size
1062 list_size *= 2;
1063 }
1064 }
1065
1066 //*************************************************************************
1067 // Removes the values specified.
1068 //*************************************************************************
1069 void remove(const_reference value)
1070 {
1071 iterator i_item = begin();
1072
1073 while (i_item != end())
1074 {
1075 if (*i_item == value)
1076 {
1077 i_item = erase(i_item);
1078 }
1079 else
1080 {
1081 ++i_item;
1082 }
1083 }
1084 }
1085
1086 //*************************************************************************
1088 //*************************************************************************
1089 template <typename TPredicate>
1091 {
1092 iterator i_item = begin();
1093
1094 while (i_item != end())
1095 {
1096 if (predicate(*i_item))
1097 {
1098 i_item = erase(i_item);
1099 }
1100 else
1101 {
1102 ++i_item;
1103 }
1104 }
1105 }
1106
1107 //*************************************************************************
1109 //*************************************************************************
1111 {
1112 // No point splicing to ourself!
1113 if (&other != this)
1114 {
1115 if (!other.empty())
1116 {
1117 link_type& first = *other.get_head();
1118 link_type& last = *other.get_tail();
1119
1120 if (&other != this)
1121 {
1122 this->current_size += other.size();
1123 }
1124
1125 link_type& after = *position.p_value;
1126 link_type& before = *after.etl_previous;
1127
1130
1131 other.initialise();
1132 }
1133 }
1134 }
1135
1136 //*************************************************************************
1138 //*************************************************************************
1140 {
1141 link_type& before = *position.p_value->link_type::etl_previous;
1142
1145
1146 if (&other != this)
1147 {
1148 ++this->current_size;
1149 --other.current_size;
1150 }
1151 }
1152
1153 //*************************************************************************
1155 //*************************************************************************
1157 {
1158 if (!other.empty())
1159 {
1160 if (&other != this)
1161 {
1162 size_t n = etl::distance(begin_, end_);
1163 this->current_size += n;
1164 other.current_size -= n;
1165 }
1166
1167 link_type& first = *begin_.p_value;
1168 link_type& last = *end_.p_value->link_type::etl_previous;
1169
1170 // Unlink from the source list.
1171 etl::unlink(first, last);
1172
1173 // Fix our links.
1174 link_type& before = *position.p_value->link_type::etl_previous;
1175
1176 etl::link_splice<link_type>(before, first, last);
1177 }
1178 }
1179
1180 //*************************************************************************
1182 //*************************************************************************
1184 {
1186 }
1187
1188 //*************************************************************************
1190 //*************************************************************************
1191 template <typename TCompare>
1193 {
1194 if ((this != &other) && !other.empty())
1195 {
1196#if ETL_IS_DEBUG_BUILD
1199#endif
1200
1201 link_type* other_begin = other.get_head();
1202 link_type* other_end = &other.terminal_link;
1203
1204 link_type* this_begin = this->get_head();
1205 link_type* this_end = &this->terminal_link;
1206
1207 while ((this_begin != this_end) && (other_begin != other_end))
1208 {
1209 // Find the place to insert.
1210 while ((this_begin != this_end) && !(compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(this_begin))))
1211 {
1212 this_begin = this_begin->etl_next;
1213 }
1214
1215 // Insert.
1216 if (this_begin != this_end)
1217 {
1218 while ((other_begin != other_end) && (compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(this_begin))))
1219 {
1220 link_type* value = other_begin;
1221 other_begin = other_begin->etl_next;
1222 etl::link_splice<link_type>(*this_begin->etl_previous, *value);
1223 }
1224 }
1225 }
1226
1227 // Any left over?
1228 if ((this_begin == this_end) && (other_begin != other_end))
1229 {
1230 etl::link_splice<link_type>(*this->get_tail(), *other_begin, *other_end->etl_previous);
1231 }
1232
1233 this->current_size += other.size();
1234
1235 other.initialise();
1236 }
1237 }
1238
1239 //*************************************************************************
1242 //*************************************************************************
1243 bool contains(const_reference value) const
1244 {
1246
1247 while (i_item != end())
1248 {
1249 if (*i_item == value)
1250 {
1251 return true;
1252 }
1253
1254 ++i_item;
1255 }
1256
1257 return false;
1258 }
1259
1260 private:
1261
1262#if ETL_USING_CPP17
1263 //***************************************************************************
1265 //***************************************************************************
1266 template <typename... TLinks>
1267 link_type* make_linked_list(size_t& count, link_type& first, TLinks&... links)
1268 {
1269 TLink* current = &first;
1270 ++count;
1271 ((current->etl_next = &links, static_cast<TLink&>(links).etl_previous = current, current = &links, ++count), ...);
1272
1273 return current;
1274 }
1275#elif ETL_USING_CPP11
1276 //***************************************************************************
1278 //***************************************************************************
1279 link_type* make_linked_list(size_t& count, link_type& first)
1280 {
1281 ++count;
1282
1283 return &first;
1284 }
1285
1286 //***************************************************************************
1288 //***************************************************************************
1289 template <typename... TLinks>
1290 link_type* make_linked_list(size_t& count, link_type& first, link_type& next, TLinks&... links)
1291 {
1292 ++count;
1293 first.etl_next = &next;
1294 next.etl_previous = &first;
1295
1296 return make_linked_list(count, next, static_cast<link_type&>(links)...);
1297 }
1298#endif
1299
1300 // Disabled.
1302 intrusive_list& operator = (const intrusive_list& rhs);
1303 };
1304}
1305
1306#include "private/minmax_pop.h"
1307
1308#endif
const_iterator
Definition intrusive_list.h:588
iterator.
Definition intrusive_list.h:495
Definition intrusive_list.h:127
void disconnect_link(link_type *link)
Remove a link.
Definition intrusive_list.h:350
size_t size() const
Returns the number of elements.
Definition intrusive_list.h:253
link_type * get_tail()
Get the tail link.
Definition intrusive_list.h:375
void insert_link(link_type &previous, link_type &new_link)
Insert a link.
Definition intrusive_list.h:301
~intrusive_list_base()
Destructor.
Definition intrusive_list.h:286
void assign(TIterator first, TIterator last)
Definition intrusive_list.h:139
bool contains_node(const link_type *search_link) const
Definition intrusive_list.h:271
size_t current_size
Counts the number of elements in the list.
Definition intrusive_list.h:281
bool is_link_in_list(const link_type *search_link) const
Tests if the link is in this list.
Definition intrusive_list.h:400
void disconnect_link(link_type &link)
Remove a link.
Definition intrusive_list.h:341
void insert_link(link_type &previous, link_type *new_link)
Insert a link.
Definition intrusive_list.h:321
void pop_back()
Removes a value from the back of the intrusive_list.
Definition intrusive_list.h:194
link_type * get_head()
Get the head link.
Definition intrusive_list.h:359
bool empty() const
Returns true if the list has no elements.
Definition intrusive_list.h:245
link_type * remove_link_range(link_type *p_first, link_type *p_last)
Removes a range of links.
Definition intrusive_list.h:443
void initialise()
Initialise the intrusive_list.
Definition intrusive_list.h:391
void reverse()
Reverses the list.
Definition intrusive_list.h:223
void insert_link(link_type *previous, link_type *new_link)
Insert a link.
Definition intrusive_list.h:331
const link_type * get_head() const
Get the head link.
Definition intrusive_list.h:367
link_type terminal_link
The link that acts as the intrusive_list start & end.
Definition intrusive_list.h:279
void insert_link(link_type *previous, link_type &new_link)
Insert a link.
Definition intrusive_list.h:311
void clear()
Clears the intrusive_list.
Definition intrusive_list.h:205
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:184
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:262
const link_type * get_tail() const
Get the tail link.
Definition intrusive_list.h:383
bool is_trivial_list() const
Is the intrusive_list a trivial length?
Definition intrusive_list.h:293
link_type * remove_link(link_type *link)
Definition intrusive_list.h:421
Definition intrusive_list.h:70
Definition intrusive_list.h:56
Definition intrusive_list.h:84
Definition intrusive_list.h:98
Definition intrusive_list.h:112
Definition intrusive_list.h:473
~intrusive_list()
Destructor.
Definition intrusive_list.h:692
const_iterator end() const
Gets the end of the intrusive_list.
Definition intrusive_list.h:759
reference back()
Gets a reference to the last element.
Definition intrusive_list.h:791
iterator begin()
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:727
node_type * erase(const node_type &node)
Erases the specified node.
Definition intrusive_list.h:882
void unique(TIsEqual isEqual)
Definition intrusive_list.h:900
const_iterator begin() const
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:735
void splice(iterator position, list_type &other)
Splice another list into this one.
Definition intrusive_list.h:1110
iterator erase(const_iterator position)
Erases the value at the specified position.
Definition intrusive_list.h:843
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:1156
reference front()
Gets a reference to the first element.
Definition intrusive_list.h:775
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:817
void merge(list_type &other, TCompare compare)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_list.h:1192
bool contains(const_reference value) const
Definition intrusive_list.h:1243
void sort(TCompare compare)
Definition intrusive_list.h:959
void splice(iterator position, list_type &other, iterator isource)
Splice an element from another list into this one.
Definition intrusive_list.h:1139
intrusive_list()
Constructor.
Definition intrusive_list.h:684
iterator erase(const_iterator first, const_iterator last)
Definition intrusive_list.h:857
const_iterator cend() const
Gets the end of the intrusive_list.
Definition intrusive_list.h:767
iterator erase(iterator position)
Erases the value at the specified position.
Definition intrusive_list.h:830
const_iterator cbegin() const
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:743
void remove_if(TPredicate predicate)
Removes according to a predicate.
Definition intrusive_list.h:1090
void sort()
Sort using in-place merge sort algorithm.
Definition intrusive_list.h:928
iterator insert(const_iterator position, value_type &value)
Inserts a value to the intrusive_list before the specified position.
Definition intrusive_list.h:807
const_reference front() const
Gets a const reference to the first element.
Definition intrusive_list.h:783
iterator end()
Gets the end of the intrusive_list.
Definition intrusive_list.h:751
node_type * erase(const node_type *p_node)
Erases the specified node.
Definition intrusive_list.h:890
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:701
const_reference back() const
Gets a const reference to the last element.
Definition intrusive_list.h:799
void merge(list_type &other)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_list.h:1183
ETL_CONSTEXPR14 bool operator==(const etl::expected< TValue, TError > &lhs, const etl::expected< TValue2, TError2 > &rhs)
Equivalence operators.
Definition expected.h:974
ETL_NODISCARD ETL_CONSTEXPR14 bool is_sorted(TIterator begin, TIterator end)
Definition algorithm.h:1709
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
Definition exception.h:47
enable_if
Definition type_traits_generator.h:1230
is_integral
Definition type_traits_generator.h:1040
bitset_ext
Definition absolute.h:38
ETL_NODISCARD ETL_CONSTEXPR14 T round_half_even_unscaled(T value) ETL_NOEXCEPT
Definition scaled_rounding.h:314
Definition compare.h:51
iterator
Definition iterator.h:399
Definition functional.h:170