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 //***************************************************************************
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_, line_number_)
74 {
75 }
76 };
77
78 //***************************************************************************
81 //***************************************************************************
82 class intrusive_forward_list_iterator_exception : public intrusive_forward_list_exception
83 {
84 public:
85
86 intrusive_forward_list_iterator_exception(string_type file_name_, numeric_type line_number_)
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 //***************************************************************************
96 class intrusive_forward_list_index_exception : public intrusive_forward_list_exception
97 {
98 public:
99
100 intrusive_forward_list_index_exception(string_type file_name_, numeric_type line_number_)
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 //***************************************************************************
110 class intrusive_forward_list_unsorted : public intrusive_forward_list_exception
111 {
112 public:
113
114 intrusive_forward_list_unsorted(string_type file_name_, numeric_type line_number_)
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 //***************************************************************************
124 class intrusive_forward_list_value_is_already_linked : public intrusive_forward_list_exception
125 {
126 public:
127
128 intrusive_forward_list_value_is_already_linked(string_type file_name_, numeric_type line_number_)
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 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(intrusive_forward_list_empty));
210
212 }
213
214 //*************************************************************************
216 //*************************************************************************
217 void reverse()
218 {
219 if (is_trivial_list())
220 {
221 return;
222 }
223
224 link_type* previous = &terminator; // Point to the terminator of the linked list.
225 link_type* current = start.etl_next; // Point to the first item in the linked list (could be the terminator).
226 link_type* next = start.etl_next; // Point to the first item in the linked list (could be the terminator).
227
228 while (next != &terminator)
229 {
230 next = next->etl_next; // Point to next link.
231 current->etl_next = previous; // Reverse the current link.
232 previous = current; // Previous points to current.
233 current = next; // Current points to next.
234 }
235
236 etl::link<link_type>(start, previous);
237 }
238
239 //*************************************************************************
241 //*************************************************************************
242 bool empty() const
243 {
244 return (current_size == 0);
245 }
246
247 //*************************************************************************
249 //*************************************************************************
250 size_t size() const
251 {
252 return current_size;
253 }
254
255 //*************************************************************************
258 //*************************************************************************
259 bool contains_node(const link_type& search_link) const
260 {
261 return is_link_in_list(&search_link);
262 }
263
264 //*************************************************************************
267 //*************************************************************************
268 bool contains_node(const link_type* search_link) const
269 {
270 return is_link_in_list(search_link);
271 }
272
273 protected:
274
275 link_type start;
276 static link_type terminator;
277
279
280 //*************************************************************************
282 //*************************************************************************
287
288 //*************************************************************************
290 //*************************************************************************
295
296 //*************************************************************************
298 //*************************************************************************
299 bool is_trivial_list() const
300 {
301 return (size() <= 1U);
302 }
303
304 //*************************************************************************
306 //*************************************************************************
307 void insert_link_after(link_type& position, link_type& link)
308 {
309 // Connect to the intrusive_forward_list.
310 etl::link_splice<link_type>(position, link);
311 ++current_size;
312 }
313
314 //*************************************************************************
316 //*************************************************************************
317 void disconnect_link_after(link_type& link)
318 {
319 link_type* p_next = link.etl_next;
320
321 if (p_next != &this->terminator)
322 {
323 link_type* p_unlinked = etl::unlink_after<link_type>(link);
324 if (p_unlinked != ETL_NULLPTR)
325 {
326 p_unlinked->clear();
327 }
328 --current_size;
329 }
330 }
331
332 //*************************************************************************
334 //*************************************************************************
335 link_type* get_head()
336 {
337 return start.etl_next;
338 }
339
340 //*************************************************************************
342 //*************************************************************************
343 const link_type* get_head() const
344 {
345 return start.etl_next;
346 }
347
348 //*************************************************************************
350 //*************************************************************************
352 {
353 start.etl_next = &terminator;
354 current_size = 0;
355 }
356
357 //*************************************************************************
360 //*************************************************************************
361 link_type* is_link_in_list(const link_type* search_link) const
362 {
363 link_type* p_link = start.etl_next;
364 link_type* p_previous = const_cast<link_type*>(&start);
365
366 while (p_link != ETL_NULLPTR)
367 {
368 if (search_link == p_link)
369 {
370 return p_previous;
371 }
372
373 p_previous = p_link;
374 p_link = p_link->link_type::etl_next;
375 }
376
377 return ETL_NULLPTR;
378 }
379
380 //*************************************************************************
384 //*************************************************************************
385 link_type* remove_link(link_type* link)
386 {
387 link_type* result = ETL_NULLPTR;
388
389 link_type* p_previous = is_link_in_list(link);
390
391 if (p_previous != ETL_NULLPTR)
392 {
393 link_type* p_next = link->etl_next;
394
395 disconnect_link_after(*p_previous);
396
397 if (p_next != &this->terminator)
398 {
399 result = p_next;
400 }
401 }
402
403 return result;
404 }
405
406 //*************************************************************************
408 //*************************************************************************
409 link_type* remove_link_range_after(link_type* p_first, link_type* p_last)
410 {
411 link_type* p_after = p_first->etl_next;
412
413 // Join the ends.
414 etl::link<link_type>(p_first, p_last);
415
416 // Unlink the erased range.
417 link_type* p_unlink = p_after;
418
419 while (p_unlink != p_last)
420 {
421 link_type* p_next = p_unlink->etl_next;
422 p_unlink->clear();
423 p_unlink = p_next;
424 }
425
426 if (p_after == &this->terminator)
427 {
428 return ETL_NULLPTR;
429 }
430 else
431 {
432 return p_last;
433 }
434 }
435 };
436
437 template <typename TLink>
439
440 //***************************************************************************
444 //***************************************************************************
445 template <typename TValue, typename TLink>
447 {
448 public:
449
450 // Node typedef.
451 typedef typename etl::intrusive_forward_list_base<TLink>::link_type link_type;
452
453 // STL style typedefs.
454 typedef TValue value_type;
455 typedef value_type* pointer;
456 typedef const value_type* const_pointer;
457 typedef value_type& reference;
458 typedef const value_type& const_reference;
459 typedef size_t size_type;
460
462
463 typedef TValue node_type;
464
465 //*************************************************************************
467 //*************************************************************************
468 class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, value_type>
469 {
470 public:
471
472 friend class intrusive_forward_list;
473 friend class const_iterator;
474
475 iterator()
476 : p_value(ETL_NULLPTR)
477 {
478 }
479
480 iterator(const iterator& other)
481 : p_value(other.p_value)
482 {
483 }
484
485 iterator& operator ++()
486 {
487 // Read the appropriate 'etl_next'.
488 p_value = p_value->etl_next;
489 return *this;
490 }
491
492 iterator operator ++(int)
493 {
494 iterator temp(*this);
495 // Read the appropriate 'etl_next'.
496 p_value = p_value->etl_next;
497 return temp;
498 }
499
500 iterator& operator =(const iterator& other)
501 {
502 p_value = other.p_value;
503 return *this;
504 }
505
506 reference operator *() const
507 {
509 return *static_cast<pointer>(p_value);
511 }
512
513 pointer operator &() const
514 {
515 return static_cast<pointer>(p_value);
516 }
517
518 pointer operator ->() const
519 {
520 return static_cast<pointer>(p_value);
521 }
522
523 friend bool operator == (const iterator& lhs, const iterator& rhs)
524 {
525 return lhs.p_value == rhs.p_value;
526 }
527
528 friend bool operator != (const iterator& lhs, const iterator& rhs)
529 {
530 return !(lhs == rhs);
531 }
532
533 private:
534
535 iterator(link_type* value)
536 : p_value(value)
537 {
538 }
539
540 link_type* p_value;
541 };
542
543 //*************************************************************************
545 //*************************************************************************
546 class const_iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, const value_type>
547 {
548 public:
549
550 friend class intrusive_forward_list;
551
552 const_iterator()
553 : p_value(ETL_NULLPTR)
554 {
555 }
556
557 const_iterator(const typename intrusive_forward_list::iterator& other)
558 : p_value(other.p_value)
559 {
560 }
561
562 const_iterator(const const_iterator& other)
563 : p_value(other.p_value)
564 {
565 }
566
567 const_iterator& operator ++()
568 {
569 // Read the appropriate 'etl_next'.
570 p_value = p_value->etl_next;
571 return *this;
572 }
573
574 const_iterator operator ++(int)
575 {
576 const_iterator temp(*this);
577 // Read the appropriate 'etl_next'.
578 p_value = p_value->etl_next;
579 return temp;
580 }
581
582 const_iterator& operator =(const const_iterator& other)
583 {
584 p_value = other.p_value;
585 return *this;
586 }
587
588 const_reference operator *() const
589 {
590 return *static_cast<const value_type*>(p_value);
591 }
592
593 const_pointer operator &() const
594 {
595 return static_cast<const value_type*>(p_value);
596 }
597
598 const_pointer operator ->() const
599 {
600 return static_cast<const value_type*>(p_value);
601 }
602
603 friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
604 {
605 return lhs.p_value == rhs.p_value;
606 }
607
608 friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
609 {
610 return !(lhs == rhs);
611 }
612
613 private:
614
615 const_iterator(const link_type* value)
616 : p_value(value)
617 {
618 }
619
620 const link_type* p_value;
621 };
622
623 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
624
625 //*************************************************************************
627 //*************************************************************************
631
632 //*************************************************************************
634 //*************************************************************************
638
639 //*************************************************************************
641 //*************************************************************************
642 template <typename TIterator>
643 intrusive_forward_list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
644 {
645 this->assign(first, last);
646 }
647
648#if ETL_USING_CPP11
649 //*************************************************************************
651 //*************************************************************************
652 template <typename... TLinks>
653 intrusive_forward_list(link_type& first, TLinks&... links)
654 {
655 ETL_STATIC_ASSERT((etl::is_base_of_all<link_type, TLinks...>::value), "Mixed link types");
656
657 this->current_size = 0;
658 this->start.etl_next = &first;
659 link_type* last = make_linked_list(this->current_size, first, static_cast<link_type&>(links)...);
660 last->etl_next = &this->terminator;
661 }
662#endif
663
664 //*************************************************************************
666 //*************************************************************************
667 iterator begin()
668 {
669 return iterator(this->get_head());
670 }
671
672 //*************************************************************************
674 //*************************************************************************
675 const_iterator begin() const
676 {
677 return const_iterator(this->get_head());
678 }
679
680 //*************************************************************************
682 //*************************************************************************
683 iterator before_begin()
684 {
685 return iterator(&this->start);
686 }
687
688 //*************************************************************************
690 //*************************************************************************
691 const_iterator before_begin() const
692 {
693 return const_iterator(&this->start);
694 }
695
696 //*************************************************************************
698 //*************************************************************************
699 const_iterator cbegin() const
700 {
701 return const_iterator(this->get_head());
702 }
703
704 //*************************************************************************
706 //*************************************************************************
707 iterator end()
708 {
709 return iterator(&this->terminator);
710 }
711
712 //*************************************************************************
714 //*************************************************************************
715 const_iterator end() const
716 {
717 return const_iterator(&this->terminator);
718 }
719
720 //*************************************************************************
722 //*************************************************************************
723 const_iterator cend() const
724 {
725 return const_iterator(&this->terminator);
726 }
727
728 //*************************************************************************
730 //*************************************************************************
731 reference front()
732 {
733 return *static_cast<pointer>(this->get_head());
734 }
735
736 //*************************************************************************
738 //*************************************************************************
739 const_reference front() const
740 {
741 return *static_cast<const value_type*>(this->get_head());
742 }
743
744 //*************************************************************************
746 //*************************************************************************
747 iterator insert_after(iterator position, value_type& value)
748 {
749 ETL_ASSERT_OR_RETURN_VALUE(!value.link_type::is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked), iterator(&value));
750
751 this->insert_link_after(*position.p_value, value);
752 return iterator(&value);
753 }
754
755 //*************************************************************************
757 //*************************************************************************
758 template <typename TIterator>
759 void insert_after(iterator position, TIterator first, TIterator last)
760 {
761 while (first != last)
762 {
763 // Set up the next free link.
764 ETL_ASSERT_OR_RETURN(!(*first).link_type::is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked));
765
766 this->insert_link_after(*position.p_value, *first);
767 ++first;
768 ++position;
769 }
770 }
771
772 //*************************************************************************
774 //*************************************************************************
775 iterator erase_after(iterator position)
776 {
777 iterator next(position);
778 if (next != end())
779 {
780 ++next;
781 if (next != end())
782 {
783 ++next;
784 this->disconnect_link_after(*position.p_value);
785 }
786 }
787
788 return next;
789 }
790
791 //*************************************************************************
793 //*************************************************************************
794 iterator erase_after(iterator first, iterator last)
795 {
796 if (first != end() && (first != last))
797 {
798 this->current_size -= etl::distance(first, last) - 1;
799
800 link_type* p_first = first.p_value;
801 link_type* p_last = last.p_value;
802 link_type* p_after = this->remove_link_range_after(p_first, p_last);
803
804 if (p_after == ETL_NULLPTR)
805 {
806 return end();
807 }
808 else
809 {
810 return last;
811 }
812 }
813 else
814 {
815 return last;
816 }
817 }
818
819 //*************************************************************************
821 //*************************************************************************
822 node_type* erase(const node_type& node)
823 {
824 return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(&node)));
825 }
826
827 //*************************************************************************
829 //*************************************************************************
830 node_type* erase(const node_type* p_node)
831 {
832 return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(p_node)));
833 }
834
835 //*************************************************************************
838 //*************************************************************************
839 template <typename TIsEqual>
840 void unique(TIsEqual isEqual)
841 {
842 if (this->empty())
843 {
844 return;
845 }
846
847 link_type* last = this->get_head();
848 link_type* current = last->etl_next;
849
850 while (current != &this->terminator)
851 {
852 // Is this value the same as the last?
853 if (isEqual(*static_cast<pointer>(current), *static_cast<pointer>(last)))
854 {
855 this->disconnect_link_after(*last);
856 }
857 else
858 {
859 // Move on one.
860 last = current;
861 }
862
863 current = last->etl_next;
864 }
865 }
866
867 //*************************************************************************
869 //*************************************************************************
870 void sort()
871 {
873 }
874
875 //*************************************************************************
899 //*************************************************************************
900 template <typename TCompare>
901 void sort(TCompare compare)
902 {
903 iterator i_left;
904 iterator i_right;
905 iterator i_link;
906 iterator i_head;
907 iterator i_tail;
908 int list_size = 1;
909 int number_of_merges;
910 int left_size;
911 int right_size;
912
913 if (this->is_trivial_list())
914 {
915 return;
916 }
917
918 while (true)
919 {
920 i_left = begin();
921 i_head = before_begin();
922 i_tail = before_begin();
923
924 number_of_merges = 0; // Count the number of merges we do in this pass.
925
926 while (i_left != end())
927 {
928 ++number_of_merges; // There exists a merge to be done.
929 i_right = i_left;
930 left_size = 0;
931
932 // Step 'list_size' places along from left
933 for (int i = 0; i < list_size; ++i)
934 {
935 ++left_size;
936
937 ++i_right;
938
939 if (i_right == end())
940 {
941 break;
942 }
943 }
944
945 // If right hasn't fallen off end, we have two lists to merge.
946 right_size = list_size;
947
948 // Now we have two lists. Merge them.
949 while (left_size > 0 || (right_size > 0 && i_right != end()))
950 {
951 // Decide whether the next link of merge comes from left or right.
952 if (left_size == 0)
953 {
954 // Left is empty. The link must come from right.
955 i_link = i_right;
956 ++i_right;
957 --right_size;
958 }
959 else if (right_size == 0 || i_right == end())
960 {
961 // Right is empty. The link must come from left.
962 i_link = i_left;
963 ++i_left;
964 --left_size;
965 }
966 else if (!compare(*i_right, *i_left))
967 {
968 // First link of left is lower or same. The link must come from left.
969 i_link = i_left;
970 ++i_left;
971 --left_size;
972 }
973 else
974 {
975 // First link of right is lower. The link must come from right.
976 i_link = i_right;
977 ++i_right;
978 --right_size;
979 }
980
981 // Add the next link to the merged head.
982 if (i_head == before_begin())
983 {
984 etl::link<link_type>(i_head.p_value, i_link.p_value);
985 i_head = i_link;
986 i_tail = i_link;
987 }
988 else
989 {
990 etl::link<link_type>(i_tail.p_value, i_link.p_value);
991 i_tail = i_link;
992 }
993
994 i_tail.p_value->etl_next = &this->terminator;
995 }
996
997 // Now left has stepped `list_size' places along, and right has too.
998 i_left = i_right;
999 }
1000
1001 // If we have done only one merge, we're finished.
1002 if (number_of_merges <= 1) // Allow for number_of_merges == 0, the empty head case
1003 {
1004 return;
1005 }
1006
1007 // Otherwise repeat, merging lists twice the size
1008 list_size *= 2;
1009 }
1010 }
1011
1012 //*************************************************************************
1013 // Removes the values specified.
1014 //*************************************************************************
1015 void remove(const_reference value)
1016 {
1017 iterator i_item = begin();
1018 iterator i_last_item = before_begin();
1019
1020 while (i_item != end())
1021 {
1022 if (*i_item == value)
1023 {
1024 i_item = erase_after(i_last_item);
1025 }
1026 else
1027 {
1028 ++i_item;
1029 ++i_last_item;
1030 }
1031 }
1032 }
1033
1034 //*************************************************************************
1036 //*************************************************************************
1037 template <typename TPredicate>
1038 void remove_if(TPredicate predicate)
1039 {
1040 iterator i_item = begin();
1041 iterator i_last_item = before_begin();
1042
1043 while (i_item != end())
1044 {
1045 if (predicate(*i_item))
1046 {
1047 i_item = erase_after(i_last_item);
1048 }
1049 else
1050 {
1051 ++i_item;
1052 ++i_last_item;
1053 }
1054 }
1055 }
1056
1057 //*************************************************************************
1059 //*************************************************************************
1061 {
1062 // No point splicing to ourself!
1063 if (&other != this)
1064 {
1065 if (!other.empty())
1066 {
1067 link_type& first = *other.get_head();
1068
1069 if (&other != this)
1070 {
1071 this->current_size += other.size();
1072 }
1073
1074 link_type& before = *position.p_value;
1075 link_type& after = *position.p_value->etl_next;
1076
1077 etl::link<link_type>(before, first);
1078
1079 link_type* last = &before;
1080 while (last->etl_next != &other.terminator)
1081 {
1082 last = last->etl_next;
1083 }
1084
1085 etl::link<link_type>(last, after);
1086
1087 other.initialise();
1088 }
1089 }
1090 }
1091
1092 //*************************************************************************
1094 //*************************************************************************
1095 void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& other, iterator isource)
1096 {
1097 link_type& before = *position.p_value;
1098
1099 etl::unlink<link_type>(*isource.p_value);
1100 etl::link_splice<link_type>(before, *isource.p_value);
1101
1102 if (&other != this)
1103 {
1104 ++this->current_size;
1105 --other.current_size;
1106 }
1107 }
1108
1109 //*************************************************************************
1111 //*************************************************************************
1112 void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& other, iterator begin_, iterator end_)
1113 {
1114 if (!other.empty())
1115 {
1116 if (&other != this)
1117 {
1118 size_t n = etl::distance(begin_, end_) - 1;
1119 this->current_size += n;
1120 other.current_size -= n;
1121 }
1122
1123 link_type* first = begin_.p_value;
1124 link_type* last = first;
1125
1126 while (last->etl_next != end_.p_value)
1127 {
1128 last = last->etl_next;
1129 }
1130
1131 // Unlink from the source list.
1132 link_type* first_next = first->etl_next;
1133 etl::unlink_after(*first, *last);
1134
1135 // Fix our links.
1136 link_type* before = position.p_value;
1137
1138 etl::link_splice<link_type>(*before, *first_next, *last);
1139 }
1140 }
1141
1142 //*************************************************************************
1144 //*************************************************************************
1145 void merge(list_type& other)
1146 {
1147 merge(other, etl::less<value_type>());
1148 }
1149
1150 //*************************************************************************
1152 //*************************************************************************
1153 template <typename TCompare>
1154 void merge(list_type& other, TCompare compare)
1155 {
1156 if ((this != &other) && !other.empty())
1157 {
1158#if ETL_IS_DEBUG_BUILD
1161#endif
1162
1163 link_type* other_begin = other.get_head();
1164 link_type* other_terminal = &other.terminator;
1165
1166 link_type* before = &this->start;
1167 link_type* before_next = get_next(before);
1168 link_type* terminal = &this->terminator;;
1169
1170 while ((before->etl_next != terminal) && (other_begin != other_terminal))
1171 {
1172 // Find the place to insert.
1173 while ((before_next != terminal) && !(compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(before_next))))
1174 {
1175 before = before_next;
1176 before_next = get_next(before_next);
1177 }
1178
1179 // Insert.
1180 if (before_next != terminal)
1181 {
1182 while ((other_begin != other_terminal) && (compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(before_next))))
1183 {
1184 link_type* value = other_begin;
1185 other_begin = get_next(other_begin);
1186 etl::link_splice<link_type>(*before, *value);
1187 before = get_next(before);
1188 }
1189 }
1190 }
1191
1192 // Any left over?
1193 if (before_next == terminal)
1194 {
1195 while (other_begin != other_terminal)
1196 {
1197 link_type* value = other_begin;
1198 other_begin = get_next(other_begin);
1199 etl::link_splice<link_type>(*before, *value);
1200 before = get_next(before);
1201 }
1202 }
1203
1204 this->current_size += other.size();
1205
1206 other.initialise();
1207 }
1208 }
1209
1210 //*************************************************************************
1213 //*************************************************************************
1214 bool contains(const_reference value) const
1215 {
1216 const_iterator i_item = begin();
1217
1218 while (i_item != end())
1219 {
1220 if (*i_item == value)
1221 {
1222 return true;
1223 }
1224
1225 ++i_item;
1226 }
1227
1228 return false;
1229 }
1230
1231 private:
1232
1233#if ETL_USING_CPP17
1234 //***************************************************************************
1236 //***************************************************************************
1237 template <typename... TLinks>
1238 link_type* make_linked_list(size_t& count, link_type& first, TLinks&... links)
1239 {
1240 link_type* current = &first;
1241 ++count;
1242 ((current->etl_next = &links, current = &links, ++count), ...);
1243
1244 return current;
1245 }
1246#elif ETL_USING_CPP11
1247 //***************************************************************************
1249 //***************************************************************************
1250 link_type* make_linked_list(size_t& count, link_type& first)
1251 {
1252 ++count;
1253 return &first;
1254 }
1255
1256 //***************************************************************************
1258 //***************************************************************************
1259 template <typename... TLinks>
1260 link_type* make_linked_list(size_t& count, link_type& first, link_type& next, TLinks&... links)
1261 {
1262 ++count;
1263 first.etl_next = &next;
1264 return make_linked_list(count, next, static_cast<link_type&>(links)...);
1265 }
1266#endif
1267
1268 //*************************************************************************
1270 //*************************************************************************
1271 link_type* get_next(link_type* link) const
1272 {
1273 return link->etl_next;
1274 }
1275
1276 // Disabled.
1278 intrusive_forward_list& operator = (const intrusive_forward_list& rhs);
1279 };
1280}
1281
1282#include "private/minmax_pop.h"
1283
1284#endif
iterator.
Definition intrusive_forward_list.h:469
Definition intrusive_forward_list.h:140
bool contains_node(const link_type &search_link) const
Definition intrusive_forward_list.h:259
bool is_trivial_list() const
Is the intrusive_forward_list a trivial length?
Definition intrusive_forward_list.h:299
link_type start
Definition intrusive_forward_list.h:275
void reverse()
Reverses the intrusive_forward_list.
Definition intrusive_forward_list.h:217
void insert_link_after(link_type &position, link_type &link)
Insert a link.
Definition intrusive_forward_list.h:307
~intrusive_forward_list_base()
Destructor.
Definition intrusive_forward_list.h:291
bool empty() const
Returns true if the list has no elements.
Definition intrusive_forward_list.h:242
static link_type terminator
Definition intrusive_forward_list.h:276
size_t current_size
Definition intrusive_forward_list.h:278
intrusive_forward_list_base()
Constructor.
Definition intrusive_forward_list.h:283
link_type * remove_link(link_type *link)
Definition intrusive_forward_list.h:385
bool contains_node(const link_type *search_link) const
Definition intrusive_forward_list.h:268
void initialise()
Initialise the intrusive_forward_list.
Definition intrusive_forward_list.h:351
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:361
link_type * get_head()
Get the head link.
Definition intrusive_forward_list.h:335
const link_type * get_head() const
Get the head link.
Definition intrusive_forward_list.h:343
void disconnect_link_after(link_type &link)
Remove a link.
Definition intrusive_forward_list.h:317
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:250
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:409
Definition intrusive_forward_list.h:69
Definition intrusive_forward_list.h:83
Definition intrusive_forward_list.h:111
Definition intrusive_forward_list.h:125
Definition intrusive_forward_list.h:447
const_iterator before_begin() const
Gets before the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:691
bool contains(const_reference value) const
Definition intrusive_forward_list.h:1214
iterator erase_after(iterator first, iterator last)
Erases a range of elements.
Definition intrusive_forward_list.h:794
void sort(TCompare compare)
Definition intrusive_forward_list.h:901
const_iterator cbegin() const
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:699
void splice_after(iterator position, etl::intrusive_forward_list< TValue, TLink > &other)
Splice another list into this one.
Definition intrusive_forward_list.h:1060
~intrusive_forward_list()
Destructor.
Definition intrusive_forward_list.h:635
void unique(TIsEqual isEqual)
Definition intrusive_forward_list.h:840
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:1112
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:1095
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:759
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:643
void remove_if(TPredicate predicate)
Removes according to a predicate.
Definition intrusive_forward_list.h:1038
iterator erase_after(iterator position)
Erases the value at the specified position.
Definition intrusive_forward_list.h:775
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:747
const_iterator begin() const
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:675
void merge(list_type &other, TCompare compare)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_forward_list.h:1154
iterator end()
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:707
iterator before_begin()
Gets before the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:683
const_iterator end() const
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:715
const_reference front() const
Gets a const reference to the first element.
Definition intrusive_forward_list.h:739
const_iterator cend() const
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:723
void merge(list_type &other)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_forward_list.h:1145
void sort()
Sort using in-place merge sort algorithm.
Definition intrusive_forward_list.h:870
intrusive_forward_list()
Constructor.
Definition intrusive_forward_list.h:628
iterator begin()
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:667
node_type * erase(const node_type *p_node)
Erases the specified node.
Definition intrusive_forward_list.h:830
node_type * erase(const node_type &node)
Erases the specified node.
Definition intrusive_forward_list.h:822
reference front()
Gets a reference to the first element.
Definition intrusive_forward_list.h:731
ETL_CONSTEXPR14 bool operator==(const etl::expected< TValue, TError > &lhs, const etl::expected< TValue2, TError2 > &rhs)
Equivalence operators.
Definition expected.h:962
ETL_NODISCARD ETL_CONSTEXPR14 bool is_sorted(TIterator begin, TIterator end)
Definition algorithm.h:1709
ETL_CONSTEXPR14 TIterator remove(TIterator first, TIterator last, const T &value)
Definition algorithm.h:2300
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition exception.h:69
enable_if
Definition type_traits_generator.h:1254
bitset_ext
Definition absolute.h:39
ETL_CONSTEXPR14 enable_if<!etl::is_specialization< TRep2, etl::chrono::duration >::value, etl::chrono::duration< typenameetl::common_type< TRep1, TRep2 >::type, TPeriod1 > >::type operator*(const etl::chrono::duration< TRep1, TPeriod1 > &lhs, const TRep2 &rhs) ETL_NOEXCEPT
Operator *.
Definition duration.h:545
Definition compare.h:51
iterator
Definition iterator.h:399
Definition functional.h:170