Embedded Template Library 1.0
Loading...
Searching...
No Matches
set.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) 2014 John Wellbelove, rlindeman
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_SET_INCLUDED
32#define ETL_SET_INCLUDED
33
34#include "platform.h"
35#include "algorithm.h"
36#include "debug_count.h"
37#include "error_handler.h"
38#include "exception.h"
39#include "functional.h"
40#include "initializer_list.h"
41#include "iterator.h"
42#include "nth_type.h"
43#include "nullptr.h"
44#include "parameter_type.h"
45#include "placement_new.h"
46#include "pool.h"
47#include "type_traits.h"
48#include "utility.h"
49
51
52#include <stddef.h>
53
54#include "private/minmax_push.h"
55
56//*****************************************************************************
60//*****************************************************************************
61
62namespace etl
63{
64 //***************************************************************************
67 //***************************************************************************
68 class set_exception : public etl::exception
69 {
70 public:
71
72 set_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
73 : etl::exception(reason_, file_name_, line_number_)
74 {
75 }
76 };
77
78 //***************************************************************************
81 //***************************************************************************
82 class set_full : public etl::set_exception
83 {
84 public:
85
86 set_full(string_type file_name_, numeric_type line_number_)
87 : etl::set_exception(ETL_ERROR_TEXT("set:full", ETL_SET_FILE_ID"A"), file_name_, line_number_)
88 {
89 }
90 };
91
92 //***************************************************************************
95 //***************************************************************************
96 class set_out_of_bounds : public etl::set_exception
97 {
98 public:
99
100 set_out_of_bounds(string_type file_name_, numeric_type line_number_)
101 : etl::set_exception(ETL_ERROR_TEXT("set:bounds", ETL_SET_FILE_ID"B"), file_name_, line_number_)
102 {
103 }
104 };
105
106 //***************************************************************************
109 //***************************************************************************
110 class set_iterator : public etl::set_exception
111 {
112 public:
113
114 set_iterator(string_type file_name_, numeric_type line_number_)
115 : etl::set_exception(ETL_ERROR_TEXT("set:iterator problem", ETL_SET_FILE_ID"C"), file_name_, line_number_)
116 {
117 }
118 };
119
120 //***************************************************************************
123 //***************************************************************************
125 {
126 public:
127
128 typedef size_t size_type;
129
130 //*************************************************************************
132 //*************************************************************************
134 {
135 return current_size;
136 }
137
138 //*************************************************************************
140 //*************************************************************************
142 {
143 return CAPACITY;
144 }
145
146 //*************************************************************************
148 //*************************************************************************
149 bool empty() const
150 {
151 return current_size == 0;
152 }
153
154 //*************************************************************************
156 //*************************************************************************
157 bool full() const
158 {
159 return current_size == CAPACITY;
160 }
161
162 //*************************************************************************
165 //*************************************************************************
167 {
168 return CAPACITY;
169 }
170
171 //*************************************************************************
174 //*************************************************************************
175 size_t available() const
176 {
177 return max_size() - size();
178 }
179
180 protected:
181
182 enum
183 {
184 kLeft = 0,
185 kRight = 1,
186 kNeither = 2
187 };
188
189 //*************************************************************************
191 //*************************************************************************
192 struct Node
193 {
194 //***********************************************************************
196 //***********************************************************************
198 : weight(kNeither)
199 , dir(kNeither)
200 {
201 children[0] = ETL_NULLPTR;
202 children[1] = ETL_NULLPTR;
203 }
204
205 //***********************************************************************
207 //***********************************************************************
209 {
210 weight = kNeither;
211 dir = kNeither;
212 children[0] = ETL_NULLPTR;
213 children[1] = ETL_NULLPTR;
214 }
215
216 Node* children[2];
217 uint_least8_t weight;
218 uint_least8_t dir;
219 };
220
221 //*************************************************************************
223 //*************************************************************************
225 : current_size(0)
226 , CAPACITY(max_size_)
227 , root_node(ETL_NULLPTR)
228
229 {
230 }
231
232 //*************************************************************************
234 //*************************************************************************
236
237 //*************************************************************************
239 //*************************************************************************
240 void attach_node(Node*& position, Node& node)
241 {
242 // Mark new node as leaf on attach to tree at position provided
243 node.mark_as_leaf();
244
245 // Add the node here
246 position = &node;
247
248 // One more.
249 ++current_size;
250 }
251
252 //*************************************************************************
254 //*************************************************************************
255 void detach_node(Node*& position, Node*& replacement)
256 {
257 // Make temporary copy of actual nodes involved because we might lose
258 // their references in the process (e.g. position is the same as
259 // replacement or replacement is a child of position)
260 Node* detached = position;
261 Node* swap = replacement;
262
263 // Update current position to point to swap (replacement) node first
264 position = swap;
265
266 // Update replacement node to point to child in opposite direction
267 // otherwise we might lose the other child of the swap node
268 replacement = swap->children[1 - swap->dir];
269
270 // Point swap node to detached node's children and weight
271 swap->children[kLeft] = detached->children[kLeft];
272 swap->children[kRight] = detached->children[kRight];
273 swap->weight = detached->weight;
274 }
275
276 //*************************************************************************
278 //*************************************************************************
279 void balance_node(Node*& critical_node)
280 {
281 // Step 1: Update weights for all children of the critical node up to the
282 // newly inserted node. This step is costly (in terms of traversing nodes
283 // multiple times during insertion) but doesn't require as much recursion
284 Node* weight_node = critical_node->children[critical_node->dir];
285 while (weight_node)
286 {
287 // Keep going until we reach a terminal node (dir == kNeither)
288 if (uint_least8_t(kNeither) != weight_node->dir)
289 {
290 // Does this insert balance the previous weight factor value?
291 if (weight_node->weight == 1 - weight_node->dir)
292 {
293 weight_node->weight = uint_least8_t(kNeither);
294 }
295 else
296 {
297 weight_node->weight = weight_node->dir;
298 }
299
300 // Update weight factor node to point to next node
301 weight_node = weight_node->children[weight_node->dir];
302 }
303 else
304 {
305 // Stop loop, terminal node found
306 break;
307 }
308 } // while(weight_node)
309
310 // Step 2: Update weight for critical_node or rotate tree to balance node
311 if (uint_least8_t(kNeither) == critical_node->weight)
312 {
313 critical_node->weight = critical_node->dir;
314 }
315 // If direction is different than weight, then it will now be balanced
316 else if (critical_node->dir != critical_node->weight)
317 {
318 critical_node->weight = uint_least8_t(kNeither);
319 }
320 // Rotate is required to balance the tree at the critical node
321 else
322 {
323 // If critical node matches child node direction then perform a two
324 // node rotate in the direction of the critical node
325 if (critical_node->children[critical_node->dir] != ETL_NULLPTR) ETL_UNLIKELY
326 {
327 if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
328 {
329 rotate_2node(critical_node, critical_node->dir);
330 }
331 // Otherwise perform a three node rotation in the direction of the
332 // critical node
333 else
334 {
335 if (critical_node->children[critical_node->dir]->children[1 - critical_node->dir] != ETL_NULLPTR) ETL_UNLIKELY
336 {
337 rotate_3node(critical_node, critical_node->dir, critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
338 }
339 }
340 }
341 }
342 }
343
344 //*************************************************************************
347 //*************************************************************************
348 Node* find_limit_node(Node* position, const int8_t dir) const
349 {
350 // Something at this position and in the direction specified? keep going
351 Node* limit_node = position;
352 while (limit_node && limit_node->children[dir])
353 {
354 limit_node = limit_node->children[dir];
355 }
356
357 // Return the limit node position found
358 return limit_node;
359 }
360
361 //*************************************************************************
364 //*************************************************************************
365 const Node* find_limit_node(const Node* position, const int8_t dir) const
366 {
367 // Something at this position and in the direction specified? keep going
368 const Node* limit_node = position;
369 while (limit_node && limit_node->children[dir])
370 {
371 limit_node = limit_node->children[dir];
372 }
373
374 // Return the limit node position found
375 return limit_node;
376 }
377
378 //*************************************************************************
380 //*************************************************************************
381 void rotate_2node(Node*& position, uint_least8_t dir)
382 {
383 // A C A B
384 // B C -> A E OR B C -> D A
385 // D E B D D E E C
386 // C (new position) becomes the root
387 // A (position) takes ownership of D as its children[kRight] child
388 // C (new position) takes ownership of A as its left child
389 // OR
390 // B (new position) becomes the root
391 // A (position) takes ownership of E as its left child
392 // B (new position) takes ownership of A as its right child
393
394 // Capture new root
395 Node* new_root = position->children[dir];
396 // Replace position's previous child with new root's other child
397 position->children[dir] = new_root->children[1 - dir];
398 // New root now becomes parent of current position
399 new_root->children[1 - dir] = position;
400 // Clear weight factor from current position
401 position->weight = uint_least8_t(kNeither);
402 // Newly detached right now becomes current position
403 position = new_root;
404 // Clear weight factor from new root
405 position->weight = uint_least8_t(kNeither);
406 }
407
408 //*************************************************************************
410 //*************************************************************************
411 void rotate_3node(Node*& position, uint_least8_t dir, uint_least8_t third)
412 {
413 // --A-- --E-- --A-- --D--
414 // _B_ C -> B A OR B _C_ -> A C
415 // D E D F G C D E B F G E
416 // F G F G
417 // E (new position) becomes the root
418 // B (position) takes ownership of F as its left child
419 // A takes ownership of G as its right child
420 // OR
421 // D (new position) becomes the root
422 // A (position) takes ownership of F as its right child
423 // C takes ownership of G as its left child
424
425 // Capture new root (either E or D depending on dir)
426 Node* new_root = position->children[dir]->children[1 - dir];
427 // Set weight factor for B or C based on F or G existing and being a
428 // different than dir
429 position->children[dir]->weight = third != uint_least8_t(kNeither) && third != dir ? dir : uint_least8_t(kNeither);
430
431 // Detach new root from its tree (replace with new roots child)
432 position->children[dir]->children[1 - dir] = new_root->children[dir];
433 // Attach current left tree to new root
434 new_root->children[dir] = position->children[dir];
435 // Set weight factor for A based on F or G
436 position->weight = third != uint_least8_t(kNeither) && third == dir ? 1 - dir : uint_least8_t(kNeither);
437
438 // Move new root's right tree to current roots left tree
439 position->children[dir] = new_root->children[1 - dir];
440 // Attach current root to new roots right tree
441 new_root->children[1 - dir] = position;
442 // Replace current position with new root
443 position = new_root;
444 // Clear weight factor for new current position
445 position->weight = uint_least8_t(kNeither);
446 }
447
451 ETL_DECLARE_DEBUG_COUNT;
452 };
453
454 //***************************************************************************
457 //***************************************************************************
458 template <typename TKey, typename TCompare = etl::less<TKey> >
459 class iset : public etl::set_base
460 {
461 public:
462
463 typedef TKey key_type;
464 typedef TKey value_type;
465 typedef TCompare key_compare;
466 typedef TCompare value_compare;
467 typedef value_type& reference;
468 typedef const value_type& const_reference;
469#if ETL_USING_CPP11
470 typedef value_type&& rvalue_reference;
471#endif
472 typedef value_type* pointer;
473 typedef const value_type* const_pointer;
474 typedef size_t size_type;
475
476 protected:
477
478 //*************************************************************************
480 //*************************************************************************
481 struct Data_Node : public Node
482 {
483 explicit Data_Node(value_type value_)
484 : value(value_)
485 {
486 }
487
488 value_type value;
489 };
490
493
494 //*************************************************************************
496 //*************************************************************************
497 bool node_comp(const Data_Node& node1, const Data_Node& node2) const
498 {
499 return compare(node1.value, node2.value);
500 }
501
502 bool node_comp(const Data_Node& node, key_parameter_t key) const
503 {
504 return compare(node.value, key);
505 }
506
507 bool node_comp(key_parameter_t key, const Data_Node& node) const
508
509 {
510 return compare(key, node.value);
511 }
512
513#if ETL_USING_CPP11
514 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
515 bool node_comp(const Data_Node& node, const K& key) const
516 {
517 return compare(node.value, key);
518 }
519
520 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
521 bool node_comp(const K& key, const Data_Node& node) const
522
523 {
524 return compare(key, node.value);
525 }
526#endif
527
528 private:
529
531 etl::ipool* p_node_pool;
532
533 key_compare compare;
534
535 //*************************************************************************
537 //*************************************************************************
538 static Data_Node* data_cast(Node* p_node)
539 {
540 return static_cast<Data_Node*>(p_node);
541 }
542
543 //*************************************************************************
545 //*************************************************************************
546 static Data_Node& data_cast(Node& node)
547 {
548 return static_cast<Data_Node&>(node);
549 }
550
551 //*************************************************************************
553 //*************************************************************************
554 static const Data_Node* data_cast(const Node* p_node)
555 {
556 return static_cast<const Data_Node*>(p_node);
557 }
558
559 //*************************************************************************
561 //*************************************************************************
562 static const Data_Node& data_cast(const Node& node)
563 {
564 return static_cast<const Data_Node&>(node);
565 }
566
567 public:
568
569 //*************************************************************************
571 //*************************************************************************
572 class iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, value_type>
573 {
574 public:
575
576 friend class iset;
577 friend class const_iterator;
578
579 iterator()
580 : p_set(ETL_NULLPTR)
581 , p_node(ETL_NULLPTR)
582 {
583 }
584
585 iterator(iset& set)
586 : p_set(&set)
587 , p_node(ETL_NULLPTR)
588 {
589 }
590
591 iterator(iset& set, Node* node)
592 : p_set(&set)
593 , p_node(node)
594 {
595 }
596
597 iterator(const iterator& other)
598 : p_set(other.p_set)
599 , p_node(other.p_node)
600 {
601 }
602
603 ~iterator() {}
604
605 iterator& operator++()
606 {
607 p_set->next_node(p_node);
608 return *this;
609 }
610
611 iterator operator++(int)
612 {
613 iterator temp(*this);
614 p_set->next_node(p_node);
615 return temp;
616 }
617
618 iterator& operator--()
619 {
620 p_set->prev_node(p_node);
621 return *this;
622 }
623
624 iterator operator--(int)
625 {
626 iterator temp(*this);
627 p_set->prev_node(p_node);
628 return temp;
629 }
630
631 iterator& operator=(const iterator& other)
632 {
633 p_set = other.p_set;
634 p_node = other.p_node;
635 return *this;
636 }
637
638 reference operator*() const
639 {
640 return iset::data_cast(p_node)->value;
641 }
642
643 pointer operator&() const
644 {
645 return &(iset::data_cast(p_node)->value);
646 }
647
648 pointer operator->() const
649 {
650 return &(iset::data_cast(p_node)->value);
651 }
652
653 friend bool operator==(const iterator& lhs, const iterator& rhs)
654 {
655 return lhs.p_set == rhs.p_set && lhs.p_node == rhs.p_node;
656 }
657
658 friend bool operator!=(const iterator& lhs, const iterator& rhs)
659 {
660 return !(lhs == rhs);
661 }
662
663 private:
664
665 // Pointer to set associated with this iterator
666 iset* p_set;
667
668 // Pointer to the current node for this iterator
669 Node* p_node;
670 };
671 friend class iterator;
672
673 //*************************************************************************
675 //*************************************************************************
676 class const_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const value_type>
677 {
678 public:
679
680 friend class iset;
681
682 const_iterator()
683 : p_set(ETL_NULLPTR)
684 , p_node(ETL_NULLPTR)
685 {
686 }
687
688 const_iterator(const iset& set)
689 : p_set(&set)
690 , p_node(ETL_NULLPTR)
691 {
692 }
693
694 const_iterator(const iset& set, const Node* node)
695 : p_set(&set)
696 , p_node(node)
697 {
698 }
699
700 const_iterator(const typename iset::iterator& other)
701 : p_set(other.p_set)
702 , p_node(other.p_node)
703 {
704 }
705
706 const_iterator(const const_iterator& other)
707 : p_set(other.p_set)
708 , p_node(other.p_node)
709 {
710 }
711
712 ~const_iterator() {}
713
714 const_iterator& operator++()
715 {
716 p_set->next_node(p_node);
717 return *this;
718 }
719
720 const_iterator operator++(int)
721 {
722 const_iterator temp(*this);
723 p_set->next_node(p_node);
724 return temp;
725 }
726
727 const_iterator& operator--()
728 {
729 p_set->prev_node(p_node);
730 return *this;
731 }
732
733 const_iterator operator--(int)
734 {
735 const_iterator temp(*this);
736 p_set->prev_node(p_node);
737 return temp;
738 }
739
740 const_iterator& operator=(const const_iterator& other)
741 {
742 p_set = other.p_set;
743 p_node = other.p_node;
744 return *this;
745 }
746
747 const_reference operator*() const
748 {
749 return iset::data_cast(p_node)->value;
750 }
751
752 const_pointer operator&() const
753 {
754 return iset::data_cast(p_node)->value;
755 }
756
757 const_pointer operator->() const
758 {
759 return &(iset::data_cast(p_node)->value);
760 }
761
762 friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
763 {
764 return lhs.p_set == rhs.p_set && lhs.p_node == rhs.p_node;
765 }
766
767 friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
768 {
769 return !(lhs == rhs);
770 }
771
772 private:
773
774 // Convert to an iterator.
775 iset::iterator to_iterator() const
776 {
777 return iset::iterator(const_cast<iset&>(*p_set), const_cast<Node*>(p_node));
778 }
779
780 // Pointer to set associated with this iterator
781 const iset* p_set;
782
783 // Pointer to the current node for this iterator
784 const Node* p_node;
785 };
786 friend class const_iterator;
787
788 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
789
790 typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
791 typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
792
793 //*************************************************************************
795 //*************************************************************************
796 iset& operator=(const iset& rhs)
797 {
798 // Skip if doing self assignment
799 if (this != &rhs)
800 {
801 assign(rhs.cbegin(), rhs.cend());
802 }
803
804 return *this;
805 }
806
807#if ETL_USING_CPP11
808 //*************************************************************************
810 //*************************************************************************
811 iset& operator=(iset&& rhs)
812 {
813 // Skip if doing self assignment
814 if (this != &rhs)
815 {
816 this->clear();
817
818 typename etl::iset<TKey, TCompare>::iterator from = rhs.begin();
819
820 while (from != rhs.end())
821 {
822 typename etl::iset<TKey, TCompare>::iterator temp = from;
823 ++temp;
824
825 this->insert(etl::move(*from));
826 from = temp;
827 }
828 }
829
830 return *this;
831 }
832#endif
833
834 //*************************************************************************
836 //*************************************************************************
838 {
839 return iterator(*this, find_limit_node(root_node, kLeft));
840 }
841
842 //*************************************************************************
844 //*************************************************************************
846 {
847 return const_iterator(*this, find_limit_node(root_node, kLeft));
848 }
849
850 //*************************************************************************
852 //*************************************************************************
854 {
855 return iterator(*this);
856 }
857
858 //*************************************************************************
860 //*************************************************************************
862 {
863 return const_iterator(*this);
864 }
865
866 //*************************************************************************
868 //*************************************************************************
870 {
871 return const_iterator(*this, find_limit_node(root_node, kLeft));
872 }
873
874 //*************************************************************************
876 //*************************************************************************
878 {
879 return const_iterator(*this);
880 }
881
882 //*************************************************************************
884 //*************************************************************************
885 reverse_iterator rbegin()
886 {
887 return reverse_iterator(iterator(*this));
888 }
889
890 //*************************************************************************
892 //*************************************************************************
893 const_reverse_iterator rbegin() const
894 {
895 return const_reverse_iterator(const_iterator(*this));
896 }
897
898 //*************************************************************************
900 //*************************************************************************
901 reverse_iterator rend()
902 {
903 return reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft)));
904 }
905
906 //*************************************************************************
908 //*************************************************************************
909 const_reverse_iterator rend() const
910 {
911 return const_reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft)));
912 }
913
914 //*************************************************************************
916 //*************************************************************************
917 const_reverse_iterator crbegin() const
918 {
919 return const_reverse_iterator(const_iterator(*this));
920 }
921
922 //*************************************************************************
924 //*************************************************************************
925 const_reverse_iterator crend() const
926 {
927 return const_reverse_iterator(const_iterator(*this, find_limit_node(root_node, kLeft)));
928 }
929
930 //*********************************************************************
937 //*********************************************************************
938 template <typename TIterator>
939 void assign(TIterator first, TIterator last)
940 {
941 initialise();
942 insert(first, last);
943 }
944
945 //*************************************************************************
947 //*************************************************************************
948 void clear()
949 {
950 initialise();
951 }
952
953 //*********************************************************************
957 //*********************************************************************
958 size_type count(key_parameter_t key) const
959 {
960 return find_node(root_node, key) ? 1 : 0;
961 }
962
963#if ETL_USING_CPP11
964 //*********************************************************************
965 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
966 size_type count(const K& key) const
967 {
968 return find_node(root_node, key) ? 1 : 0;
969 }
970#endif
971
972 //*************************************************************************
975 //*************************************************************************
976 ETL_OR_STD::pair<iterator, iterator> equal_range(key_parameter_t key)
977 {
978 return ETL_OR_STD::make_pair<iterator, iterator>(iterator(*this, find_lower_node(root_node, key)),
979 iterator(*this, find_upper_node(root_node, key)));
980 }
981
982#if ETL_USING_CPP11
983 //*************************************************************************
984 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
985 ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
986 {
987 return ETL_OR_STD::make_pair<iterator, iterator>(iterator(*this, find_lower_node(root_node, key)),
988 iterator(*this, find_upper_node(root_node, key)));
989 }
990#endif
991
992 //*************************************************************************
995 //*************************************************************************
996 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(key_parameter_t key) const
997 {
998 return ETL_OR_STD::make_pair<const_iterator, const_iterator>(const_iterator(*this, find_lower_node(root_node, key)),
999 const_iterator(*this, find_upper_node(root_node, key)));
1000 }
1001
1002#if ETL_USING_CPP11
1003 //*************************************************************************
1004 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1005 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
1006 {
1007 return ETL_OR_STD::make_pair<const_iterator, const_iterator>(const_iterator(*this, find_lower_node(root_node, key)),
1008 const_iterator(*this, find_upper_node(root_node, key)));
1009 }
1010#endif
1011
1012 //*************************************************************************
1014 //*************************************************************************
1016 {
1017 // Remove the node by its node specified in iterator position
1018 return erase(const_iterator(position));
1019 }
1020
1021 //*************************************************************************
1023 //*************************************************************************
1025 {
1026 // Find the parent node to be removed
1027 Node*& reference_node = find_node(root_node, position.p_node);
1028 iterator next(*this, reference_node);
1029 ++next;
1030
1031 remove_node(root_node, (*position));
1032
1033 return next;
1034 }
1035
1036 //*************************************************************************
1037 // Erase the key specified.
1038 //*************************************************************************
1040 {
1041 // Return 1 if key value was found and removed
1042 return remove_node(root_node, key_value) ? 1 : 0;
1043 }
1044
1045 //*************************************************************************
1046#if ETL_USING_CPP11
1047 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1048 size_type erase(K&& key_value)
1049 {
1050 // Return 1 if key value was found and removed
1051 return remove_node(root_node, etl::forward<K>(key_value)) ? 1 : 0;
1052 }
1053#endif
1054
1055 //*************************************************************************
1057 //*************************************************************************
1059 {
1060 while (first != last)
1061 {
1062 first = erase(first);
1063 }
1064
1065 return last.to_iterator();
1066 }
1067
1068 //*********************************************************************
1072 //*********************************************************************
1074 {
1075 return iterator(*this, find_node(root_node, key_value));
1076 }
1077
1078#if ETL_USING_CPP11
1079 //*********************************************************************
1080 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1081 iterator find(const K& k)
1082 {
1083 return iterator(*this, find_node(root_node, k));
1084 }
1085#endif
1086
1087 //*********************************************************************
1091 //*********************************************************************
1093 {
1094 return const_iterator(*this, find_node(root_node, key_value));
1095 }
1096
1097#if ETL_USING_CPP11
1098 //*********************************************************************
1099 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1100 const_iterator find(const K& key_value) const
1101 {
1102 return const_iterator(*this, find_node(root_node, key_value));
1103 }
1104#endif
1105
1106 //*********************************************************************
1111 //*********************************************************************
1112 ETL_OR_STD::pair<iterator, bool> insert(const_reference value)
1113 {
1114 // Default to no inserted node
1115 Node* inserted_node = ETL_NULLPTR;
1116 bool inserted = false;
1117
1118 if (full())
1119 {
1120 iterator iter = find(value);
1121 if (iter == end())
1122 {
1123 ETL_ASSERT_FAIL(ETL_ERROR(set_full));
1124 }
1125 else
1126 {
1127 return ETL_OR_STD::make_pair(iter, false);
1128 }
1129 }
1130
1131 // Get next available free node
1132 Data_Node& node = allocate_data_node(value);
1133
1134 // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1135 inserted_node = insert_node(root_node, node);
1136 inserted = inserted_node == &node;
1137
1138 // Insert node into tree and return iterator to new node location in tree
1139 return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted);
1140 }
1141
1142#if ETL_USING_CPP11
1143 //*********************************************************************
1148 //*********************************************************************
1149 ETL_OR_STD::pair<iterator, bool> insert(rvalue_reference value)
1150 {
1151 // Default to no inserted node
1152 Node* inserted_node = ETL_NULLPTR;
1153 bool inserted = false;
1154
1155 if (full())
1156 {
1157 iterator iter = find(value);
1158 if (iter == end())
1159 {
1160 ETL_ASSERT_FAIL(ETL_ERROR(set_full));
1161 }
1162 else
1163 {
1164 return ETL_OR_STD::make_pair(iter, false);
1165 }
1166 }
1167
1168 // Get next available free node
1169 Data_Node& node = allocate_data_node(etl::move(value));
1170
1171 // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1172 inserted_node = insert_node(root_node, node);
1173 inserted = inserted_node == &node;
1174
1175 // Insert node into tree and return iterator to new node location in tree
1176 return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted);
1177 }
1178#endif
1179
1180 //*********************************************************************
1186 //*********************************************************************
1187 iterator insert(const_iterator, const_reference value)
1188 {
1189 // Default to no inserted node
1190 Node* inserted_node = ETL_NULLPTR;
1191
1192 if (full())
1193 {
1194 iterator iter = find(value);
1195 if (iter == end())
1196 {
1197 ETL_ASSERT_FAIL(ETL_ERROR(set_full));
1198 }
1199 else
1200 {
1201 return iter;
1202 }
1203 }
1204
1205 // Get next available free node
1206 Data_Node& node = allocate_data_node(value);
1207
1208 // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1209 inserted_node = insert_node(root_node, node);
1210
1211 // Insert node into tree and return iterator to new node location in tree
1212 return iterator(*this, inserted_node);
1213 }
1214
1215#if ETL_USING_CPP11
1216 //*********************************************************************
1222 //*********************************************************************
1223 iterator insert(const_iterator, rvalue_reference value)
1224 {
1225 // Default to no inserted node
1226 Node* inserted_node = ETL_NULLPTR;
1227
1228 if (full())
1229 {
1230 iterator iter = find(value);
1231 if (iter == end())
1232 {
1233 ETL_ASSERT_FAIL(ETL_ERROR(set_full));
1234 }
1235 else
1236 {
1237 return iter;
1238 }
1239 }
1240
1241 // Get next available free node
1242 Data_Node& node = allocate_data_node(etl::move(value));
1243
1244 // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1245 inserted_node = insert_node(root_node, node);
1246
1247 // Insert node into tree and return iterator to new node location in tree
1248 return iterator(*this, inserted_node);
1249 }
1250#endif
1251
1252 //*********************************************************************
1259 //*********************************************************************
1260 template <class TIterator>
1261 void insert(TIterator first, TIterator last)
1262 {
1263 while (first != last)
1264 {
1265 insert(*first);
1266 ++first;
1267 }
1268 }
1269
1270 //*********************************************************************
1275 //*********************************************************************
1277 {
1278 return iterator(*this, find_lower_node(root_node, key));
1279 }
1280
1281#if ETL_USING_CPP11
1282 //*********************************************************************
1283 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1284 iterator lower_bound(const K& key)
1285 {
1286 return iterator(*this, find_lower_node(root_node, key));
1287 }
1288#endif
1289
1290 //*********************************************************************
1295 //*********************************************************************
1297 {
1298 return const_iterator(*this, find_lower_node(root_node, key));
1299 }
1300
1301#if ETL_USING_CPP11
1302 //*********************************************************************
1303 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1304 const_iterator lower_bound(const K& key) const
1305 {
1306 return const_iterator(*this, find_lower_node(root_node, key));
1307 }
1308#endif
1309
1310 //*********************************************************************
1315 //*********************************************************************
1317 {
1318 return iterator(*this, find_upper_node(root_node, key));
1319 }
1320
1321#if ETL_USING_CPP11
1322 //*********************************************************************
1323 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1324 iterator upper_bound(const K& key)
1325 {
1326 return iterator(*this, find_upper_node(root_node, key));
1327 }
1328#endif
1329
1330 //*********************************************************************
1335 //*********************************************************************
1337 {
1338 return const_iterator(*this, find_upper_node(root_node, key));
1339 }
1340
1341#if ETL_USING_CPP11
1342 //*********************************************************************
1343 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1344 const_iterator upper_bound(const K& key) const
1345 {
1346 return const_iterator(*this, find_upper_node(root_node, key));
1347 }
1348#endif
1349
1350 //*************************************************************************
1352 //*************************************************************************
1353 key_compare key_comp() const
1354 {
1355 return compare;
1356 }
1357
1358 //*************************************************************************
1360 //*************************************************************************
1361 value_compare value_comp() const
1362 {
1363 return compare;
1364 }
1365
1366 //*************************************************************************
1368 //*************************************************************************
1369 bool contains(const TKey& key) const
1370 {
1371 return find(key) != end();
1372 }
1373
1374#if ETL_USING_CPP11
1375 //*************************************************************************
1376 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1377 bool contains(const K& k) const
1378 {
1379 return find(k) != end();
1380 }
1381#endif
1382
1383 protected:
1384
1385 //*************************************************************************
1387 //*************************************************************************
1388 iset(etl::ipool& node_pool, size_t max_size_)
1389 : etl::set_base(max_size_)
1390 , p_node_pool(&node_pool)
1391 {
1392 }
1393
1394 //*************************************************************************
1396 //*************************************************************************
1398 {
1399 const_iterator item = begin();
1400
1401 while (item != end())
1402 {
1403 item = erase(item);
1404 }
1405 }
1406
1407 private:
1408
1409 //*************************************************************************
1411 //*************************************************************************
1412 Data_Node& allocate_data_node(const_reference value)
1413 {
1414 Data_Node* node = allocate_data_node();
1415 ::new ((void*)&node->value) value_type(value);
1416 ETL_INCREMENT_DEBUG_COUNT;
1417 return *node;
1418 }
1419
1420#if ETL_USING_CPP11
1421 //*************************************************************************
1423 //*************************************************************************
1424 Data_Node& allocate_data_node(rvalue_reference value)
1425 {
1426 Data_Node* node = allocate_data_node();
1427 ::new ((void*)&node->value) value_type(etl::move(value));
1428 ETL_INCREMENT_DEBUG_COUNT;
1429 return *node;
1430 }
1431#endif
1432
1433 //*************************************************************************
1435 //*************************************************************************
1436 Data_Node* allocate_data_node()
1437 {
1438 Data_Node* (etl::ipool::*func)() = &etl::ipool::allocate<Data_Node>;
1439 return (p_node_pool->*func)();
1440 }
1441
1442 //*************************************************************************
1444 //*************************************************************************
1445 void destroy_data_node(Data_Node& node)
1446 {
1447 node.value.~value_type();
1448 p_node_pool->release(&node);
1449 ETL_DECREMENT_DEBUG_COUNT;
1450 }
1451
1452 //*************************************************************************
1454 //*************************************************************************
1455 Node* find_node(Node* position, key_parameter_t key)
1456 {
1457 Node* found = position;
1458 while (found)
1459 {
1460 // Downcast found to Data_Node class for comparison and other operations
1461 Data_Node& found_data_node = iset::data_cast(*found);
1462
1463 // Compare the node value to the current position value
1464 if (node_comp(key, found_data_node))
1465 {
1466 // Keep searching for the node on the left
1467 found = found->children[kLeft];
1468 }
1469 else if (node_comp(found_data_node, key))
1470 {
1471 // Keep searching for the node on the right
1472 found = found->children[kRight];
1473 }
1474 else
1475 {
1476 // Node that matches the key provided was found, exit loop
1477 break;
1478 }
1479 }
1480
1481 // Return the node found (might be ETL_NULLPTR)
1482 return found;
1483 }
1484
1485#if ETL_USING_CPP11
1486 //*************************************************************************
1487 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1488 Node* find_node(Node* position, const K& key)
1489 {
1490 Node* found = position;
1491 while (found)
1492 {
1493 // Downcast found to Data_Node class for comparison and other operations
1494 Data_Node& found_data_node = iset::data_cast(*found);
1495
1496 // Compare the node value to the current position value
1497 if (node_comp(key, found_data_node))
1498 {
1499 // Keep searching for the node on the left
1500 found = found->children[kLeft];
1501 }
1502 else if (node_comp(found_data_node, key))
1503 {
1504 // Keep searching for the node on the right
1505 found = found->children[kRight];
1506 }
1507 else
1508 {
1509 // Node that matches the key provided was found, exit loop
1510 break;
1511 }
1512 }
1513
1514 // Return the node found (might be ETL_NULLPTR)
1515 return found;
1516 }
1517#endif
1518
1519 //*************************************************************************
1521 //*************************************************************************
1522 const Node* find_node(const Node* position, key_parameter_t key) const
1523 {
1524 const Node* found = position;
1525 while (found)
1526 {
1527 // Downcast found to Data_Node class for comparison and other operations
1528 const Data_Node& found_data_node = iset::data_cast(*found);
1529
1530 // Compare the node value to the current position value
1531 if (node_comp(key, found_data_node))
1532 {
1533 // Keep searching for the node on the left
1534 found = found->children[kLeft];
1535 }
1536 else if (node_comp(found_data_node, key))
1537 {
1538 // Keep searching for the node on the right
1539 found = found->children[kRight];
1540 }
1541 else
1542 {
1543 // Node that matches the key provided was found, exit loop
1544 break;
1545 }
1546 }
1547
1548 // Return the node found (might be ETL_NULLPTR)
1549 return found;
1550 }
1551
1552#if ETL_USING_CPP11
1553 //*************************************************************************
1554 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1555 const Node* find_node(const Node* position, const K& key) const
1556 {
1557 const Node* found = position;
1558 while (found)
1559 {
1560 // Downcast found to Data_Node class for comparison and other operations
1561 const Data_Node& found_data_node = iset::data_cast(*found);
1562
1563 // Compare the node value to the current position value
1564 if (node_comp(key, found_data_node))
1565 {
1566 // Keep searching for the node on the left
1567 found = found->children[kLeft];
1568 }
1569 else if (node_comp(found_data_node, key))
1570 {
1571 // Keep searching for the node on the right
1572 found = found->children[kRight];
1573 }
1574 else
1575 {
1576 // Node that matches the key provided was found, exit loop
1577 break;
1578 }
1579 }
1580
1581 // Return the node found (might be ETL_NULLPTR)
1582 return found;
1583 }
1584#endif
1585
1586 //*************************************************************************
1588 //*************************************************************************
1589 Node*& find_node(Node*& position, const Node* node)
1590 {
1591 Node* found = position;
1592 while (found)
1593 {
1594 if (found->children[kLeft] == node)
1595 {
1596 return found->children[kLeft];
1597 }
1598 else if (found->children[kRight] == node)
1599 {
1600 return found->children[kRight];
1601 }
1602 else
1603 {
1604 // Downcast found to Data_Node class for comparison and other
1605 // operations
1606 Data_Node& found_data_node = iset::data_cast(*found);
1607 const Data_Node& data_node = iset::data_cast(*node);
1608
1609 // Compare the node value to the current position value
1610 if (node_comp(data_node, found_data_node))
1611 {
1612 // Keep searching for the node on the left
1613 found = found->children[kLeft];
1614 }
1615 else if (node_comp(found_data_node, data_node))
1616 {
1617 // Keep searching for the node on the right
1618 found = found->children[kRight];
1619 }
1620 else
1621 {
1622 // Return position provided (it matches the node)
1623 return position;
1624 }
1625 }
1626 }
1627
1628 // Return root node if nothing was found
1629 return root_node;
1630 }
1631
1632 //*************************************************************************
1635 //*************************************************************************
1636 Node* find_parent_node(Node* position, const Node* node)
1637 {
1638 // Default to no parent node found
1639 Node* found = ETL_NULLPTR;
1640
1641 // If the position provided is the same as the node then there is no
1642 // parent
1643 if (position && node && position != node)
1644 {
1645 while (position)
1646 {
1647 // Is this position not the parent of the node we are looking for?
1648 if (position->children[kLeft] != node && position->children[kRight] != node)
1649 {
1650 // Downcast node and position to Data_Node references for key
1651 // comparisons
1652 const Data_Node& node_data_node = iset::data_cast(*node);
1653 Data_Node& position_data_node = iset::data_cast(*position);
1654 // Compare the node value to the current position value
1655 if (node_comp(node_data_node, position_data_node))
1656 {
1657 // Keep looking for parent on the left
1658 position = position->children[kLeft];
1659 }
1660 else if (node_comp(position_data_node, node_data_node))
1661 {
1662 // Keep looking for parent on the right
1663 position = position->children[kRight];
1664 }
1665 }
1666 else
1667 {
1668 // Return the current position as the parent node found
1669 found = position;
1670
1671 // Parent node found, exit loop
1672 break;
1673 }
1674 }
1675 }
1676
1677 // Return the parent node found (might be ETL_NULLPTR)
1678 return found;
1679 }
1680
1681 //*************************************************************************
1684 //*************************************************************************
1685 const Node* find_parent_node(const Node* position, const Node* node) const
1686 {
1687 // Default to no parent node found
1688 const Node* found = ETL_NULLPTR;
1689
1690 // If the position provided is the same as the node then there is no
1691 // parent
1692 if (position && node && position != node)
1693 {
1694 while (position)
1695 {
1696 // Is this position not the parent of the node we are looking for?
1697 if (position->children[kLeft] != node && position->children[kRight] != node)
1698 {
1699 // Downcast node and position to Data_Node references for key
1700 // comparisons
1701 const Data_Node& node_data_node = iset::data_cast(*node);
1702 const Data_Node& position_data_node = iset::data_cast(*position);
1703 // Compare the node value to the current position value
1704 if (node_comp(node_data_node, position_data_node))
1705 {
1706 // Keep looking for parent on the left
1707 position = position->children[kLeft];
1708 }
1709 else if (node_comp(position_data_node, node_data_node))
1710 {
1711 // Keep looking for parent on the right
1712 position = position->children[kRight];
1713 }
1714 }
1715 else
1716 {
1717 // Return the current position as the parent node found
1718 found = position;
1719
1720 // Parent node found, exit loop
1721 break;
1722 }
1723 }
1724 }
1725
1726 // Return the parent node found (might be ETL_NULLPTR)
1727 return found;
1728 }
1729
1730 //*************************************************************************
1732 //*************************************************************************
1733 Node* find_lower_node(Node* position, key_parameter_t key) const
1734 {
1735 // Something at this position? keep going
1736 Node* lower_node = ETL_NULLPTR;
1737 while (position)
1738 {
1739 // Downcast lower node to Data_Node reference for key comparisons
1740 Data_Node& data_node = iset::data_cast(*position);
1741 // Compare the key value to the current lower node key value
1742 if (node_comp(key, data_node))
1743 {
1744 lower_node = position;
1745 if (position->children[kLeft])
1746 {
1747 position = position->children[kLeft];
1748 }
1749 else
1750 {
1751 // Found lowest node
1752 break;
1753 }
1754 }
1755 else if (node_comp(data_node, key))
1756 {
1757 position = position->children[kRight];
1758 }
1759 else
1760 {
1761 // Make note of current position, but keep looking to left for more
1762 lower_node = position;
1763 position = position->children[kLeft];
1764 }
1765 }
1766
1767 // Return the lower_node position found
1768 return lower_node;
1769 }
1770
1771#if ETL_USING_CPP11
1772 //*************************************************************************
1773 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1774 Node* find_lower_node(Node* position, const K& key) const
1775 {
1776 // Something at this position? keep going
1777 Node* lower_node = ETL_NULLPTR;
1778 while (position)
1779 {
1780 // Downcast lower node to Data_Node reference for key comparisons
1781 Data_Node& data_node = iset::data_cast(*position);
1782 // Compare the key value to the current lower node key value
1783 if (node_comp(key, data_node))
1784 {
1785 lower_node = position;
1786 if (position->children[kLeft])
1787 {
1788 position = position->children[kLeft];
1789 }
1790 else
1791 {
1792 // Found lowest node
1793 break;
1794 }
1795 }
1796 else if (node_comp(data_node, key))
1797 {
1798 position = position->children[kRight];
1799 }
1800 else
1801 {
1802 // Make note of current position, but keep looking to left for more
1803 lower_node = position;
1804 position = position->children[kLeft];
1805 }
1806 }
1807
1808 // Return the lower_node position found
1809 return lower_node;
1810 }
1811#endif
1812
1813 //*************************************************************************
1815 //*************************************************************************
1816 Node* find_upper_node(Node* position, key_parameter_t key) const
1817 {
1818 // Keep track of parent of last upper node
1819 Node* upper_node = ETL_NULLPTR;
1820 // Start with position provided
1821 Node* node = position;
1822 while (node)
1823 {
1824 // Downcast position to Data_Node reference for key comparisons
1825 Data_Node& data_node = iset::data_cast(*node);
1826 // Compare the key value to the current upper node key value
1827 if (node_comp(key, data_node))
1828 {
1829 upper_node = node;
1830 node = node->children[kLeft];
1831 }
1832 else if (node_comp(data_node, key))
1833 {
1834 node = node->children[kRight];
1835 }
1836 else if (node->children[kRight])
1837 {
1838 upper_node = find_limit_node(node->children[kRight], kLeft);
1839 break;
1840 }
1841 else
1842 {
1843 break;
1844 }
1845 }
1846
1847 // Return the upper node position found (might be ETL_NULLPTR)
1848 return upper_node;
1849 }
1850
1851#if ETL_USING_CPP11
1852 //*************************************************************************
1853 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1854 Node* find_upper_node(Node* position, const K& key) const
1855 {
1856 // Keep track of parent of last upper node
1857 Node* upper_node = ETL_NULLPTR;
1858 // Start with position provided
1859 Node* node = position;
1860 while (node)
1861 {
1862 // Downcast position to Data_Node reference for key comparisons
1863 Data_Node& data_node = iset::data_cast(*node);
1864 // Compare the key value to the current upper node key value
1865 if (node_comp(key, data_node))
1866 {
1867 upper_node = node;
1868 node = node->children[kLeft];
1869 }
1870 else if (node_comp(data_node, key))
1871 {
1872 node = node->children[kRight];
1873 }
1874 else if (node->children[kRight])
1875 {
1876 upper_node = find_limit_node(node->children[kRight], kLeft);
1877 break;
1878 }
1879 else
1880 {
1881 break;
1882 }
1883 }
1884
1885 // Return the upper node position found (might be ETL_NULLPTR)
1886 return upper_node;
1887 }
1888#endif
1889
1890 //*************************************************************************
1892 //*************************************************************************
1893 Node* insert_node(Node*& position, Data_Node& node)
1894 {
1895 // Find the location where the node belongs
1896 Node* found = position;
1897
1898 // Was position provided not empty? then find where the node belongs
1899 if (position)
1900 {
1901 // Find the critical parent node (default to ETL_NULLPTR)
1902 Node* critical_parent_node = ETL_NULLPTR;
1903 Node* critical_node = root_node;
1904
1905 while (found)
1906 {
1907 // Search for critical weight node (all nodes whose weight factor
1908 // is set to kNeither (balanced)
1909 if (kNeither != found->weight)
1910 {
1911 critical_node = found;
1912 }
1913
1914 // Downcast found to Data_Node class for comparison and other
1915 // operations
1916 Data_Node& found_data_node = iset::data_cast(*found);
1917
1918 // Is the node provided to the left of the current position?
1919 if (node_comp(node, found_data_node))
1920 {
1921 // Update direction taken to insert new node in parent node
1922 found->dir = kLeft;
1923 }
1924 // Is the node provided to the right of the current position?
1925 else if (node_comp(found_data_node, node))
1926 {
1927 // Update direction taken to insert new node in parent node
1928 found->dir = kRight;
1929 }
1930 else
1931 {
1932 // Update direction taken to insert new node in parent node
1933 found->dir = kNeither;
1934
1935 // Clear critical node value to skip weight step below
1936 critical_node = ETL_NULLPTR;
1937
1938 // Destroy the node provided (its a duplicate)
1939 destroy_data_node(node);
1940
1941 // Exit loop, duplicate node found
1942 break;
1943 }
1944
1945 // Is there a child of this parent node?
1946 if (found->children[found->dir])
1947 {
1948 // Will this node be the parent of the next critical node whose
1949 // weight factor is set to kNeither (balanced)?
1950 if (kNeither != found->children[found->dir]->weight)
1951 {
1952 critical_parent_node = found;
1953 }
1954
1955 // Keep looking for empty spot to insert new node
1956 found = found->children[found->dir];
1957 }
1958 else
1959 {
1960 // Attach node to right
1961 attach_node(found->children[found->dir], node);
1962
1963 // Return newly added node
1964 found = found->children[found->dir];
1965
1966 // Exit loop
1967 break;
1968 }
1969 }
1970
1971 // Was a critical node found that should be checked for balance?
1972 if (critical_node)
1973 {
1974 if (critical_parent_node == ETL_NULLPTR && critical_node == root_node)
1975 {
1977 }
1978 else if (critical_parent_node == ETL_NULLPTR && critical_node == position)
1979 {
1980 balance_node(position);
1981 }
1982 else
1983 {
1984 if (critical_parent_node != ETL_NULLPTR)
1985 {
1986 balance_node(critical_parent_node->children[critical_parent_node->dir]);
1987 }
1988 }
1989 }
1990 }
1991 else
1992 {
1993 // Attach node to current position
1994 attach_node(position, node);
1995
1996 // Return newly added node at current position
1997 found = position;
1998 }
1999
2000 // Return the node found (might be ETL_NULLPTR)
2001 return found;
2002 }
2003
2004 //*************************************************************************
2006 //*************************************************************************
2007 void next_node(Node*& position)
2008 {
2009 if (position)
2010 {
2011 // Is there a tree on the right? then find the minimum of that tree
2012 if (position->children[kRight])
2013 {
2014 // Return minimum node found
2015 position = find_limit_node(position->children[kRight], kLeft);
2016 }
2017 // Otherwise find the parent of this node
2018 else
2019 {
2020 // Start with current position as parent
2021 Node* parent = position;
2022 do {
2023 // Update current position as previous parent
2024 position = parent;
2025 // Find parent of current position
2026 parent = find_parent_node(root_node, position);
2027 // Repeat while previous position was on right side of parent tree
2028 } while (parent && parent->children[kRight] == position);
2029
2030 // Set parent node as the next position
2031 position = parent;
2032 }
2033 }
2034 }
2035
2036 //*************************************************************************
2038 //*************************************************************************
2039 void next_node(const Node*& position) const
2040 {
2041 if (position)
2042 {
2043 // Is there a tree on the right? then find the minimum of that tree
2044 if (position->children[kRight])
2045 {
2046 // Return minimum node found
2047 position = find_limit_node(position->children[kRight], kLeft);
2048 }
2049 // Otherwise find the parent of this node
2050 else
2051 {
2052 // Start with current position as parent
2053 const Node* parent = position;
2054 do {
2055 // Update current position as previous parent
2056 position = parent;
2057 // Find parent of current position
2058 parent = find_parent_node(root_node, position);
2059 // Repeat while previous position was on right side of parent tree
2060 } while (parent && parent->children[kRight] == position);
2061
2062 // Set parent node as the next position
2063 position = parent;
2064 }
2065 }
2066 }
2067
2068 //*************************************************************************
2070 //*************************************************************************
2071 void prev_node(Node*& position)
2072 {
2073 // If starting at the terminal end, the previous node is the maximum node
2074 // from the root
2075 if (!position)
2076 {
2077 position = find_limit_node(root_node, kRight);
2078 }
2079 else
2080 {
2081 // Is there a tree on the left? then find the maximum of that tree
2082 if (position->children[kLeft])
2083 {
2084 // Return maximum node found
2085 position = find_limit_node(position->children[kLeft], kRight);
2086 }
2087 // Otherwise find the parent of this node
2088 else
2089 {
2090 // Start with current position as parent
2091 Node* parent = position;
2092 do {
2093 // Update current position as previous parent
2094 position = parent;
2095 // Find parent of current position
2096 parent = find_parent_node(root_node, position);
2097 // Repeat while previous position was on left side of parent tree
2098 } while (parent && parent->children[kLeft] == position);
2099
2100 // Set parent node as the next position
2101 position = parent;
2102 }
2103 }
2104 }
2105
2106 //*************************************************************************
2108 //*************************************************************************
2109 void prev_node(const Node*& position) const
2110 {
2111 // If starting at the terminal end, the previous node is the maximum node
2112 // from the root
2113 if (!position)
2114 {
2115 position = find_limit_node(root_node, kRight);
2116 }
2117 else
2118 {
2119 // Is there a tree on the left? then find the maximum of that tree
2120 if (position->children[kLeft])
2121 {
2122 // Return maximum node found
2123 position = find_limit_node(position->children[kLeft], kRight);
2124 }
2125 // Otherwise find the parent of this node
2126 else
2127 {
2128 // Start with current position as parent
2129 const Node* parent = position;
2130 do {
2131 // Update current position as previous parent
2132 position = parent;
2133 // Find parent of current position
2134 parent = find_parent_node(root_node, position);
2135 // Repeat while previous position was on left side of parent tree
2136 } while (parent && parent->children[kLeft] == position);
2137
2138 // Set parent node as the next position
2139 position = parent;
2140 }
2141 }
2142 }
2143
2144 //*************************************************************************
2147 //*************************************************************************
2148 Node* remove_node(Node*& position, key_parameter_t key)
2149 {
2150 // Step 1: Find the target node that matches the key provided, the
2151 // replacement node (might be the same as target node), and the critical
2152 // node to start rebalancing the tree from (up to the replacement node)
2153 Node* found_parent = ETL_NULLPTR;
2154 Node* found = ETL_NULLPTR;
2155 Node* replace_parent = ETL_NULLPTR;
2156 Node* replace = position;
2157 Node* balance_parent = ETL_NULLPTR;
2158 Node* balance = root_node;
2159 while (replace)
2160 {
2161 // Downcast found to Data_Node class for comparison and other operations
2162 Data_Node& replace_data_node = iset::data_cast(*replace);
2163
2164 // Compare the key provided to the replace data node key
2165 if (node_comp(key, replace_data_node))
2166 {
2167 // Update the direction to the target/replace node
2168 replace->dir = kLeft;
2169 }
2170 else if (node_comp(replace_data_node, key))
2171 {
2172 // Update the direction to the target/replace node
2173 replace->dir = kRight;
2174 }
2175 else
2176 {
2177 // Update the direction to the replace node (target node found here)
2178 replace->dir = replace->children[kLeft] ? kLeft : kRight;
2179
2180 // Note the target node was found (and its parent)
2181 found_parent = replace_parent;
2182 found = replace;
2183 }
2184 // Replacement node found if its missing a child in the replace->dir
2185 // value set above
2186 if (replace->children[replace->dir] == ETL_NULLPTR)
2187 {
2188 // Exit loop once replace node is found (target might not have been)
2189 break;
2190 }
2191
2192 // If replacement node weight is kNeither or we are taking the shorter
2193 // path of replacement node and our sibling (on longer path) is
2194 // balanced then we need to update the balance node to match this
2195 // replacement node but all our ancestors will not require rebalancing
2196 if ((replace->weight == kNeither) || (replace->weight == (1 - replace->dir) && replace->children[1 - replace->dir]->weight == kNeither))
2197 {
2198 // Update balance node (and its parent) to replacement node
2199 balance_parent = replace_parent;
2200 balance = replace;
2201 }
2202
2203 // Keep searching for the replacement node
2204 replace_parent = replace;
2205 replace = replace->children[replace->dir];
2206 }
2207
2208 // If target node was found, proceed with rebalancing and replacement
2209 if (found)
2210 {
2211 // Step 2: Update weights from critical node to replacement parent node
2212 while (balance)
2213 {
2214 if (balance->children[balance->dir] == ETL_NULLPTR)
2215 {
2216 break;
2217 }
2218
2219 if (balance->weight == kNeither)
2220 {
2221 balance->weight = 1 - balance->dir;
2222 }
2223 else if (balance->weight == balance->dir)
2224 {
2225 balance->weight = kNeither;
2226 }
2227 else
2228 {
2229 int weight = balance->children[1 - balance->dir]->weight;
2230 // Perform a 3 node rotation if weight is same as balance->dir
2231 if (weight == balance->dir)
2232 {
2233 // Is the root node being rebalanced (no parent)
2234 if (balance_parent == ETL_NULLPTR)
2235 {
2236 rotate_3node(root_node, 1 - balance->dir, balance->children[1 - balance->dir]->children[balance->dir]->weight);
2237 }
2238 else
2239 {
2240 rotate_3node(balance_parent->children[balance_parent->dir], 1 - balance->dir,
2241 balance->children[1 - balance->dir]->children[balance->dir]->weight);
2242 }
2243 }
2244 // Already balanced, rebalance and make it heavy in opposite
2245 // direction of the node being removed
2246 else if (weight == kNeither)
2247 {
2248 // Is the root node being rebalanced (no parent)
2249 if (balance_parent == ETL_NULLPTR)
2250 {
2251 rotate_2node(root_node, 1 - balance->dir);
2252 root_node->weight = balance->dir;
2253 }
2254 else
2255 {
2256 rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2257 balance_parent->children[balance_parent->dir]->weight = balance->dir;
2258 }
2259 // Update balance node weight in opposite direction of node
2260 // removed
2261 balance->weight = 1 - balance->dir;
2262 }
2263 // Rebalance and leave it balanced
2264 else
2265 {
2266 // Is the root node being rebalanced (no parent)
2267 if (balance_parent == ETL_NULLPTR)
2268 {
2269 rotate_2node(root_node, 1 - balance->dir);
2270 }
2271 else
2272 {
2273 rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2274 }
2275 }
2276
2277 // Is balance node the same as the target node found? then update
2278 // its parent after the rotation performed above
2279 if (balance == found)
2280 {
2281 if (balance_parent)
2282 {
2283 found_parent = balance_parent->children[balance_parent->dir];
2284 // Update dir since it is likely stale
2285 found_parent->dir = found_parent->children[kLeft] == found ? kLeft : kRight;
2286 }
2287 else
2288 {
2289 found_parent = root_node;
2290 root_node->dir = root_node->children[kLeft] == found ? kLeft : kRight;
2291 }
2292 }
2293 }
2294
2295 // Next balance node to consider
2296 balance_parent = balance;
2297 balance = balance->children[balance->dir];
2298 } // while(balance)
2299
2300 // Step 3: Swap found node with replacement node
2301 if (found_parent)
2302 {
2303 // Handle traditional case
2304 detach_node(found_parent->children[found_parent->dir], replace_parent->children[replace_parent->dir]);
2305 }
2306 // Handle root node removal
2307 else
2308 {
2309 // Valid replacement node for root node being removed?
2310 if (replace_parent)
2311 {
2312 detach_node(root_node, replace_parent->children[replace_parent->dir]);
2313 }
2314 else
2315 {
2316 // Target node and replacement node are both root node
2318 }
2319 }
2320
2321 // Downcast found into data node
2322 Data_Node& found_data_node = iset::data_cast(*found);
2323
2324 // One less.
2325 --current_size;
2326
2327 // Destroy the node removed
2328 destroy_data_node(found_data_node);
2329 } // if(found)
2330
2331 // Return node found (might be ETL_NULLPTR)
2332 return found;
2333 }
2334
2335#if ETL_USING_CPP11
2336 //*************************************************************************
2337 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
2338 Node* remove_node(Node*& position, const K& key)
2339 {
2340 // Step 1: Find the target node that matches the key provided, the
2341 // replacement node (might be the same as target node), and the critical
2342 // node to start rebalancing the tree from (up to the replacement node)
2343 Node* found_parent = ETL_NULLPTR;
2344 Node* found = ETL_NULLPTR;
2345 Node* replace_parent = ETL_NULLPTR;
2346 Node* replace = position;
2347 Node* balance_parent = ETL_NULLPTR;
2348 Node* balance = root_node;
2349 while (replace)
2350 {
2351 // Downcast found to Data_Node class for comparison and other operations
2352 Data_Node& replace_data_node = iset::data_cast(*replace);
2353
2354 // Compare the key provided to the replace data node key
2355 if (node_comp(key, replace_data_node))
2356 {
2357 // Update the direction to the target/replace node
2358 replace->dir = kLeft;
2359 }
2360 else if (node_comp(replace_data_node, key))
2361 {
2362 // Update the direction to the target/replace node
2363 replace->dir = kRight;
2364 }
2365 else
2366 {
2367 // Update the direction to the replace node (target node found here)
2368 replace->dir = replace->children[kLeft] ? kLeft : kRight;
2369
2370 // Note the target node was found (and its parent)
2371 found_parent = replace_parent;
2372 found = replace;
2373 }
2374 // Replacement node found if its missing a child in the replace->dir
2375 // value set above
2376 if (replace->children[replace->dir] == ETL_NULLPTR)
2377 {
2378 // Exit loop once replace node is found (target might not have been)
2379 break;
2380 }
2381
2382 // If replacement node weight is kNeither or we are taking the shorter
2383 // path of replacement node and our sibling (on longer path) is
2384 // balanced then we need to update the balance node to match this
2385 // replacement node but all our ancestors will not require rebalancing
2386 if ((replace->weight == kNeither) || (replace->weight == (1 - replace->dir) && replace->children[1 - replace->dir]->weight == kNeither))
2387 {
2388 // Update balance node (and its parent) to replacement node
2389 balance_parent = replace_parent;
2390 balance = replace;
2391 }
2392
2393 // Keep searching for the replacement node
2394 replace_parent = replace;
2395 replace = replace->children[replace->dir];
2396 }
2397
2398 // If target node was found, proceed with rebalancing and replacement
2399 if (found)
2400 {
2401 // Step 2: Update weights from critical node to replacement parent node
2402 while (balance)
2403 {
2404 if (balance->children[balance->dir] == ETL_NULLPTR)
2405 {
2406 break;
2407 }
2408
2409 if (balance->weight == kNeither)
2410 {
2411 balance->weight = 1 - balance->dir;
2412 }
2413 else if (balance->weight == balance->dir)
2414 {
2415 balance->weight = kNeither;
2416 }
2417 else
2418 {
2419 int weight = balance->children[1 - balance->dir]->weight;
2420 // Perform a 3 node rotation if weight is same as balance->dir
2421 if (weight == balance->dir)
2422 {
2423 // Is the root node being rebalanced (no parent)
2424 if (balance_parent == ETL_NULLPTR)
2425 {
2426 rotate_3node(root_node, 1 - balance->dir, balance->children[1 - balance->dir]->children[balance->dir]->weight);
2427 }
2428 else
2429 {
2430 rotate_3node(balance_parent->children[balance_parent->dir], 1 - balance->dir,
2431 balance->children[1 - balance->dir]->children[balance->dir]->weight);
2432 }
2433 }
2434 // Already balanced, rebalance and make it heavy in opposite
2435 // direction of the node being removed
2436 else if (weight == kNeither)
2437 {
2438 // Is the root node being rebalanced (no parent)
2439 if (balance_parent == ETL_NULLPTR)
2440 {
2441 rotate_2node(root_node, 1 - balance->dir);
2442 root_node->weight = balance->dir;
2443 }
2444 else
2445 {
2446 rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2447 balance_parent->children[balance_parent->dir]->weight = balance->dir;
2448 }
2449 // Update balance node weight in opposite direction of node
2450 // removed
2451 balance->weight = 1 - balance->dir;
2452 }
2453 // Rebalance and leave it balanced
2454 else
2455 {
2456 // Is the root node being rebalanced (no parent)
2457 if (balance_parent == ETL_NULLPTR)
2458 {
2459 rotate_2node(root_node, 1 - balance->dir);
2460 }
2461 else
2462 {
2463 rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2464 }
2465 }
2466
2467 // Is balance node the same as the target node found? then update
2468 // its parent after the rotation performed above
2469 if (balance == found)
2470 {
2471 if (balance_parent)
2472 {
2473 found_parent = balance_parent->children[balance_parent->dir];
2474 // Update dir since it is likely stale
2475 found_parent->dir = found_parent->children[kLeft] == found ? kLeft : kRight;
2476 }
2477 else
2478 {
2479 found_parent = root_node;
2480 root_node->dir = root_node->children[kLeft] == found ? kLeft : kRight;
2481 }
2482 }
2483 }
2484
2485 // Next balance node to consider
2486 balance_parent = balance;
2487 balance = balance->children[balance->dir];
2488 } // while(balance)
2489
2490 // Step 3: Swap found node with replacement node
2491 if (found_parent)
2492 {
2493 // Handle traditional case
2494 detach_node(found_parent->children[found_parent->dir], replace_parent->children[replace_parent->dir]);
2495 }
2496 // Handle root node removal
2497 else
2498 {
2499 // Valid replacement node for root node being removed?
2500 if (replace_parent)
2501 {
2502 detach_node(root_node, replace_parent->children[replace_parent->dir]);
2503 }
2504 else
2505 {
2506 // Target node and replacement node are both root node
2508 }
2509 }
2510
2511 // Downcast found into data node
2512 Data_Node& found_data_node = iset::data_cast(*found);
2513
2514 // One less.
2515 --current_size;
2516
2517 // Destroy the node removed
2518 destroy_data_node(found_data_node);
2519 } // if(found)
2520
2521 // Return node found (might be ETL_NULLPTR)
2522 return found;
2523 }
2524#endif
2525
2526 // Disable copy construction.
2527 iset(const iset&);
2528
2529 //*************************************************************************
2531 //*************************************************************************
2532#if defined(ETL_POLYMORPHIC_SET) || defined(ETL_POLYMORPHIC_CONTAINERS)
2533
2534 public:
2535
2536 virtual ~iset() {}
2537#else
2538
2539 protected:
2540
2542#endif
2543 };
2544
2545 //*************************************************************************
2547 //*************************************************************************
2548 template <typename TKey, const size_t MAX_SIZE_, typename TCompare = etl::less<TKey> >
2549 class set : public etl::iset<TKey, TCompare>
2550 {
2551 public:
2552
2553 static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
2554
2555 //*************************************************************************
2557 //*************************************************************************
2559 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2560 {
2561 this->initialise();
2562 }
2563
2564 //*************************************************************************
2566 //*************************************************************************
2567 set(const set& other)
2568 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2569 {
2570 if (this != &other)
2571 {
2572 this->assign(other.cbegin(), other.cend());
2573 }
2574 }
2575
2576#if ETL_USING_CPP11
2577 //*************************************************************************
2579 //*************************************************************************
2580 set(set&& other)
2581 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2582 {
2583 if (this != &other)
2584 {
2585 typename etl::iset<TKey, TCompare>::iterator from = other.begin();
2586
2587 while (from != other.end())
2588 {
2589 typename etl::iset<TKey, TCompare>::iterator temp = from;
2590 ++temp;
2591
2592 this->insert(etl::move(*from));
2593 from = temp;
2594 }
2595 }
2596 }
2597#endif
2598
2599 //*************************************************************************
2604 //*************************************************************************
2605 template <typename TIterator>
2606 set(TIterator first, TIterator last)
2607 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2608 {
2609 this->assign(first, last);
2610 }
2611
2612#if ETL_HAS_INITIALIZER_LIST
2613 //*************************************************************************
2615 //*************************************************************************
2616 set(std::initializer_list<typename etl::iset<TKey, TCompare>::value_type> init)
2617 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2618 {
2619 this->assign(init.begin(), init.end());
2620 }
2621#endif
2622
2623 //*************************************************************************
2625 //*************************************************************************
2627 {
2628 this->initialise();
2629 }
2630
2631 //*************************************************************************
2633 //*************************************************************************
2634 set& operator=(const set& rhs)
2635 {
2636 // Skip if doing self assignment
2637 if (this != &rhs)
2638 {
2639 this->assign(rhs.cbegin(), rhs.cend());
2640 }
2641
2642 return *this;
2643 }
2644
2645#if ETL_USING_CPP11
2646 //*************************************************************************
2648 //*************************************************************************
2649 set& operator=(set&& rhs)
2650 {
2651 // Skip if doing self assignment
2652 if (this != &rhs)
2653 {
2654 this->clear();
2655
2656 typename etl::iset<TKey, TCompare>::iterator from = rhs.begin();
2657
2658 while (from != rhs.end())
2659 {
2660 typename etl::iset<TKey, TCompare>::iterator temp = from;
2661 ++temp;
2662
2663 this->insert(etl::move(*from));
2664 from = temp;
2665 }
2666 }
2667
2668 return *this;
2669 }
2670#endif
2671
2672 private:
2673
2675 etl::pool<typename etl::iset<TKey, TCompare>::Data_Node, MAX_SIZE> node_pool;
2676 };
2677
2678 template <typename TKey, const size_t MAX_SIZE_, typename TCompare>
2679 ETL_CONSTANT size_t set<TKey, MAX_SIZE_, TCompare>::MAX_SIZE;
2680
2681 //*************************************************************************
2683 //*************************************************************************
2684#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
2685 template <typename... T>
2686 set(T...) -> set<etl::nth_type_t<0, T...>, sizeof...(T)>;
2687#endif
2688
2689 //*************************************************************************
2691 //*************************************************************************
2692#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
2693 template <typename TKey, typename TCompare = etl::less<TKey>, typename... T>
2694 constexpr auto make_set(T&&... keys) -> etl::set<TKey, sizeof...(T), TCompare>
2695 {
2696 return {etl::forward<T>(keys)...};
2697 }
2698#endif
2699
2700 //***************************************************************************
2706 //***************************************************************************
2707 template <typename TKey, typename TCompare>
2709 {
2710 return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
2711 }
2712
2713 //***************************************************************************
2719 //***************************************************************************
2720 template <typename TKey, typename TCompare>
2722 {
2723 return !(lhs == rhs);
2724 }
2725
2726 //*************************************************************************
2732 //*************************************************************************
2733 template <typename TKey, typename TCompare>
2735 {
2736 return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), etl::iset<TKey, TCompare>::value_compare());
2737 }
2738
2739 //*************************************************************************
2745 //*************************************************************************
2746 template <typename TKey, typename TCompare>
2748 {
2749 return (rhs < lhs);
2750 }
2751
2752 //*************************************************************************
2759 //*************************************************************************
2760 template <typename TKey, typename TCompare>
2762 {
2763 return !(lhs > rhs);
2764 }
2765
2766 //*************************************************************************
2772 //*************************************************************************
2773 template <typename TKey, typename TCompare>
2775 {
2776 return !(lhs < rhs);
2777 }
2778} // namespace etl
2779
2780#include "private/minmax_pop.h"
2781
2782#endif
const_iterator
Definition set.h:677
iterator.
Definition set.h:573
A templated set implementation that uses a fixed size buffer.
Definition set.h:2550
set(const set &other)
Copy constructor.
Definition set.h:2567
set & operator=(const set &rhs)
Assignment operator.
Definition set.h:2634
set()
Default constructor.
Definition set.h:2558
set(TIterator first, TIterator last)
Definition set.h:2606
~set()
Destructor.
Definition set.h:2626
ETL_CONSTEXPR14 bool operator!=(const etl::bitset< Active_Bits, TElement > &lhs, const etl::bitset< Active_Bits, TElement > &rhs) ETL_NOEXCEPT
Definition bitset_new.h:2529
Definition exception.h:59
T * allocate()
Definition ipool.h:333
Definition ipool.h:109
size_type current_size
The number of the used nodes.
Definition set.h:448
set_base(size_type max_size_)
The constructor that is called from derived classes.
Definition set.h:224
~iset()
Destructor.
Definition set.h:2541
void balance_node(Node *&critical_node)
Balance the critical node at the position provided as needed.
Definition set.h:279
size_type count(key_parameter_t key) const
Definition set.h:958
bool node_comp(const Data_Node &node1, const Data_Node &node2) const
How to compare node elements.
Definition set.h:497
Node * find_limit_node(Node *position, const int8_t dir) const
Definition set.h:348
const_reverse_iterator crbegin() const
Gets the reverse beginning of the list.
Definition set.h:917
ETL_OR_STD::pair< iterator, bool > insert(const_reference value)
Definition set.h:1112
size_type capacity() const
Definition set.h:166
size_type size() const
Gets the size of the set.
Definition set.h:133
const_reverse_iterator crend() const
Gets the reverse end of the list.
Definition set.h:925
iterator erase(const_iterator first, const_iterator last)
Erases a range of elements.
Definition set.h:1058
const_iterator find(key_parameter_t key_value) const
Definition set.h:1092
iterator upper_bound(key_parameter_t key)
Definition set.h:1316
const_iterator begin() const
Gets the beginning of the set.
Definition set.h:845
size_type max_size() const
Gets the maximum possible size of the set.
Definition set.h:141
void detach_node(Node *&position, Node *&replacement)
Detach the node at the position provided.
Definition set.h:255
iterator end()
Gets the end of the set.
Definition set.h:853
const_iterator cbegin() const
Gets the beginning of the set.
Definition set.h:869
bool empty() const
Checks to see if the set is empty.
Definition set.h:149
ETL_OR_STD::pair< iterator, iterator > equal_range(key_parameter_t key)
Definition set.h:976
void insert(TIterator first, TIterator last)
Definition set.h:1261
value_compare value_comp() const
How to compare two value elements.
Definition set.h:1361
const_iterator end() const
Gets the end of the set.
Definition set.h:861
void rotate_3node(Node *&position, uint_least8_t dir, uint_least8_t third)
Rotate three nodes at the position provided the to balance the tree.
Definition set.h:411
iterator erase(iterator position)
Erases the value at the specified position.
Definition set.h:1015
void assign(TIterator first, TIterator last)
Definition set.h:939
key_compare key_comp() const
How to compare two key elements.
Definition set.h:1353
reverse_iterator rbegin()
Gets the reverse beginning of the list.
Definition set.h:885
const_reverse_iterator rbegin() const
Gets the reverse beginning of the list.
Definition set.h:893
bool full() const
Checks to see if the set is full.
Definition set.h:157
iterator lower_bound(key_parameter_t key)
Definition set.h:1276
reverse_iterator rend()
Gets the reverse end of the list.
Definition set.h:901
const_iterator upper_bound(key_parameter_t key) const
Definition set.h:1336
const_iterator lower_bound(key_parameter_t key) const
Definition set.h:1296
bool contains(const TKey &key) const
Check if the set contains the key.
Definition set.h:1369
void rotate_2node(Node *&position, uint_least8_t dir)
Rotate two nodes at the position provided the to balance the tree.
Definition set.h:381
~set_base()
The constructor that is called from derived classes.
Definition set.h:235
iset(etl::ipool &node_pool, size_t max_size_)
Constructor.
Definition set.h:1388
size_t size_type
The type used for determining the size of set.
Definition set.h:128
iterator begin()
Gets the beginning of the set.
Definition set.h:837
void initialise()
Initialise the set.
Definition set.h:1397
void attach_node(Node *&position, Node &node)
Attach the provided node to the position provided.
Definition set.h:240
size_t available() const
Definition set.h:175
void clear()
Clears the set.
Definition set.h:948
iterator erase(const_iterator position)
Erases the value at the specified position.
Definition set.h:1024
iterator find(key_parameter_t key_value)
Definition set.h:1073
const Node * find_limit_node(const Node *position, const int8_t dir) const
Definition set.h:365
iterator insert(const_iterator, const_reference value)
Definition set.h:1187
const_reverse_iterator rend() const
Gets the reverse end of the list.
Definition set.h:909
Node * root_node
The node that acts as the set root.
Definition set.h:450
const_iterator cend() const
Gets the end of the set.
Definition set.h:877
ETL_OR_STD::pair< const_iterator, const_iterator > equal_range(key_parameter_t key) const
Definition set.h:996
const size_type CAPACITY
The maximum size of the set.
Definition set.h:449
iset & operator=(const iset &rhs)
Assignment operator.
Definition set.h:796
etl::parameter_type< TKey >::type key_parameter_t
Defines the key value parameter type.
Definition set.h:492
Definition set.h:460
Definition set.h:125
Definition set.h:69
Definition set.h:83
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_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1133
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1147
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1093
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1106
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1120
Definition compare.h:51
The data node element in the set.
Definition set.h:482
iterator
Definition iterator.h:424
etl::conditional< etl::is_fundamental< T >::value||etl::is_pointer< T >::value, T, constT & >::type type
By default fundamental and pointer types are passed by value.
Definition parameter_type.h:46
The node element in the set.
Definition set.h:193
Node()
Constructor.
Definition set.h:197
void mark_as_leaf()
Marks the node as a leaf.
Definition set.h:208