Embedded Template Library 1.0
Loading...
Searching...
No Matches
intrusive_links.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_LINKS_INCLUDED
32#define ETL_INTRUSIVE_LINKS_INCLUDED
33
34#include "platform.h"
35#include "nullptr.h"
36#include "type_traits.h"
37#include "exception.h"
38#include "error_handler.h"
39#include "utility.h"
40#include "algorithm.h"
41
42#include <assert.h>
43
44//*****************************************************************************
45// Note:
46// The link functions work slightly differently to the STL 'insert' convention
47// in that the second link parameter will be inserted after the first.
48// i.e.
49// If the list contains '1', '2', '3', '4' and "link_splice '2','5'" is invoked the
50// resulting list will contain '1', '2', '5', '3', '4'
51// This is to maintain consistency between forward and bidirectional links
52// and also is intuitive.
53//*****************************************************************************
54
55namespace etl
56{
57 //***************************************************************************
59 //***************************************************************************
60 class link_exception : public etl::exception
61 {
62 public:
63
64 link_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
65 : exception(reason_, file_name_, line_number_)
66 {
67 }
68 };
69
70 //***************************************************************************
72 //***************************************************************************
73 class not_unlinked_exception : public etl::link_exception
74 {
75 public:
76
77 not_unlinked_exception(string_type file_name_, numeric_type line_number_)
78 : link_exception(ETL_ERROR_TEXT("link:still linked", ETL_INTRUSIVE_LINKS_FILE_ID"A"), file_name_, line_number_)
79 {
80 }
81 };
82
83 //***************************************************************************
85 //***************************************************************************
86 template <size_t ID_>
87 struct forward_link
88 {
89 enum
90 {
91 ID = ID_,
92 };
93
94 //***********************************
95 forward_link()
96 : etl_next(ETL_NULLPTR)
97 {
98 }
99
100 //***********************************
101 forward_link(forward_link* p_next)
102 : etl_next(p_next)
103 {
104 }
105
106 //***********************************
107 forward_link(const forward_link& other)
108 : etl_next(other.etl_next)
109 {
110 }
111
112 //***********************************
113 forward_link& operator =(const forward_link& other)
114 {
115 etl_next = other.etl_next;
116
117 return *this;
118 }
119
120 //***********************************
121 void clear()
122 {
123 etl_next = ETL_NULLPTR;
124 }
125
126 //***********************************
127 ETL_NODISCARD
128 bool is_linked() const
129 {
130 return etl_next != ETL_NULLPTR;
131 }
132
133 //***********************************
134 ETL_NODISCARD
135 bool has_next() const
136 {
137 return etl_next != ETL_NULLPTR;
138 }
139
140 //***********************************
141 void set_next(forward_link* n)
142 {
143 etl_next = n;
144 }
145
146 //***********************************
147 void set_next(forward_link& n)
148 {
149 etl_next = &n;
150 }
151
152 //***********************************
153 ETL_NODISCARD
154 forward_link* get_next() const
155 {
156 return etl_next;
157 }
158
159 forward_link* etl_next;
160 };
161
162 //***********************************
163 template <typename TLink>
165 {
166 static ETL_CONSTANT bool value = etl::is_same<TLink, etl::forward_link<TLink::ID> >::value;
167 };
168
169 //***********************************
170#if ETL_USING_CPP17
171 template <typename TLink>
172 inline constexpr bool is_forward_link_v = etl::is_forward_link<TLink>::value;
173#endif
174
175 //***************************************************************************
176 // link
177 //***************************************************************************
178 // Reference, Reference
179 template <typename TLink>
181 link(TLink& lhs, TLink& rhs)
182 {
183 lhs.etl_next = &rhs;
184 }
185
186 //***********************************
187 // Pointer, Pointer
188 template <typename TLink>
190 link(TLink* lhs, TLink* rhs)
191 {
192 if (lhs != ETL_NULLPTR)
193 {
194 lhs->etl_next = rhs;
195 }
196 }
197
198 //***********************************
199 // Reference, Pointer
200 template <typename TLink>
201 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
202 link(TLink& lhs, TLink* rhs)
203 {
204 lhs.etl_next = rhs;
205 }
206
207 //***********************************
208 // Pointer, Reference
209 template <typename TLink>
210 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
211 link(TLink* lhs, TLink& rhs)
212 {
213 if (lhs != ETL_NULLPTR)
214 {
215 lhs->etl_next = &rhs;
216 }
217 }
218
219 //***************************************************************************
220 // link_splice
221 //***************************************************************************
222 // Reference, Reference
223 template <typename TLink>
224 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
225 link_splice(TLink& lhs, TLink& rhs)
226 {
227 rhs.etl_next = lhs.etl_next;
228 lhs.etl_next = &rhs;
229 }
230
231 //***********************************
232 // Pointer, Pointer
233 template <typename TLink>
234 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
235 link_splice(TLink* lhs, TLink* rhs)
236 {
237 if (lhs != ETL_NULLPTR)
238 {
239 if (rhs != ETL_NULLPTR)
240 {
241 rhs->etl_next = lhs->etl_next;
242 }
243
244 lhs->etl_next = rhs;
245 }
246 }
247
248 //***********************************
249 // Reference, Pointer
250 template <typename TLink>
251 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
252 link_splice(TLink& lhs, TLink* rhs)
253 {
254 if (rhs != ETL_NULLPTR)
255 {
256 rhs->etl_next = lhs.etl_next;
257 }
258
259 lhs.etl_next = rhs;
260 }
261
262 //***********************************
263 // Pointer, Reference
264 template <typename TLink>
265 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
266 link_splice(TLink* lhs, TLink& rhs)
267 {
268 if (lhs != ETL_NULLPTR)
269 {
270 rhs.etl_next = lhs->etl_next;
271 lhs->etl_next = &rhs;
272 }
273 }
274
275 //***********************************
276 // Reference, Reference, Reference
277 template <typename TLink>
278 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
279 link_splice(TLink& lhs, TLink& first, TLink& last)
280 {
281 last.etl_next = lhs.etl_next;
282 lhs.etl_next = &first;
283 }
284
285 //***********************************
286 // Pointer, Reference, Reference
287 template <typename TLink>
288 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
289 link_splice(TLink* lhs, TLink& first, TLink& last)
290 {
291 if (lhs != ETL_NULLPTR)
292 {
293 last.etl_next = lhs->etl_next;
294 lhs->etl_next = &first;
295 }
296 else
297 {
298 last.etl_next = ETL_NULLPTR;
299 }
300 }
301
302 //***************************************************************************
303 // unlink_after
304 //***************************************************************************
305 // Reference
306 template <typename TLink>
307 typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
308 unlink_after(TLink& node)
309 {
310 if (node.etl_next != ETL_NULLPTR)
311 {
312 TLink* unlinked_node = node.etl_next;
313 node.etl_next = unlinked_node->etl_next;
314 unlinked_node->clear();
315 return unlinked_node;
316 }
317
318 return node.etl_next;
319 }
320
321 //***********************************
322 // Reference, Reference
323 template <typename TLink>
324 typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
325 unlink_after(TLink& before, TLink& last)
326 {
327 TLink* first = before.etl_next;
328
329 if (&before != &last)
330 {
331 before.etl_next = last.etl_next;
332 last.clear();
333 }
334
335 return first;
336 }
337
338 // Reference
339 template <typename TLink>
340 typename etl::enable_if<etl::is_forward_link<TLink>::value, bool>::type
341 is_linked(TLink& node)
342 {
343 return node.is_linked();
344 }
345
346 // Pointer
347 template <typename TLink>
348 typename etl::enable_if<etl::is_forward_link<TLink>::value, bool>::type
349 is_linked(TLink* node)
350 {
351 return node->is_linked();
352 }
353
354 //***************************************************************************
355 // link_clear
356 //***************************************************************************
357 // Reference
358 template <typename TLink>
359 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
360 link_clear(TLink& start)
361 {
362 start.etl_next = ETL_NULLPTR;
363 }
364
365 //***********************************
366 // Pointer
367 template <typename TLink>
368 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
369 link_clear(TLink* start)
370 {
371 if (start != ETL_NULLPTR)
372 {
373 etl::link_clear(*start);
374 }
375 }
376
377 //***************************************************************************
378 // link_clear range
379 //***************************************************************************
380 // Reference
381 template <typename TLink>
382 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
383 link_clear_range(TLink& start)
384 {
385 TLink* current = &start;
386
387 while (current != ETL_NULLPTR)
388 {
389 TLink* next = current->etl_next;
390 current->clear();
391 current = next;
392 }
393 }
394
395 //***********************************
396 // Pointer
397 template <typename TLink>
398 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
399 link_clear_range(TLink* start)
400 {
401 if (start != ETL_NULLPTR)
402 {
403 etl::link_clear_range(*start);
404 }
405 }
406
407#if ETL_USING_CPP17
408 //***************************************************************************
410 //***************************************************************************
411 template <typename TLink, typename... TLinks>
412 typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
413 create_linked_list(TLink& first, TLinks&... links)
414 {
415 TLink* current = &first;
416 ((current->etl_next = &links, current = &links), ...);
417
418 return current;
419 }
420
421 //***************************************************************************
423 //***************************************************************************
424 template <typename TLink, typename... TLinks>
425 typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
426 create_linked_list(TLink* first, TLinks*... links)
427 {
428 if (first != ETL_NULLPTR)
429 {
430 return create_linked_list(*first, (*links)...);
431 }
432 else
433 {
434 return nullptr;
435 }
436 }
437#elif ETL_USING_CPP11
438 //***************************************************************************
440 //***************************************************************************
441 template <typename TLink>
442 typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
443 create_linked_list(TLink& first)
444 {
445 return &first;
446 }
447
448 //***************************************************************************
450 //***************************************************************************
451 template <typename TLink, typename... TLinks>
452 typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
453 create_linked_list(TLink& first, TLink& next, TLinks&... links)
454 {
455 first.etl_next = &next;
456 return create_linked_list(next, static_cast<TLink&>(links)...);
457 }
458
459 //***************************************************************************
461 //***************************************************************************
462 template <typename TLink>
463 typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
464 create_linked_list(TLink* first)
465 {
466 if (first != ETL_NULLPTR)
467 {
468 return create_linked_list(*first);
469 }
470 else
471 {
472 return ETL_NULLPTR;
473 }
474 }
475
476 //***************************************************************************
478 //***************************************************************************
479 template <typename TLink, typename... TLinks>
480 typename etl::enable_if<etl::is_forward_link<TLink>::value, TLink*>::type
481 create_linked_list(TLink* first, TLink* next, TLinks*... links)
482 {
483 if (first != ETL_NULLPTR)
484 {
485 return create_linked_list(*first, *next, static_cast<TLink&>(*links)...);
486 }
487 else
488 {
489 return ETL_NULLPTR;
490 }
491 }
492#endif
493
494 //***************************************************************************
495 template <typename TLink>
496 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
497 detach_linked_list(TLink& first)
498 {
499 link_clear_range(first);
500 }
501
502 //***************************************************************************
503 template <typename TLink>
504 typename etl::enable_if<etl::is_forward_link<TLink>::value, void>::type
505 detach_linked_list(TLink* first)
506 {
507 if (first != ETL_NULLPTR)
508 {
509 detach_linked_list(*first);
510 }
511 }
512
513 //***************************************************************************
515 //***************************************************************************
516 template <size_t ID_>
517 struct bidirectional_link
518 {
519 enum
520 {
521 ID = ID_,
522 };
523
524 //***********************************
525 bidirectional_link()
526 : etl_previous(ETL_NULLPTR)
527 , etl_next(ETL_NULLPTR)
528 {
529 }
530
531 //***********************************
532 bidirectional_link(bidirectional_link* p_previous, bidirectional_link* p_next)
533 : etl_previous(p_previous)
534 , etl_next(p_next)
535 {
536 }
537
538 //***********************************
539 bidirectional_link(const bidirectional_link& other)
540 : etl_previous(other.etl_previous)
541 , etl_next(other.etl_next)
542 {
543 }
544
545 //***********************************
546 bidirectional_link& operator =(const bidirectional_link& other)
547 {
548 etl_previous = other.etl_previous;
549 etl_next = other.etl_next;
550
551 return *this;
552 }
553
554 //***********************************
555 void clear()
556 {
557 etl_previous = ETL_NULLPTR;
558 etl_next = ETL_NULLPTR;
559 }
560
561 //***********************************
562 ETL_NODISCARD
563 bool is_linked() const
564 {
565 return (etl_previous != ETL_NULLPTR) || (etl_next != ETL_NULLPTR);
566 }
567
568 //***********************************
569 ETL_NODISCARD
570 bool has_next() const
571 {
572 return etl_next != ETL_NULLPTR;
573 }
574
575 //***********************************
576 ETL_NODISCARD
577 bool has_previous() const
578 {
579 return etl_previous != ETL_NULLPTR;
580 }
581
582 //***********************************
583 void set_next(bidirectional_link* n)
584 {
585 etl_next = n;
586 }
587
588 //***********************************
589 void set_next(bidirectional_link& n)
590 {
591 etl_next = &n;
592 }
593
594 //***********************************
595 ETL_NODISCARD
596 bidirectional_link* get_next() const
597 {
598 return etl_next;
599 }
600
601 //***********************************
602 void set_previous(bidirectional_link* n)
603 {
604 etl_previous = n;
605 }
606
607 //***********************************
608 void set_previous(bidirectional_link& n)
609 {
610 etl_previous = &n;
611 }
612
613 //***********************************
614 ETL_NODISCARD
615 bidirectional_link* get_previous() const
616 {
617 return etl_previous;
618 }
619
620 //***********************************
621 void reverse()
622 {
623 using ETL_OR_STD::swap; // Allow ADL
624 swap(etl_previous, etl_next);
625 }
626
627 //***********************************
628 void unlink()
629 {
630 // Connect the previous link with the next.
631 if (etl_previous != ETL_NULLPTR)
632 {
633 etl_previous->etl_next = etl_next;
634 }
635
636 // Connect the next link with the previous.
637 if (etl_next != ETL_NULLPTR)
638 {
639 etl_next->etl_previous = etl_previous;
640 }
641
642 clear();
643 }
644
645 bidirectional_link* etl_previous;
646 bidirectional_link* etl_next;
647 };
648
649 //***********************************
650 template <typename TLink>
652 {
653 static ETL_CONSTANT bool value = etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value;
654 };
655
656 //***********************************
657#if ETL_USING_CPP17
658 template <typename TLink>
659 inline constexpr bool is_bidirectional_link_v = etl::is_bidirectional_link<TLink>::value;
660#endif
661
662 //***************************************************************************
663 // link
664 //***************************************************************************
665 // Reference, Reference
666 template <typename TLink>
668 link(TLink& lhs, TLink& rhs)
669 {
670 lhs.etl_next = &rhs;
671 rhs.etl_previous = &lhs;
672 }
673
674 //***********************************
675 // Pointer, Pointer
676 template <typename TLink>
678 link(TLink* lhs, TLink* rhs)
679 {
680 if (lhs != ETL_NULLPTR)
681 {
682 lhs->etl_next = rhs;
683 }
684
685 if (rhs != ETL_NULLPTR)
686 {
687 rhs->etl_previous = lhs;
688 }
689 }
690
691 //***********************************
692 // Reference, Pointer
693 template <typename TLink>
694 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
695 link(TLink& lhs, TLink* rhs)
696 {
697 lhs.etl_next = rhs;
698
699 if (rhs != ETL_NULLPTR)
700 {
701 rhs->etl_previous = &lhs;
702 }
703 }
704
705 //***********************************
706 // Pointer, Reference
707 template <typename TLink>
708 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
709 link(TLink* lhs, TLink& rhs)
710 {
711 if (lhs != ETL_NULLPTR)
712 {
713 lhs->etl_next = &rhs;
714 }
715
716 rhs.etl_previous = lhs;
717 }
718
719 //***********************************
720 // Reference, Reference
721 template <typename TLink>
722 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
723 link_splice(TLink& lhs, TLink& rhs)
724 {
725 rhs.etl_next = lhs.etl_next;
726 rhs.etl_previous = &lhs;
727
728 if (lhs.etl_next != ETL_NULLPTR)
729 {
730 lhs.etl_next->etl_previous = &rhs;
731 }
732
733 lhs.etl_next = &rhs;
734 }
735
736 //***************************************************************************
737 // link_splice
738 //***************************************************************************
739 // Pointer, Pointer
740 template <typename TLink>
741 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
742 link_splice(TLink* lhs, TLink* rhs)
743 {
744 if (rhs != ETL_NULLPTR)
745 {
746 if (lhs != ETL_NULLPTR)
747 {
748 rhs->etl_next = lhs->etl_next;
749 }
750
751 rhs->etl_previous = lhs;
752 }
753
754 if (lhs != ETL_NULLPTR)
755 {
756 if (lhs->etl_next != ETL_NULLPTR)
757 {
758 lhs->etl_next->etl_previous = rhs;
759 }
760
761 lhs->etl_next = rhs;
762 }
763 }
764
765 //***********************************
766 // Reference, Pointer
767 template <typename TLink>
768 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
769 link_splice(TLink& lhs, TLink* rhs)
770 {
771 if (rhs != ETL_NULLPTR)
772 {
773 rhs->etl_next = lhs.etl_next;
774 rhs->etl_previous = &lhs;
775 }
776
777 if (lhs.etl_next != ETL_NULLPTR)
778 {
779 lhs.etl_next->etl_previous = rhs;
780 }
781
782 lhs.etl_next = rhs;
783 }
784
785 //***********************************
786 // Pointer, Reference
787 template <typename TLink>
788 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
789 link_splice(TLink* lhs, TLink& rhs)
790 {
791 if (lhs != ETL_NULLPTR)
792 {
793 rhs.etl_next = lhs->etl_next;
794 }
795
796 rhs.etl_previous = lhs;
797
798 if (lhs != ETL_NULLPTR)
799 {
800 if (lhs->etl_next != ETL_NULLPTR)
801 {
802 lhs->etl_next->etl_previous = &rhs;
803 }
804
805 lhs->etl_next = &rhs;
806 }
807 }
808
809 //***********************************
810 // Reference, Reference, Reference
811 template <typename TLink>
812 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
813 link_splice(TLink& lhs, TLink& first, TLink& last)
814 {
815 last.etl_next = lhs.etl_next;
816 first.etl_previous = &lhs;
817
818 if (last.etl_next != ETL_NULLPTR)
819 {
820 last.etl_next->etl_previous = &last;
821 }
822
823 lhs.etl_next = &first;
824 }
825
826 //***********************************
827 // Pointer, Reference, Reference
828 template <typename TLink>
829 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
830 link_splice(TLink* lhs, TLink& first, TLink& last)
831 {
832 if (lhs != ETL_NULLPTR)
833 {
834 last.etl_next = lhs->etl_next;
835 }
836 else
837 {
838 last.etl_next = ETL_NULLPTR;
839 }
840
841 first.etl_previous = lhs;
842
843 if (last.etl_next != ETL_NULLPTR)
844 {
845 last.etl_next->etl_previous = &last;
846 }
847
848 if (lhs != ETL_NULLPTR)
849 {
850 lhs->etl_next = &first;
851 }
852 }
853
854 //***************************************************************************
855 // unlink
856 //***************************************************************************
857 // Reference
858 template <typename TLink>
859 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
860 unlink(TLink& node)
861 {
862 node.unlink();
863 }
864
865 //***********************************
866 // Reference Reference
867 template <typename TLink>
868 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, TLink&>::type
869 unlink(TLink& first, TLink& last)
870 {
871 if (&first == &last)
872 {
873 first.unlink();
874 }
875 else
876 {
877 if (last.etl_next != ETL_NULLPTR)
878 {
879 last.etl_next->etl_previous = first.etl_previous;
880 }
881
882 if (first.etl_previous != ETL_NULLPTR)
883 {
884 first.etl_previous->etl_next = last.etl_next;
885 }
886
887 first.etl_previous = ETL_NULLPTR;
888 last.etl_next = ETL_NULLPTR;
889 }
890
891 return first;
892 }
893
894 // Reference
895 template <typename TLink>
896 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, bool>::type
897 is_linked(TLink& node)
898 {
899 return node.is_linked();
900 }
901
902 // Pointer
903 template <typename TLink>
904 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, bool>::type
905 is_linked(TLink* node)
906 {
907 return node->is_linked();
908 }
909
910 //***************************************************************************
911 // link_clear_range
912 //***************************************************************************
913 // Reference
914 template <typename TLink>
915 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
916 link_clear_range(TLink& start)
917 {
918 TLink* current = &start;
919
920 while (current != ETL_NULLPTR)
921 {
922 TLink* next = current->etl_next;
923 current->clear();
924 current = next;
925 }
926 }
927
928 //***********************************
929 // Pointer
930 template <typename TLink>
931 typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
932 link_clear_range(TLink* start)
933 {
934 etl::link_clear_range(*start);
935 }
936
937#if ETL_USING_CPP17
938 //***************************************************************************
940 //***************************************************************************
941 template <typename TLink, typename... TLinks>
942 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
943 create_linked_list(TLink& first, TLinks&... links)
944 {
945 TLink* current = &first;
946 ((current->etl_next = &links, static_cast<TLink&>(links).etl_previous = current, current = &links), ...);
947
948 return current;
949 }
950
951 //***************************************************************************
953 //***************************************************************************
954 template <typename TLink, typename... TLinks>
955 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
956 create_linked_list(TLink* first, TLinks*... links)
957 {
958 TLink* current = first;
959 ((current->etl_next = links, static_cast<TLink*>(links)->etl_previous = current, current = links), ...);
960
961 return current;
962 }
963#elif ETL_USING_CPP11
964 //***************************************************************************
966 //***************************************************************************
967 template <typename TLink>
968 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
969 create_linked_list(TLink& first)
970 {
971 return &first;
972 }
973
974 //***************************************************************************
976 //***************************************************************************
977 template <typename TLink, typename... TLinks>
978 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
979 create_linked_list(TLink& first, TLink& next, TLinks&... links)
980 {
981 first.etl_next = &next;
982 next.etl_previous = &first;
983
984 return create_linked_list(next, static_cast<TLink&>(links)...);
985 }
986
987 //***************************************************************************
989 //***************************************************************************
990 template <typename TLink, typename... TLinks>
991 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type
992 create_linked_list(TLink* first, TLink* next, TLinks*... links)
993 {
994 if (first != ETL_NULLPTR)
995 {
996 return create_linked_list(*first, *next, static_cast<TLink&>(*links)...);
997 }
998 else
999 {
1000 return ETL_NULLPTR;
1001 }
1002 }
1003#endif
1004
1005 //***************************************************************************
1006 template <typename TLink>
1007 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, void>::type
1008 detach_linked_list(TLink& first)
1009 {
1010 link_clear_range(first);
1011 }
1012
1013 //***************************************************************************
1014 template <typename TLink>
1015 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, void>::type
1016 detach_linked_list(TLink* first)
1017 {
1018 if (first != ETL_NULLPTR)
1019 {
1020 detach_linked_list(*first);
1021 }
1022 }
1023
1024 //***************************************************************************
1026 //***************************************************************************
1027 template <size_t ID_>
1028 struct tree_link
1029 {
1030 enum
1031 {
1032 ID = ID_,
1033 };
1034
1035 //***********************************
1036 tree_link()
1037 : etl_parent(ETL_NULLPTR)
1038 , etl_left(ETL_NULLPTR)
1039 , etl_right(ETL_NULLPTR)
1040 {
1041 }
1042
1043 //***********************************
1044 tree_link(tree_link* p_parent, tree_link* p_left, tree_link* p_right)
1045 : etl_parent(p_parent)
1046 , etl_left(p_left)
1047 , etl_right(p_right)
1048 {
1049 }
1050
1051 //***********************************
1052 tree_link(const tree_link& other)
1053 : etl_parent(other.etl_parent)
1054 , etl_left(other.etl_left)
1055 , etl_right(other.etl_right)
1056 {
1057 }
1058
1059 //***********************************
1060 tree_link& operator =(const tree_link& other)
1061 {
1062 etl_parent = other.etl_parent;
1063 etl_left = other.etl_left;
1064 etl_right = other.etl_right;
1065
1066 return *this;
1067 }
1068
1069 //***********************************
1070 void clear()
1071 {
1072 etl_parent = ETL_NULLPTR;
1073 etl_left = ETL_NULLPTR;
1074 etl_right = ETL_NULLPTR;
1075 }
1076
1077 //***********************************
1078 bool is_linked() const
1079 {
1080 return (etl_parent != ETL_NULLPTR) || (etl_left != ETL_NULLPTR) || (etl_right != ETL_NULLPTR);
1081 }
1082
1083 //***********************************
1084 ETL_NODISCARD
1085 bool has_parent() const
1086 {
1087 return etl_parent != ETL_NULLPTR;
1088 }
1089
1090 //***********************************
1091 ETL_NODISCARD
1092 bool has_left() const
1093 {
1094 return etl_left != ETL_NULLPTR;
1095 }
1096
1097 //***********************************
1098 ETL_NODISCARD
1099 bool has_right() const
1100 {
1101 return etl_right != ETL_NULLPTR;
1102 }
1103
1104 //***********************************
1105 void set_parent(tree_link* p)
1106 {
1107 etl_parent = p;
1108 }
1109
1110 //***********************************
1111 void set_left(tree_link* l)
1112 {
1113 etl_left = l;
1114 }
1115
1116 //***********************************
1117 void set_right(tree_link* r)
1118 {
1119 etl_right = r;
1120 }
1121
1122 //***********************************
1123 void set_parent(tree_link& p)
1124 {
1125 etl_parent = &p;
1126 }
1127
1128 //***********************************
1129 void set_left(tree_link& l)
1130 {
1131 etl_left = &l;
1132 }
1133
1134 //***********************************
1135 void set_right(tree_link& r)
1136 {
1137 etl_right = &r;
1138 }
1139
1140 //***********************************
1141 ETL_NODISCARD
1142 tree_link* get_parent() const
1143 {
1144 return etl_parent;
1145 }
1146
1147 //***********************************
1148 ETL_NODISCARD
1149 tree_link* get_left() const
1150 {
1151 return etl_left;
1152 }
1153
1154 //***********************************
1155 ETL_NODISCARD
1156 tree_link* get_right() const
1157 {
1158 return etl_right;
1159 }
1160
1161 //***********************************
1162 void mirror()
1163 {
1164 using ETL_OR_STD::swap;
1165 swap(etl_left, etl_right);
1166 }
1167
1168 tree_link* etl_parent;
1169 tree_link* etl_left;
1170 tree_link* etl_right;
1171 };
1172
1173 //***********************************
1174 template <typename TLink>
1176 {
1177 static ETL_CONSTANT bool value = etl::is_same<TLink, etl::tree_link<TLink::ID> >::value;
1178 };
1179
1180 //***********************************
1181#if ETL_USING_CPP17
1182 template <typename TLink>
1183 inline constexpr bool is_tree_link_v = etl::is_tree_link<TLink>::value;
1184#endif
1185
1186 //***************************************************************************
1187 // link_left
1188 // Sets the left link.
1189 //***************************************************************************
1190 // Reference, Reference
1191 template <typename TLink>
1193 link_left(TLink& parent, TLink& leaf)
1194 {
1195 parent.etl_left = &leaf;
1196 leaf.etl_parent = &parent;
1197 }
1198
1199 //***********************************
1200 // Pointer, Pointer
1201 template <typename TLink>
1203 link_left(TLink* parent, TLink* leaf)
1204 {
1205 if (parent != ETL_NULLPTR)
1206 {
1207 parent->etl_left = leaf;
1208 }
1209
1210 if (leaf != ETL_NULLPTR)
1211 {
1212 leaf->etl_parent = parent;
1213 }
1214 }
1215
1216 //***********************************
1217 // Reference, Pointer
1218 template <typename TLink>
1219 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1220 link_left(TLink& parent, TLink* leaf)
1221 {
1222 parent.etl_left = leaf;
1223
1224 if (leaf != ETL_NULLPTR)
1225 {
1226 leaf->etl_parent = &parent;
1227 }
1228 }
1229
1230 //***********************************
1231 // Pointer, Reference
1232 template <typename TLink>
1233 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1234 link_left(TLink* parent, TLink& leaf)
1235 {
1236 if (parent != ETL_NULLPTR)
1237 {
1238 parent->etl_left = &leaf;
1239 }
1240
1241 leaf.etl_parent = parent;
1242 }
1243
1244 //***************************************************************************
1245 // link_right
1246 // Sets the right link.
1247 //***************************************************************************
1248 template <typename TLink>
1249 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1250 link_right(TLink& parent, TLink& leaf)
1251 {
1252 parent.etl_right = &leaf;
1253 leaf.etl_parent = &parent;
1254 }
1255
1256 //***********************************
1257 template <typename TLink>
1258 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1259 link_right(TLink* parent, TLink* leaf)
1260 {
1261 if (parent != ETL_NULLPTR)
1262 {
1263 parent->etl_right = leaf;
1264 }
1265
1266 if (leaf != ETL_NULLPTR)
1267 {
1268 leaf->etl_parent = parent;
1269 }
1270 }
1271
1272 //***********************************
1273 template <typename TLink>
1274 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1275 link_right(TLink& parent, TLink* leaf)
1276 {
1277 parent.etl_right = leaf;
1278
1279 if (leaf != ETL_NULLPTR)
1280 {
1281 leaf->etl_parent = &parent;
1282 }
1283 }
1284
1285 //***********************************
1286 template <typename TLink>
1287 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1288 link_right(TLink* parent, TLink& leaf)
1289 {
1290 if (parent != ETL_NULLPTR)
1291 {
1292 parent->etl_right = &leaf;
1293 }
1294
1295 leaf.etl_parent = parent;
1296 }
1297
1298 //***************************************************************************
1299 // link_rotate_left
1300 //***************************************************************************
1301 // Reference, Reference
1302 template <typename TLink>
1303 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1304 link_rotate_left(TLink& parent, TLink& leaf)
1305 {
1306 parent.etl_right = leaf.etl_left;
1307
1308 if (parent.etl_right != ETL_NULLPTR)
1309 {
1310 parent.etl_right->etl_parent = &parent;
1311 }
1312
1313 leaf.etl_parent = parent.etl_parent;
1314 parent.etl_parent = &leaf;
1315 leaf.etl_left = &parent;
1316 }
1317
1318 //***********************************
1319 // Pointer, Pointer
1320 template <typename TLink>
1321 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1322 link_rotate_left(TLink* parent, TLink* leaf)
1323 {
1324 if ((parent != ETL_NULLPTR) && (leaf != ETL_NULLPTR))
1325 {
1326 link_rotate_left(*parent, *leaf);
1327 }
1328 }
1329
1330 //***********************************
1331 // Reference, Pointer
1332 template <typename TLink>
1333 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1334 link_rotate_left(TLink& parent, TLink* leaf)
1335 {
1336 if (leaf != ETL_NULLPTR)
1337 {
1338 link_rotate_left(parent, *leaf);
1339 }
1340 }
1341
1342 //***********************************
1343 // Pointer, Reference
1344 template <typename TLink>
1345 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1346 link_rotate_left(TLink* parent, TLink& leaf)
1347 {
1348 if (parent != ETL_NULLPTR)
1349 {
1350 link_rotate_left(*parent, leaf);
1351 }
1352 }
1353
1354 //***************************************************************************
1355 // link_rotate_right
1356 //***************************************************************************
1357 template <typename TLink>
1358 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1359 link_rotate_right(TLink& parent, TLink& leaf)
1360 {
1361 parent.etl_left = leaf.etl_right;
1362
1363 if (parent.etl_left != ETL_NULLPTR)
1364 {
1365 parent.etl_left->etl_parent = &parent;
1366 }
1367
1368 leaf.etl_parent = parent.etl_parent;
1369 parent.etl_parent = &leaf;
1370 leaf.etl_right = &parent;
1371 }
1372
1373
1374 template <typename TLink>
1375 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1376 link_rotate_right(TLink* parent, TLink* leaf)
1377 {
1378 if ((parent != ETL_NULLPTR) && (leaf != ETL_NULLPTR))
1379 {
1380 link_rotate_right(*parent, *leaf);
1381 }
1382 }
1383
1384 template <typename TLink>
1385 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1386 link_rotate_right(TLink& parent, TLink* leaf)
1387 {
1388 if (leaf != ETL_NULLPTR)
1389 {
1390 link_rotate_right(parent, *leaf);
1391 }
1392 }
1393
1394 //***********************************
1395 template <typename TLink>
1396 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1397 link_rotate_right(TLink* parent, TLink& leaf)
1398 {
1399 if (parent != ETL_NULLPTR)
1400 {
1401 link_rotate_right(*parent, leaf);
1402 }
1403 }
1404
1405 //***************************************************************************
1406 // link_rotate
1407 //***************************************************************************
1408 // Reference, Reference
1410 template <typename TLink>
1411 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1412 link_rotate(TLink& parent, TLink& leaf)
1413 {
1414 if (parent.etl_left == &leaf)
1415 {
1416 etl::link_rotate_right(parent, leaf);
1417 }
1418 else
1419 {
1420 etl::link_rotate_left(parent, leaf);
1421 }
1422 }
1423
1424 //***********************************
1425 // Pointer, Pointer
1427 template <typename TLink>
1429 link_rotate(TLink* parent, TLink* leaf)
1430 {
1431 if ((parent != ETL_NULLPTR) && (leaf != ETL_NULLPTR))
1432 {
1433 if (parent->etl_left == leaf)
1434 {
1435 etl::link_rotate_right(*parent, *leaf);
1436 }
1437 else
1438 {
1439 etl::link_rotate_left(*parent, *leaf);
1440 }
1441 }
1442 }
1443
1444 //***********************************
1445 // Reference, Pointer
1447 template <typename TLink>
1449 link_rotate(TLink& parent, TLink* leaf)
1450 {
1451 if (leaf != ETL_NULLPTR)
1452 {
1453 if (parent.etl_left == leaf)
1454 {
1455 etl::link_rotate_right(parent, *leaf);
1456 }
1457 else
1458 {
1459 etl::link_rotate_left(parent, *leaf);
1460 }
1461 }
1462 }
1463
1464 //***********************************
1465 // Pointer, Reference
1467 template <typename TLink>
1469 link_rotate(TLink* parent, TLink& leaf)
1470 {
1471 if (parent != ETL_NULLPTR)
1472 {
1473 if (parent->etl_left == &leaf)
1474 {
1475 etl::link_rotate_right(*parent, leaf);
1476 }
1477 else
1478 {
1479 etl::link_rotate_left(*parent, leaf);
1480 }
1481 }
1482 }
1483
1484 // Reference
1485 template <typename TLink>
1487 link_clear(TLink& node)
1488 {
1489 node.clear();
1490 }
1491
1492 // Pointer
1493 template <typename TLink>
1494 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
1495 link_clear(TLink* node)
1496 {
1497 node->clear();
1498 }
1499
1500 // Reference
1501 template <typename TLink>
1502 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, bool>::type
1503 is_linked(TLink& node)
1504 {
1505 return node.is_linked();
1506 }
1507
1508 // Pointer
1509 template <typename TLink>
1510 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, bool>::type
1511 is_linked(TLink* node)
1512 {
1513 return node->is_linked();
1514 }
1515}
1516
1517#endif
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition exception.h:69
Definition exception.h:47
enable_if
Definition type_traits_generator.h:1254
is_same
Definition type_traits_generator.h:1104
bitset_ext
Definition absolute.h:39
ETL_CONSTEXPR14 void swap(etl::typed_storage_ext< T > &lhs, etl::typed_storage_ext< T > &rhs) ETL_NOEXCEPT
Swap two etl::typed_storage_ext.
Definition alignment.h:838
etl::enable_if< etl::is_same< TLink, etl::tree_link< TLink::ID > >::value, void >::type link_rotate(TLink &parent, TLink &leaf)
Automatically detects whether a left or right rotate is expected.
Definition intrusive_links.h:1412