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 <stddef.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 ETL_CONSTEXPR forward_link()
95 : etl_next(ETL_NULLPTR)
96 {
97 }
98
99 //***********************************
100 ETL_CONSTEXPR forward_link(forward_link* p_next)
101 : etl_next(p_next)
102 {
103 }
104
105 //***********************************
106 ETL_CONSTEXPR forward_link(const forward_link& other)
107 : etl_next(other.etl_next)
108 {
109 }
110
111 //***********************************
112 ETL_CONSTEXPR14 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 ETL_CONSTEXPR bidirectional_link()
499 : etl_previous(ETL_NULLPTR)
500 , etl_next(ETL_NULLPTR)
501 {
502 }
503
504 //***********************************
505 ETL_CONSTEXPR 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 ETL_CONSTEXPR bidirectional_link(const bidirectional_link& other)
513 : etl_previous(other.etl_previous)
514 , etl_next(other.etl_next)
515 {
516 }
517
518 //***********************************
519 ETL_CONSTEXPR14 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 if (start != ETL_NULLPTR)
894 {
895 etl::link_clear_range(*start);
896 }
897 }
898
899#if ETL_USING_CPP17
900 //***************************************************************************
902 //***************************************************************************
903 template <typename TLink, typename... TLinks>
904 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type create_linked_list(TLink& first, TLinks&... links)
905 {
906 TLink* current = &first;
907 ((current->etl_next = &links, static_cast<TLink&>(links).etl_previous = current, current = &links), ...);
908
909 return current;
910 }
911
912 //***************************************************************************
914 //***************************************************************************
915 template <typename TLink, typename... TLinks>
916 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type create_linked_list(TLink* first, TLinks*... links)
917 {
918 TLink* current = first;
919 ((current->etl_next = links, static_cast<TLink*>(links)->etl_previous = current, current = links), ...);
920
921 return current;
922 }
923#elif ETL_USING_CPP11
924 //***************************************************************************
926 //***************************************************************************
927 template <typename TLink>
928 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type create_linked_list(TLink& first)
929 {
930 return &first;
931 }
932
933 //***************************************************************************
935 //***************************************************************************
936 template <typename TLink, typename... TLinks>
937 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type create_linked_list(TLink& first, TLink& next, TLinks&... links)
938 {
939 first.etl_next = &next;
940 next.etl_previous = &first;
941
942 return create_linked_list(next, static_cast<TLink&>(links)...);
943 }
944
945 //***************************************************************************
947 //***************************************************************************
948 template <typename TLink, typename... TLinks>
949 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, TLink*>::type create_linked_list(TLink* first, TLink* next, TLinks*... links)
950 {
951 if (first != ETL_NULLPTR)
952 {
953 return create_linked_list(*first, *next, static_cast<TLink&>(*links)...);
954 }
955 else
956 {
957 return ETL_NULLPTR;
958 }
959 }
960#endif
961
962 //***************************************************************************
963 template <typename TLink>
964 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, void>::type detach_linked_list(TLink& first)
965 {
966 link_clear_range(first);
967 }
968
969 //***************************************************************************
970 template <typename TLink>
971 typename etl::enable_if<etl::is_bidirectional_link<TLink>::value, void>::type detach_linked_list(TLink* first)
972 {
973 if (first != ETL_NULLPTR)
974 {
975 detach_linked_list(*first);
976 }
977 }
978
979 //***************************************************************************
981 //***************************************************************************
982 template <size_t ID_>
983 struct tree_link
984 {
985 enum
986 {
987 ID = ID_,
988 };
989
990 //***********************************
991 tree_link()
992 : etl_parent(ETL_NULLPTR)
993 , etl_left(ETL_NULLPTR)
994 , etl_right(ETL_NULLPTR)
995 {
996 }
997
998 //***********************************
999 tree_link(tree_link* p_parent, tree_link* p_left, tree_link* p_right)
1000 : etl_parent(p_parent)
1001 , etl_left(p_left)
1002 , etl_right(p_right)
1003 {
1004 }
1005
1006 //***********************************
1007 tree_link(const tree_link& other)
1008 : etl_parent(other.etl_parent)
1009 , etl_left(other.etl_left)
1010 , etl_right(other.etl_right)
1011 {
1012 }
1013
1014 //***********************************
1015 tree_link& operator=(const tree_link& other)
1016 {
1017 etl_parent = other.etl_parent;
1018 etl_left = other.etl_left;
1019 etl_right = other.etl_right;
1020
1021 return *this;
1022 }
1023
1024 //***********************************
1025 void clear()
1026 {
1027 etl_parent = ETL_NULLPTR;
1028 etl_left = ETL_NULLPTR;
1029 etl_right = ETL_NULLPTR;
1030 }
1031
1032 //***********************************
1033 bool is_linked() const
1034 {
1035 return (etl_parent != ETL_NULLPTR) || (etl_left != ETL_NULLPTR) || (etl_right != ETL_NULLPTR);
1036 }
1037
1038 //***********************************
1039 ETL_NODISCARD
1040 bool has_parent() const
1041 {
1042 return etl_parent != ETL_NULLPTR;
1043 }
1044
1045 //***********************************
1046 ETL_NODISCARD
1047 bool has_left() const
1048 {
1049 return etl_left != ETL_NULLPTR;
1050 }
1051
1052 //***********************************
1053 ETL_NODISCARD
1054 bool has_right() const
1055 {
1056 return etl_right != ETL_NULLPTR;
1057 }
1058
1059 //***********************************
1060 void set_parent(tree_link* p)
1061 {
1062 etl_parent = p;
1063 }
1064
1065 //***********************************
1066 void set_left(tree_link* l)
1067 {
1068 etl_left = l;
1069 }
1070
1071 //***********************************
1072 void set_right(tree_link* r)
1073 {
1074 etl_right = r;
1075 }
1076
1077 //***********************************
1078 void set_parent(tree_link& p)
1079 {
1080 etl_parent = &p;
1081 }
1082
1083 //***********************************
1084 void set_left(tree_link& l)
1085 {
1086 etl_left = &l;
1087 }
1088
1089 //***********************************
1090 void set_right(tree_link& r)
1091 {
1092 etl_right = &r;
1093 }
1094
1095 //***********************************
1096 ETL_NODISCARD
1097 tree_link* get_parent() const
1098 {
1099 return etl_parent;
1100 }
1101
1102 //***********************************
1103 ETL_NODISCARD
1104 tree_link* get_left() const
1105 {
1106 return etl_left;
1107 }
1108
1109 //***********************************
1110 ETL_NODISCARD
1111 tree_link* get_right() const
1112 {
1113 return etl_right;
1114 }
1115
1116 //***********************************
1117 void mirror()
1118 {
1119 using ETL_OR_STD::swap;
1120 swap(etl_left, etl_right);
1121 }
1122
1123 tree_link* etl_parent;
1124 tree_link* etl_left;
1125 tree_link* etl_right;
1126 };
1127
1128 //***********************************
1129 template <typename TLink>
1131 {
1132 static ETL_CONSTANT bool value = etl::is_same<TLink, etl::tree_link<TLink::ID> >::value;
1133 };
1134
1135 //***********************************
1136#if ETL_USING_CPP17
1137 template <typename TLink>
1138 inline constexpr bool is_tree_link_v = etl::is_tree_link<TLink>::value;
1139#endif
1140
1141 //***************************************************************************
1142 // link_left
1143 // Sets the left link.
1144 //***************************************************************************
1145 // Reference, Reference
1146 template <typename TLink>
1147 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_left(TLink& parent, TLink& child)
1148 {
1149 parent.etl_left = &child;
1150 child.etl_parent = &parent;
1151 }
1152
1153 //***********************************
1154 // Pointer, Pointer
1155 template <typename TLink>
1156 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_left(TLink* parent, TLink* child)
1157 {
1158 if (parent != ETL_NULLPTR)
1159 {
1160 parent->etl_left = child;
1161 }
1162
1163 if (child != ETL_NULLPTR)
1164 {
1165 child->etl_parent = parent;
1166 }
1167 }
1168
1169 //***********************************
1170 // Reference, Pointer
1171 template <typename TLink>
1172 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_left(TLink& parent, TLink* child)
1173 {
1174 parent.etl_left = child;
1175
1176 if (child != ETL_NULLPTR)
1177 {
1178 child->etl_parent = &parent;
1179 }
1180 }
1181
1182 //***********************************
1183 // Pointer, Reference
1184 template <typename TLink>
1185 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_left(TLink* parent, TLink& child)
1186 {
1187 if (parent != ETL_NULLPTR)
1188 {
1189 parent->etl_left = &child;
1190 }
1191
1192 child.etl_parent = parent;
1193 }
1194
1195 //***************************************************************************
1196 // link_right
1197 // Sets the right link.
1198 //***************************************************************************
1199 template <typename TLink>
1200 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_right(TLink& parent, TLink& child)
1201 {
1202 parent.etl_right = &child;
1203 child.etl_parent = &parent;
1204 }
1205
1206 //***********************************
1207 template <typename TLink>
1208 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_right(TLink* parent, TLink* child)
1209 {
1210 if (parent != ETL_NULLPTR)
1211 {
1212 parent->etl_right = child;
1213 }
1214
1215 if (child != ETL_NULLPTR)
1216 {
1217 child->etl_parent = parent;
1218 }
1219 }
1220
1221 //***********************************
1222 template <typename TLink>
1223 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_right(TLink& parent, TLink* child)
1224 {
1225 parent.etl_right = child;
1226
1227 if (child != ETL_NULLPTR)
1228 {
1229 child->etl_parent = &parent;
1230 }
1231 }
1232
1233 //***********************************
1234 template <typename TLink>
1235 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_right(TLink* parent, TLink& child)
1236 {
1237 if (parent != ETL_NULLPTR)
1238 {
1239 parent->etl_right = &child;
1240 }
1241
1242 child.etl_parent = parent;
1243 }
1244
1245 //***************************************************************************
1246 // link_rotate_left
1247 //***************************************************************************
1248 // Reference, Reference
1249 template <typename TLink>
1250 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate_left(TLink& parent, TLink& child)
1251 {
1252 TLink* grandparent = parent.etl_parent;
1253
1254 parent.etl_right = child.etl_left;
1255
1256 if (parent.etl_right != ETL_NULLPTR)
1257 {
1258 parent.etl_right->etl_parent = &parent;
1259 }
1260
1261 child.etl_parent = grandparent;
1262 parent.etl_parent = &child;
1263 child.etl_left = &parent;
1264
1265 if (grandparent != ETL_NULLPTR)
1266 {
1267 if (grandparent->etl_left == &parent)
1268 {
1269 grandparent->etl_left = &child;
1270 }
1271 else if (grandparent->etl_right == &parent)
1272 {
1273 grandparent->etl_right = &child;
1274 }
1275 }
1276 }
1277
1278 //***********************************
1279 // Pointer, Pointer
1280 template <typename TLink>
1281 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate_left(TLink* parent, TLink* child)
1282 {
1283 if ((parent != ETL_NULLPTR) && (child != ETL_NULLPTR))
1284 {
1285 link_rotate_left(*parent, *child);
1286 }
1287 }
1288
1289 //***********************************
1290 // Reference, Pointer
1291 template <typename TLink>
1292 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate_left(TLink& parent, TLink* child)
1293 {
1294 if (child != ETL_NULLPTR)
1295 {
1296 link_rotate_left(parent, *child);
1297 }
1298 }
1299
1300 //***********************************
1301 // Pointer, Reference
1302 template <typename TLink>
1303 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate_left(TLink* parent, TLink& child)
1304 {
1305 if (parent != ETL_NULLPTR)
1306 {
1307 link_rotate_left(*parent, child);
1308 }
1309 }
1310
1311 //***************************************************************************
1312 // link_rotate_right
1313 //***************************************************************************
1314 template <typename TLink>
1315 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate_right(TLink& parent, TLink& child)
1316 {
1317 TLink* grandparent = parent.etl_parent;
1318
1319 parent.etl_left = child.etl_right;
1320
1321 if (parent.etl_left != ETL_NULLPTR)
1322 {
1323 parent.etl_left->etl_parent = &parent;
1324 }
1325
1326 child.etl_parent = grandparent;
1327 parent.etl_parent = &child;
1328 child.etl_right = &parent;
1329
1330 if (grandparent != ETL_NULLPTR)
1331 {
1332 if (grandparent->etl_left == &parent)
1333 {
1334 grandparent->etl_left = &child;
1335 }
1336 else if (grandparent->etl_right == &parent)
1337 {
1338 grandparent->etl_right = &child;
1339 }
1340 }
1341 }
1342
1343 template <typename TLink>
1344 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate_right(TLink* parent, TLink* child)
1345 {
1346 if ((parent != ETL_NULLPTR) && (child != ETL_NULLPTR))
1347 {
1348 link_rotate_right(*parent, *child);
1349 }
1350 }
1351
1352 template <typename TLink>
1353 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate_right(TLink& parent, TLink* child)
1354 {
1355 if (child != ETL_NULLPTR)
1356 {
1357 link_rotate_right(parent, *child);
1358 }
1359 }
1360
1361 //***********************************
1362 template <typename TLink>
1363 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate_right(TLink* parent, TLink& child)
1364 {
1365 if (parent != ETL_NULLPTR)
1366 {
1367 link_rotate_right(*parent, child);
1368 }
1369 }
1370
1371 //***************************************************************************
1372 // link_rotate
1373 //***************************************************************************
1374 // Reference, Reference
1376 template <typename TLink>
1377 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate(TLink& parent, TLink& child)
1378 {
1379 if (parent.etl_left == &child)
1380 {
1381 etl::link_rotate_right(parent, child);
1382 }
1383 else
1384 {
1385 etl::link_rotate_left(parent, child);
1386 }
1387 }
1388
1389 //***********************************
1390 // Pointer, Pointer
1392 template <typename TLink>
1393 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate(TLink* parent, TLink* child)
1394 {
1395 if ((parent != ETL_NULLPTR) && (child != ETL_NULLPTR))
1396 {
1397 if (parent->etl_left == child)
1398 {
1399 etl::link_rotate_right(*parent, *child);
1400 }
1401 else
1402 {
1403 etl::link_rotate_left(*parent, *child);
1404 }
1405 }
1406 }
1407
1408 //***********************************
1409 // Reference, Pointer
1411 template <typename TLink>
1412 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate(TLink& parent, TLink* child)
1413 {
1414 if (child != ETL_NULLPTR)
1415 {
1416 if (parent.etl_left == child)
1417 {
1418 etl::link_rotate_right(parent, *child);
1419 }
1420 else
1421 {
1422 etl::link_rotate_left(parent, *child);
1423 }
1424 }
1425 }
1426
1427 //***********************************
1428 // Pointer, Reference
1430 template <typename TLink>
1431 typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_rotate(TLink* parent, TLink& child)
1432 {
1433 if (parent != ETL_NULLPTR)
1434 {
1435 if (parent->etl_left == &child)
1436 {
1437 etl::link_rotate_right(*parent, child);
1438 }
1439 else
1440 {
1441 etl::link_rotate_left(*parent, child);
1442 }
1443 }
1444 }
1445
1446 // Reference
1447 template <typename TLink>
1448 typename etl::enable_if< etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_clear(TLink& node)
1449 {
1450 node.clear();
1451 }
1452
1453 // Pointer
1454 template <typename TLink>
1455 typename etl::enable_if< etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type link_clear(TLink* node)
1456 {
1457 node->clear();
1458 }
1459
1460 // Reference
1461 template <typename TLink>
1462 typename etl::enable_if< etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, bool>::type is_linked(TLink& node)
1463 {
1464 return node.is_linked();
1465 }
1466
1467 // Pointer
1468 template <typename TLink>
1469 typename etl::enable_if< etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, bool>::type is_linked(TLink* node)
1470 {
1471 return node->is_linked();
1472 }
1473} // namespace etl
1474
1475#endif
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
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:1377