Embedded Template Library 1.0
Loading...
Searching...
No Matches
intrusive_forward_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_FORWARD_LIST_INCLUDED
32#define ETL_INTRUSIVE_FORWARD_LIST_INCLUDED
33
34#include "platform.h"
35#include "algorithm.h"
36#include "iterator.h"
37#include "functional.h"
38#include "nullptr.h"
39#include "type_traits.h"
40#include "exception.h"
41#include "error_handler.h"
42#include "intrusive_links.h"
43
44#include <stddef.h>
45
46#include "private/minmax_push.h"
47
48namespace etl
49{
50 //***************************************************************************
53 //***************************************************************************
55 {
56 public:
57
58 intrusive_forward_list_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
60 {
61 }
62 };
63
64 //***************************************************************************
67 //***************************************************************************
69 {
70 public:
71
73 : intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:empty", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"A"), file_name_, line_number_)
74 {
75 }
76 };
77
78 //***************************************************************************
81 //***************************************************************************
83 {
84 public:
85
87 : intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:iterator", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"B"), file_name_, line_number_)
88 {
89 }
90 };
91
92 //***************************************************************************
95 //***************************************************************************
97 {
98 public:
99
101 : intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:bounds", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"C"), file_name_, line_number_)
102 {
103 }
104 };
105
106 //***************************************************************************
109 //***************************************************************************
111 {
112 public:
113
115 : intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:unsorted", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"D"), file_name_, line_number_)
116 {
117 }
118 };
119
120 //***************************************************************************
123 //***************************************************************************
125 {
126 public:
127
129 : intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:value is already linked", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"E"), file_name_, line_number_)
130 {
131 }
132 };
133
134 //***************************************************************************
137 //***************************************************************************
138 template <typename TLink>
140 {
141 public:
142
143 // Node typedef.
144 typedef TLink link_type;
145
146 //*************************************************************************
148 //*************************************************************************
149 void clear()
150 {
151 // Unlink all of the items.
152 link_type* p_unlink = start.etl_next;
153
154 while (p_unlink != &terminator)
155 {
156 link_type* p_next = p_unlink->etl_next;
157 p_unlink->clear();
158 p_unlink = p_next;
159 }
160
161 initialise();
162 }
163
164 //*************************************************************************
167 //*************************************************************************
168 template <typename TIterator>
169 void assign(TIterator first, TIterator last)
170 {
171#if ETL_IS_DEBUG_BUILD
172 intmax_t d = etl::distance(first, last);
173 ETL_ASSERT_OR_RETURN(d >= 0, ETL_ERROR(intrusive_forward_list_iterator_exception));
174#endif
175
176 clear();
177
178 link_type* p_last = &start;
179
180 // Add all of the elements.
181 while (first != last)
182 {
183 link_type& value = *first++;
184
185 ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked));
186
187 value.etl_next = p_last->etl_next;
188 p_last->etl_next = &value;
189 p_last = &value;
190 ++current_size;
191 }
192 }
193
194 //*************************************************************************
196 //*************************************************************************
197 void push_front(link_type& value)
198 {
199 ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked));
200
201 insert_link_after(start, value);
202 }
203
204 //*************************************************************************
206 //*************************************************************************
208 {
209#if defined(ETL_CHECK_PUSH_POP)
210 ETL_ASSERT_OR_RETURN(!empty(), ETL_ERROR(intrusive_forward_list_empty));
211#endif
213 }
214
215 //*************************************************************************
217 //*************************************************************************
218 void reverse()
219 {
220 if (is_trivial_list())
221 {
222 return;
223 }
224
225 link_type* previous = &terminator; // Point to the terminator of the linked list.
226 link_type* current = start.etl_next; // Point to the first item in the linked list (could be the terminator).
227 link_type* next = start.etl_next; // Point to the first item in the linked list (could be the terminator).
228
229 while (next != &terminator)
230 {
231 next = next->etl_next; // Point to next link.
232 current->etl_next = previous; // Reverse the current link.
233 previous = current; // Previous points to current.
234 current = next; // Current points to next.
235 }
236
237 etl::link<link_type>(start, previous);
238 }
239
240 //*************************************************************************
242 //*************************************************************************
243 bool empty() const
244 {
245 return (current_size == 0);
246 }
247
248 //*************************************************************************
250 //*************************************************************************
251 size_t size() const
252 {
253 return current_size;
254 }
255
256 //*************************************************************************
259 //*************************************************************************
260 bool contains_node(const link_type& search_link) const
261 {
263 }
264
265 //*************************************************************************
268 //*************************************************************************
269 bool contains_node(const link_type* search_link) const
270 {
272 }
273
274 protected:
275
276 link_type start;
277 static link_type terminator;
278
280
281 //*************************************************************************
283 //*************************************************************************
288
289 //*************************************************************************
291 //*************************************************************************
296
297 //*************************************************************************
299 //*************************************************************************
300 bool is_trivial_list() const
301 {
302 return (size() <= 1U);
303 }
304
305 //*************************************************************************
307 //*************************************************************************
308 void insert_link_after(link_type& position, link_type& link)
309 {
310 // Connect to the intrusive_forward_list.
311 etl::link_splice<link_type>(position, link);
312 ++current_size;
313 }
314
315 //*************************************************************************
317 //*************************************************************************
318 void disconnect_link_after(link_type& link)
319 {
320 link_type* p_next = link.etl_next;
321
322 if (p_next != &this->terminator)
323 {
324 link_type* p_unlinked = etl::unlink_after<link_type>(link);
325 if (p_unlinked != ETL_NULLPTR)
326 {
327 p_unlinked->clear();
328 }
329 --current_size;
330 }
331 }
332
333 //*************************************************************************
335 //*************************************************************************
336 link_type* get_head()
337 {
338 return start.etl_next;
339 }
340
341 //*************************************************************************
343 //*************************************************************************
344 const link_type* get_head() const
345 {
346 return start.etl_next;
347 }
348
349 //*************************************************************************
351 //*************************************************************************
353 {
354 start.etl_next = &terminator;
355 current_size = 0;
356 }
357
358 //*************************************************************************
361 //*************************************************************************
362 link_type* is_link_in_list(const link_type* search_link) const
363 {
364 link_type* p_link = start.etl_next;
365 link_type* p_previous = const_cast<link_type*>(&start);
366
367 while (p_link != ETL_NULLPTR)
368 {
369 if (search_link == p_link)
370 {
371 return p_previous;
372 }
373
375 p_link = p_link->link_type::etl_next;
376 }
377
378 return ETL_NULLPTR;
379 }
380
381 //*************************************************************************
385 //*************************************************************************
386 link_type* remove_link(link_type* link)
387 {
388 link_type* result = ETL_NULLPTR;
389
390 link_type* p_previous = is_link_in_list(link);
391
392 if (p_previous != ETL_NULLPTR)
393 {
394 link_type* p_next = link->etl_next;
395
397
398 if (p_next != &this->terminator)
399 {
400 result = p_next;
401 }
402 }
403
404 return result;
405 }
406
407 //*************************************************************************
409 //*************************************************************************
410 link_type* remove_link_range_after(link_type* p_first, link_type* p_last)
411 {
412 link_type* p_after = p_first->etl_next;
413
414 // Join the ends.
416
417 // Unlink the erased range.
418 link_type* p_unlink = p_after;
419
420 while (p_unlink != p_last)
421 {
422 link_type* p_next = p_unlink->etl_next;
423 p_unlink->clear();
424 p_unlink = p_next;
425 }
426
427 if (p_after == &this->terminator)
428 {
429 return ETL_NULLPTR;
430 }
431 else
432 {
433 return p_last;
434 }
435 }
436 };
437
438 template <typename TLink>
440
441 //***************************************************************************
445 //***************************************************************************
446 template <typename TValue, typename TLink>
448 {
449 public:
450
451 // Node typedef.
452 typedef typename etl::intrusive_forward_list_base<TLink>::link_type link_type;
453
454 // STL style typedefs.
455 typedef TValue value_type;
456 typedef value_type* pointer;
457 typedef const value_type* const_pointer;
458 typedef value_type& reference;
459 typedef const value_type& const_reference;
460 typedef size_t size_type;
461
463
464 typedef TValue node_type;
465
466 //*************************************************************************
468 //*************************************************************************
469 class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, value_type>
470 {
471 public:
472
473 friend class intrusive_forward_list;
474 friend class const_iterator;
475
476 iterator()
477 : p_value(ETL_NULLPTR)
478 {
479 }
480
481 iterator(const iterator& other)
482 : p_value(other.p_value)
483 {
484 }
485
486 iterator& operator ++()
487 {
488 // Read the appropriate 'etl_next'.
489 p_value = p_value->etl_next;
490 return *this;
491 }
492
493 iterator operator ++(int)
494 {
495 iterator temp(*this);
496 // Read the appropriate 'etl_next'.
497 p_value = p_value->etl_next;
498 return temp;
499 }
500
501 iterator& operator =(const iterator& other)
502 {
503 p_value = other.p_value;
504 return *this;
505 }
506
507 reference operator *() const
508 {
510 return *static_cast<pointer>(p_value);
512 }
513
514 pointer operator &() const
515 {
516 return static_cast<pointer>(p_value);
517 }
518
519 pointer operator ->() const
520 {
521 return static_cast<pointer>(p_value);
522 }
523
524 friend bool operator == (const iterator& lhs, const iterator& rhs)
525 {
526 return lhs.p_value == rhs.p_value;
527 }
528
529 friend bool operator != (const iterator& lhs, const iterator& rhs)
530 {
531 return !(lhs == rhs);
532 }
533
534 private:
535
536 iterator(link_type* value)
537 : p_value(value)
538 {
539 }
540
541 link_type* p_value;
542 };
543
544 //*************************************************************************
546 //*************************************************************************
547 class const_iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, const value_type>
548 {
549 public:
550
551 friend class intrusive_forward_list;
552
554 : p_value(ETL_NULLPTR)
555 {
556 }
557
559 : p_value(other.p_value)
560 {
561 }
562
564 : p_value(other.p_value)
565 {
566 }
567
568 const_iterator& operator ++()
569 {
570 // Read the appropriate 'etl_next'.
571 p_value = p_value->etl_next;
572 return *this;
573 }
574
575 const_iterator operator ++(int)
576 {
577 const_iterator temp(*this);
578 // Read the appropriate 'etl_next'.
579 p_value = p_value->etl_next;
580 return temp;
581 }
582
583 const_iterator& operator =(const const_iterator& other)
584 {
585 p_value = other.p_value;
586 return *this;
587 }
588
589 const_reference operator *() const
590 {
591 return *static_cast<const value_type*>(p_value);
592 }
593
594 const_pointer operator &() const
595 {
596 return static_cast<const value_type*>(p_value);
597 }
598
599 const_pointer operator ->() const
600 {
601 return static_cast<const value_type*>(p_value);
602 }
603
604 friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
605 {
606 return lhs.p_value == rhs.p_value;
607 }
608
609 friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
610 {
611 return !(lhs == rhs);
612 }
613
614 private:
615
616 const_iterator(const link_type* value)
617 : p_value(value)
618 {
619 }
620
621 const link_type* p_value;
622 };
623
624 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
625
626 //*************************************************************************
628 //*************************************************************************
632
633 //*************************************************************************
635 //*************************************************************************
639
640 //*************************************************************************
642 //*************************************************************************
643 template <typename TIterator>
645 {
646 this->assign(first, last);
647 }
648
649#if ETL_USING_CPP11
650 //*************************************************************************
652 //*************************************************************************
653 template <typename... TLinks>
654 intrusive_forward_list(link_type& first, TLinks&... links)
655 {
656 ETL_STATIC_ASSERT((etl::is_base_of_all<link_type, TLinks...>::value), "Mixed link types");
657
658 this->current_size = 0;
659 this->start.etl_next = &first;
660 link_type* last = make_linked_list(this->current_size, first, static_cast<link_type&>(links)...);
661 last->etl_next = &this->terminator;
662 }
663#endif
664
665 //*************************************************************************
667 //*************************************************************************
669 {
670 return iterator(this->get_head());
671 }
672
673 //*************************************************************************
675 //*************************************************************************
677 {
678 return const_iterator(this->get_head());
679 }
680
681 //*************************************************************************
683 //*************************************************************************
685 {
686 return iterator(&this->start);
687 }
688
689 //*************************************************************************
691 //*************************************************************************
693 {
694 return const_iterator(&this->start);
695 }
696
697 //*************************************************************************
699 //*************************************************************************
701 {
702 return const_iterator(this->get_head());
703 }
704
705 //*************************************************************************
707 //*************************************************************************
709 {
710 return iterator(&this->terminator);
711 }
712
713 //*************************************************************************
715 //*************************************************************************
717 {
718 return const_iterator(&this->terminator);
719 }
720
721 //*************************************************************************
723 //*************************************************************************
725 {
726 return const_iterator(&this->terminator);
727 }
728
729 //*************************************************************************
731 //*************************************************************************
732 reference front()
733 {
734 return *static_cast<pointer>(this->get_head());
735 }
736
737 //*************************************************************************
739 //*************************************************************************
740 const_reference front() const
741 {
742 return *static_cast<const value_type*>(this->get_head());
743 }
744
745 //*************************************************************************
747 //*************************************************************************
748 iterator insert_after(iterator position, value_type& value)
749 {
750 ETL_ASSERT_OR_RETURN_VALUE(!value.link_type::is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked), iterator(&value));
751
752 this->insert_link_after(*position.p_value, value);
753 return iterator(&value);
754 }
755
756 //*************************************************************************
758 //*************************************************************************
759 template <typename TIterator>
760 void insert_after(iterator position, TIterator first, TIterator last)
761 {
762 while (first != last)
763 {
764 // Set up the next free link.
765 ETL_ASSERT_OR_RETURN(!(*first).link_type::is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked));
766
767 this->insert_link_after(*position.p_value, *first);
768 ++first;
769 ++position;
770 }
771 }
772
773 //*************************************************************************
775 //*************************************************************************
777 {
778 iterator next(position);
779 if (next != end())
780 {
781 ++next;
782 if (next != end())
783 {
784 ++next;
785 this->disconnect_link_after(*position.p_value);
786 }
787 }
788
789 return next;
790 }
791
792 //*************************************************************************
794 //*************************************************************************
796 {
797 if (first != end() && (first != last))
798 {
799 this->current_size -= etl::distance(first, last) - 1;
800
801 link_type* p_first = first.p_value;
802 link_type* p_last = last.p_value;
803 link_type* p_after = this->remove_link_range_after(p_first, p_last);
804
805 if (p_after == ETL_NULLPTR)
806 {
807 return end();
808 }
809 else
810 {
811 return last;
812 }
813 }
814 else
815 {
816 return last;
817 }
818 }
819
820 //*************************************************************************
822 //*************************************************************************
823 node_type* erase(const node_type& node)
824 {
825 return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(&node)));
826 }
827
828 //*************************************************************************
830 //*************************************************************************
831 node_type* erase(const node_type* p_node)
832 {
833 return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(p_node)));
834 }
835
836 //*************************************************************************
839 //*************************************************************************
840 template <typename TIsEqual>
842 {
843 if (this->empty())
844 {
845 return;
846 }
847
848 link_type* last = this->get_head();
849 link_type* current = last->etl_next;
850
851 while (current != &this->terminator)
852 {
853 // Is this value the same as the last?
854 if (isEqual(*static_cast<pointer>(current), *static_cast<pointer>(last)))
855 {
856 this->disconnect_link_after(*last);
857 }
858 else
859 {
860 // Move on one.
861 last = current;
862 }
863
864 current = last->etl_next;
865 }
866 }
867
868 //*************************************************************************
870 //*************************************************************************
871 void sort()
872 {
874 }
875
876 //*************************************************************************
900 //*************************************************************************
901 template <typename TCompare>
903 {
909 int list_size = 1;
911 int left_size;
912 int right_size;
913
914 if (this->is_trivial_list())
915 {
916 return;
917 }
918
919 while (true)
920 {
921 i_left = begin();
924
925 number_of_merges = 0; // Count the number of merges we do in this pass.
926
927 while (i_left != end())
928 {
929 ++number_of_merges; // There exists a merge to be done.
930 i_right = i_left;
931 left_size = 0;
932
933 // Step 'list_size' places along from left
934 for (int i = 0; i < list_size; ++i)
935 {
936 ++left_size;
937
938 ++i_right;
939
940 if (i_right == end())
941 {
942 break;
943 }
944 }
945
946 // If right hasn't fallen off end, we have two lists to merge.
948
949 // Now we have two lists. Merge them.
950 while (left_size > 0 || (right_size > 0 && i_right != end()))
951 {
952 // Decide whether the next link of merge comes from left or right.
953 if (left_size == 0)
954 {
955 // Left is empty. The link must come from right.
956 i_link = i_right;
957 ++i_right;
958 --right_size;
959 }
960 else if (right_size == 0 || i_right == end())
961 {
962 // Right is empty. The link must come from left.
963 i_link = i_left;
964 ++i_left;
965 --left_size;
966 }
967 else if (!compare(*i_right, *i_left))
968 {
969 // First link of left is lower or same. The link must come from left.
970 i_link = i_left;
971 ++i_left;
972 --left_size;
973 }
974 else
975 {
976 // First link of right is lower. The link must come from right.
977 i_link = i_right;
978 ++i_right;
979 --right_size;
980 }
981
982 // Add the next link to the merged head.
983 if (i_head == before_begin())
984 {
985 etl::link<link_type>(i_head.p_value, i_link.p_value);
986 i_head = i_link;
987 i_tail = i_link;
988 }
989 else
990 {
991 etl::link<link_type>(i_tail.p_value, i_link.p_value);
992 i_tail = i_link;
993 }
994
995 i_tail.p_value->etl_next = &this->terminator;
996 }
997
998 // Now left has stepped `list_size' places along, and right has too.
999 i_left = i_right;
1000 }
1001
1002 // If we have done only one merge, we're finished.
1003 if (number_of_merges <= 1) // Allow for number_of_merges == 0, the empty head case
1004 {
1005 return;
1006 }
1007
1008 // Otherwise repeat, merging lists twice the size
1009 list_size *= 2;
1010 }
1011 }
1012
1013 //*************************************************************************
1014 // Removes the values specified.
1015 //*************************************************************************
1016 void remove(const_reference value)
1017 {
1018 iterator i_item = begin();
1020
1021 while (i_item != end())
1022 {
1023 if (*i_item == value)
1024 {
1026 }
1027 else
1028 {
1029 ++i_item;
1030 ++i_last_item;
1031 }
1032 }
1033 }
1034
1035 //*************************************************************************
1037 //*************************************************************************
1038 template <typename TPredicate>
1040 {
1041 iterator i_item = begin();
1043
1044 while (i_item != end())
1045 {
1046 if (predicate(*i_item))
1047 {
1049 }
1050 else
1051 {
1052 ++i_item;
1053 ++i_last_item;
1054 }
1055 }
1056 }
1057
1058 //*************************************************************************
1060 //*************************************************************************
1062 {
1063 // No point splicing to ourself!
1064 if (&other != this)
1065 {
1066 if (!other.empty())
1067 {
1068 link_type& first = *other.get_head();
1069
1070 if (&other != this)
1071 {
1072 this->current_size += other.size();
1073 }
1074
1075 link_type& before = *position.p_value;
1076 link_type& after = *position.p_value->etl_next;
1077
1079
1080 link_type* last = &before;
1081 while (last->etl_next != &other.terminator)
1082 {
1083 last = last->etl_next;
1084 }
1085
1087
1088 other.initialise();
1089 }
1090 }
1091 }
1092
1093 //*************************************************************************
1095 //*************************************************************************
1097 {
1098 link_type& before = *position.p_value;
1099
1102
1103 if (&other != this)
1104 {
1105 ++this->current_size;
1106 --other.current_size;
1107 }
1108 }
1109
1110 //*************************************************************************
1112 //*************************************************************************
1114 {
1115 if (!other.empty())
1116 {
1117 if (&other != this)
1118 {
1119 size_t n = etl::distance(begin_, end_) - 1;
1120 this->current_size += n;
1121 other.current_size -= n;
1122 }
1123
1124 link_type* first = begin_.p_value;
1125 link_type* last = first;
1126
1127 while (last->etl_next != end_.p_value)
1128 {
1129 last = last->etl_next;
1130 }
1131
1132 // Unlink from the source list.
1133 link_type* first_next = first->etl_next;
1134 etl::unlink_after(*first, *last);
1135
1136 // Fix our links.
1137 link_type* before = position.p_value;
1138
1140 }
1141 }
1142
1143 //*************************************************************************
1145 //*************************************************************************
1147 {
1149 }
1150
1151 //*************************************************************************
1153 //*************************************************************************
1154 template <typename TCompare>
1156 {
1157 if ((this != &other) && !other.empty())
1158 {
1159#if ETL_IS_DEBUG_BUILD
1162#endif
1163
1164 link_type* other_begin = other.get_head();
1165 link_type* other_terminal = &other.terminator;
1166
1167 link_type* before = &this->start;
1168 link_type* before_next = get_next(before);
1169 link_type* terminal = &this->terminator;;
1170
1171 while ((before->etl_next != terminal) && (other_begin != other_terminal))
1172 {
1173 // Find the place to insert.
1174 while ((before_next != terminal) && !(compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(before_next))))
1175 {
1177 before_next = get_next(before_next);
1178 }
1179
1180 // Insert.
1181 if (before_next != terminal)
1182 {
1183 while ((other_begin != other_terminal) && (compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(before_next))))
1184 {
1185 link_type* value = other_begin;
1186 other_begin = get_next(other_begin);
1188 before = get_next(before);
1189 }
1190 }
1191 }
1192
1193 // Any left over?
1194 if (before_next == terminal)
1195 {
1196 while (other_begin != other_terminal)
1197 {
1198 link_type* value = other_begin;
1199 other_begin = get_next(other_begin);
1201 before = get_next(before);
1202 }
1203 }
1204
1205 this->current_size += other.size();
1206
1207 other.initialise();
1208 }
1209 }
1210
1211 //*************************************************************************
1214 //*************************************************************************
1215 bool contains(const_reference value) const
1216 {
1218
1219 while (i_item != end())
1220 {
1221 if (*i_item == value)
1222 {
1223 return true;
1224 }
1225
1226 ++i_item;
1227 }
1228
1229 return false;
1230 }
1231
1232 private:
1233
1234#if ETL_USING_CPP17
1235 //***************************************************************************
1237 //***************************************************************************
1238 template <typename... TLinks>
1239 link_type* make_linked_list(size_t& count, link_type& first, TLinks&... links)
1240 {
1241 link_type* current = &first;
1242 ++count;
1243 ((current->etl_next = &links, current = &links, ++count), ...);
1244
1245 return current;
1246 }
1247#elif ETL_USING_CPP11
1248 //***************************************************************************
1250 //***************************************************************************
1251 link_type* make_linked_list(size_t& count, link_type& first)
1252 {
1253 ++count;
1254 return &first;
1255 }
1256
1257 //***************************************************************************
1259 //***************************************************************************
1260 template <typename... TLinks>
1261 link_type* make_linked_list(size_t& count, link_type& first, link_type& next, TLinks&... links)
1262 {
1263 ++count;
1264 first.etl_next = &next;
1265 return make_linked_list(count, next, static_cast<link_type&>(links)...);
1266 }
1267#endif
1268
1269 //*************************************************************************
1271 //*************************************************************************
1272 link_type* get_next(link_type* link) const
1273 {
1274 return link->etl_next;
1275 }
1276
1277 // Disabled.
1280 };
1281}
1282
1283#include "private/minmax_pop.h"
1284
1285#endif
const_iterator
Definition intrusive_forward_list.h:548
iterator.
Definition intrusive_forward_list.h:470
Definition intrusive_forward_list.h:140
bool contains_node(const link_type &search_link) const
Definition intrusive_forward_list.h:260
bool is_trivial_list() const
Is the intrusive_forward_list a trivial length?
Definition intrusive_forward_list.h:300
link_type start
The link pointer that acts as the intrusive_forward_list start.
Definition intrusive_forward_list.h:276
void reverse()
Reverses the intrusive_forward_list.
Definition intrusive_forward_list.h:218
void insert_link_after(link_type &position, link_type &link)
Insert a link.
Definition intrusive_forward_list.h:308
~intrusive_forward_list_base()
Destructor.
Definition intrusive_forward_list.h:292
bool empty() const
Returns true if the list has no elements.
Definition intrusive_forward_list.h:243
static link_type terminator
The link that acts as the intrusive_forward_list terminator.
Definition intrusive_forward_list.h:277
size_t current_size
Counts the number of elements in the list.
Definition intrusive_forward_list.h:279
intrusive_forward_list_base()
Constructor.
Definition intrusive_forward_list.h:284
link_type * remove_link(link_type *link)
Definition intrusive_forward_list.h:386
bool contains_node(const link_type *search_link) const
Definition intrusive_forward_list.h:269
void initialise()
Initialise the intrusive_forward_list.
Definition intrusive_forward_list.h:352
void pop_front()
Removes a value from the front of the intrusive_forward_list.
Definition intrusive_forward_list.h:207
link_type * is_link_in_list(const link_type *search_link) const
Definition intrusive_forward_list.h:362
link_type * get_head()
Get the head link.
Definition intrusive_forward_list.h:336
const link_type * get_head() const
Get the head link.
Definition intrusive_forward_list.h:344
void disconnect_link_after(link_type &link)
Remove a link.
Definition intrusive_forward_list.h:318
void assign(TIterator first, TIterator last)
Definition intrusive_forward_list.h:169
size_t size() const
Returns the number of elements.
Definition intrusive_forward_list.h:251
void push_front(link_type &value)
Pushes a value to the front of the intrusive_forward_list.
Definition intrusive_forward_list.h:197
void clear()
Clears the intrusive_forward_list.
Definition intrusive_forward_list.h:149
link_type * remove_link_range_after(link_type *p_first, link_type *p_last)
Remove a range of elements.
Definition intrusive_forward_list.h:410
Definition intrusive_forward_list.h:69
Definition intrusive_forward_list.h:55
Definition intrusive_forward_list.h:97
Definition intrusive_forward_list.h:83
Definition intrusive_forward_list.h:111
Definition intrusive_forward_list.h:125
Definition intrusive_forward_list.h:448
const_iterator before_begin() const
Gets before the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:692
bool contains(const_reference value) const
Definition intrusive_forward_list.h:1215
iterator erase_after(iterator first, iterator last)
Erases a range of elements.
Definition intrusive_forward_list.h:795
void sort(TCompare compare)
Definition intrusive_forward_list.h:902
const_iterator cbegin() const
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:700
void splice_after(iterator position, etl::intrusive_forward_list< TValue, TLink > &other)
Splice another list into this one.
Definition intrusive_forward_list.h:1061
~intrusive_forward_list()
Destructor.
Definition intrusive_forward_list.h:636
void unique(TIsEqual isEqual)
Definition intrusive_forward_list.h:841
void splice_after(iterator position, etl::intrusive_forward_list< TValue, TLink > &other, iterator begin_, iterator end_)
Splice a range of elements from another list into this one.
Definition intrusive_forward_list.h:1113
void splice_after(iterator position, etl::intrusive_forward_list< TValue, TLink > &other, iterator isource)
Splice an element from another list into this one.
Definition intrusive_forward_list.h:1096
void insert_after(iterator position, TIterator first, TIterator last)
Inserts a range of values to the intrusive_forward_list after the specified position.
Definition intrusive_forward_list.h:760
intrusive_forward_list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Constructor from range.
Definition intrusive_forward_list.h:644
void remove_if(TPredicate predicate)
Removes according to a predicate.
Definition intrusive_forward_list.h:1039
iterator erase_after(iterator position)
Erases the value at the specified position.
Definition intrusive_forward_list.h:776
iterator insert_after(iterator position, value_type &value)
Inserts a value to the intrusive_forward_list after the specified position.
Definition intrusive_forward_list.h:748
const_iterator begin() const
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:676
void merge(list_type &other, TCompare compare)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_forward_list.h:1155
iterator end()
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:708
iterator before_begin()
Gets before the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:684
const_iterator end() const
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:716
const_reference front() const
Gets a const reference to the first element.
Definition intrusive_forward_list.h:740
const_iterator cend() const
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:724
void merge(list_type &other)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_forward_list.h:1146
void sort()
Sort using in-place merge sort algorithm.
Definition intrusive_forward_list.h:871
intrusive_forward_list()
Constructor.
Definition intrusive_forward_list.h:629
iterator begin()
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:668
node_type * erase(const node_type *p_node)
Erases the specified node.
Definition intrusive_forward_list.h:831
node_type * erase(const node_type &node)
Erases the specified node.
Definition intrusive_forward_list.h:823
reference front()
Gets a reference to the first element.
Definition intrusive_forward_list.h:732
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