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