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