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#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
1271 //*********************************************************************
1273 //*********************************************************************
1274 template <typename... Args>
1275 ETL_OR_STD::pair<iterator, bool> emplace(Args&&... args)
1276 {
1277 if (full())
1278 {
1279 // A duplicate key does not require a free node, so emplacing it is not
1280 // a capacity failure. Construct a temporary to obtain its key and only
1281 // emit set_full if the key is not already present. This keeps emplace
1282 // consistent with insert when the set is full.
1283 value_type temp_value(etl::forward<Args>(args)...);
1284 iterator position = find(temp_value);
1285
1286 if (position == end())
1287 {
1288 ETL_ASSERT_FAIL(ETL_ERROR(set_full));
1289 return ETL_OR_STD::make_pair(end(), false);
1290 }
1291
1292 return ETL_OR_STD::make_pair(position, false);
1293 }
1294
1295 // Construct the value
1296 Data_Node* p_node = allocate_data_node();
1297 ::new ((void*)&p_node->value) value_type(etl::forward<Args>(args)...);
1298 ETL_INCREMENT_DEBUG_COUNT;
1299
1300 // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1301 Node* inserted_node = insert_node(root_node, *p_node);
1302 bool inserted = inserted_node == p_node;
1303
1304 return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted);
1305 }
1306#else
1307 //*********************************************************************
1309 //*********************************************************************
1310 ETL_OR_STD::pair<iterator, bool> emplace(const_reference value)
1311 {
1312 return insert(value);
1313 }
1314
1315 //*********************************************************************
1317 //*********************************************************************
1318 template <typename T1>
1319 ETL_OR_STD::pair<iterator, bool> emplace(const T1& value1)
1320 {
1321 if (full())
1322 {
1323 // A duplicate key does not require a free node, so emplacing it is not
1324 // a capacity failure. Construct a temporary to obtain its key and only
1325 // emit set_full if the key is not already present. This keeps emplace
1326 // consistent with insert when the set is full.
1327 value_type temp_value(value1);
1328 iterator position = find(temp_value);
1329
1330 if (position == end())
1331 {
1332 ETL_ASSERT_FAIL(ETL_ERROR(set_full));
1333 return ETL_OR_STD::make_pair(end(), false);
1334 }
1335
1336 return ETL_OR_STD::make_pair(position, false);
1337 }
1338
1339 Data_Node* p_node = allocate_data_node();
1340 ::new ((void*)&p_node->value) value_type(value1);
1341 ETL_INCREMENT_DEBUG_COUNT;
1342
1343 Node* inserted_node = insert_node(root_node, *p_node);
1344 bool inserted = inserted_node == p_node;
1345
1346 return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted);
1347 }
1348#endif
1349
1350 //*********************************************************************
1355 //*********************************************************************
1357 {
1358 return iterator(*this, find_lower_node(root_node, key));
1359 }
1360
1361#if ETL_USING_CPP11
1362 //*********************************************************************
1363 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1364 iterator lower_bound(const K& key)
1365 {
1366 return iterator(*this, find_lower_node(root_node, key));
1367 }
1368#endif
1369
1370 //*********************************************************************
1375 //*********************************************************************
1377 {
1378 return const_iterator(*this, find_lower_node(root_node, key));
1379 }
1380
1381#if ETL_USING_CPP11
1382 //*********************************************************************
1383 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1384 const_iterator lower_bound(const K& key) const
1385 {
1386 return const_iterator(*this, find_lower_node(root_node, key));
1387 }
1388#endif
1389
1390 //*********************************************************************
1395 //*********************************************************************
1397 {
1398 return iterator(*this, find_upper_node(root_node, key));
1399 }
1400
1401#if ETL_USING_CPP11
1402 //*********************************************************************
1403 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1404 iterator upper_bound(const K& key)
1405 {
1406 return iterator(*this, find_upper_node(root_node, key));
1407 }
1408#endif
1409
1410 //*********************************************************************
1415 //*********************************************************************
1417 {
1418 return const_iterator(*this, find_upper_node(root_node, key));
1419 }
1420
1421#if ETL_USING_CPP11
1422 //*********************************************************************
1423 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1424 const_iterator upper_bound(const K& key) const
1425 {
1426 return const_iterator(*this, find_upper_node(root_node, key));
1427 }
1428#endif
1429
1430 //*************************************************************************
1432 //*************************************************************************
1433 key_compare key_comp() const
1434 {
1435 return compare;
1436 }
1437
1438 //*************************************************************************
1440 //*************************************************************************
1441 value_compare value_comp() const
1442 {
1443 return compare;
1444 }
1445
1446 //*************************************************************************
1448 //*************************************************************************
1449 bool contains(const TKey& key) const
1450 {
1451 return find(key) != end();
1452 }
1453
1454#if ETL_USING_CPP11
1455 //*************************************************************************
1456 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1457 bool contains(const K& k) const
1458 {
1459 return find(k) != end();
1460 }
1461#endif
1462
1463 protected:
1464
1465 //*************************************************************************
1467 //*************************************************************************
1468 iset(etl::ipool& node_pool, size_t max_size_)
1469 : etl::set_base(max_size_)
1470 , p_node_pool(&node_pool)
1471 {
1472 }
1473
1474 //*************************************************************************
1476 //*************************************************************************
1478 {
1479 const_iterator item = begin();
1480
1481 while (item != end())
1482 {
1483 item = erase(item);
1484 }
1485 }
1486
1487 private:
1488
1489 //*************************************************************************
1491 //*************************************************************************
1492 Data_Node& allocate_data_node(const_reference value)
1493 {
1494 Data_Node* node = allocate_data_node();
1495 ::new ((void*)&node->value) value_type(value);
1496 ETL_INCREMENT_DEBUG_COUNT;
1497 return *node;
1498 }
1499
1500#if ETL_USING_CPP11
1501 //*************************************************************************
1503 //*************************************************************************
1504 Data_Node& allocate_data_node(rvalue_reference value)
1505 {
1506 Data_Node* node = allocate_data_node();
1507 ::new ((void*)&node->value) value_type(etl::move(value));
1508 ETL_INCREMENT_DEBUG_COUNT;
1509 return *node;
1510 }
1511#endif
1512
1513 //*************************************************************************
1515 //*************************************************************************
1516 Data_Node* allocate_data_node()
1517 {
1518 Data_Node* (etl::ipool::*func)() = &etl::ipool::allocate<Data_Node>;
1519 return (p_node_pool->*func)();
1520 }
1521
1522 //*************************************************************************
1524 //*************************************************************************
1525 void destroy_data_node(Data_Node& node)
1526 {
1527 node.value.~value_type();
1528 p_node_pool->release(&node);
1529 ETL_DECREMENT_DEBUG_COUNT;
1530 }
1531
1532 //*************************************************************************
1534 //*************************************************************************
1535 Node* find_node(Node* position, key_parameter_t key)
1536 {
1537 Node* found = position;
1538 while (found)
1539 {
1540 // Downcast found to Data_Node class for comparison and other operations
1541 Data_Node& found_data_node = iset::data_cast(*found);
1542
1543 // Compare the node value to the current position value
1544 if (node_comp(key, found_data_node))
1545 {
1546 // Keep searching for the node on the left
1547 found = found->children[kLeft];
1548 }
1549 else if (node_comp(found_data_node, key))
1550 {
1551 // Keep searching for the node on the right
1552 found = found->children[kRight];
1553 }
1554 else
1555 {
1556 // Node that matches the key provided was found, exit loop
1557 break;
1558 }
1559 }
1560
1561 // Return the node found (might be ETL_NULLPTR)
1562 return found;
1563 }
1564
1565#if ETL_USING_CPP11
1566 //*************************************************************************
1567 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1568 Node* find_node(Node* position, const K& key)
1569 {
1570 Node* found = position;
1571 while (found)
1572 {
1573 // Downcast found to Data_Node class for comparison and other operations
1574 Data_Node& found_data_node = iset::data_cast(*found);
1575
1576 // Compare the node value to the current position value
1577 if (node_comp(key, found_data_node))
1578 {
1579 // Keep searching for the node on the left
1580 found = found->children[kLeft];
1581 }
1582 else if (node_comp(found_data_node, key))
1583 {
1584 // Keep searching for the node on the right
1585 found = found->children[kRight];
1586 }
1587 else
1588 {
1589 // Node that matches the key provided was found, exit loop
1590 break;
1591 }
1592 }
1593
1594 // Return the node found (might be ETL_NULLPTR)
1595 return found;
1596 }
1597#endif
1598
1599 //*************************************************************************
1601 //*************************************************************************
1602 const Node* find_node(const Node* position, key_parameter_t key) const
1603 {
1604 const Node* found = position;
1605 while (found)
1606 {
1607 // Downcast found to Data_Node class for comparison and other operations
1608 const Data_Node& found_data_node = iset::data_cast(*found);
1609
1610 // Compare the node value to the current position value
1611 if (node_comp(key, found_data_node))
1612 {
1613 // Keep searching for the node on the left
1614 found = found->children[kLeft];
1615 }
1616 else if (node_comp(found_data_node, key))
1617 {
1618 // Keep searching for the node on the right
1619 found = found->children[kRight];
1620 }
1621 else
1622 {
1623 // Node that matches the key provided was found, exit loop
1624 break;
1625 }
1626 }
1627
1628 // Return the node found (might be ETL_NULLPTR)
1629 return found;
1630 }
1631
1632#if ETL_USING_CPP11
1633 //*************************************************************************
1634 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1635 const Node* find_node(const Node* position, const K& key) const
1636 {
1637 const Node* found = position;
1638 while (found)
1639 {
1640 // Downcast found to Data_Node class for comparison and other operations
1641 const Data_Node& found_data_node = iset::data_cast(*found);
1642
1643 // Compare the node value to the current position value
1644 if (node_comp(key, found_data_node))
1645 {
1646 // Keep searching for the node on the left
1647 found = found->children[kLeft];
1648 }
1649 else if (node_comp(found_data_node, key))
1650 {
1651 // Keep searching for the node on the right
1652 found = found->children[kRight];
1653 }
1654 else
1655 {
1656 // Node that matches the key provided was found, exit loop
1657 break;
1658 }
1659 }
1660
1661 // Return the node found (might be ETL_NULLPTR)
1662 return found;
1663 }
1664#endif
1665
1666 //*************************************************************************
1668 //*************************************************************************
1669 Node*& find_node(Node*& position, const Node* node)
1670 {
1671 Node* found = position;
1672 while (found)
1673 {
1674 if (found->children[kLeft] == node)
1675 {
1676 return found->children[kLeft];
1677 }
1678 else if (found->children[kRight] == node)
1679 {
1680 return found->children[kRight];
1681 }
1682 else
1683 {
1684 // Downcast found to Data_Node class for comparison and other
1685 // operations
1686 Data_Node& found_data_node = iset::data_cast(*found);
1687 const Data_Node& data_node = iset::data_cast(*node);
1688
1689 // Compare the node value to the current position value
1690 if (node_comp(data_node, found_data_node))
1691 {
1692 // Keep searching for the node on the left
1693 found = found->children[kLeft];
1694 }
1695 else if (node_comp(found_data_node, data_node))
1696 {
1697 // Keep searching for the node on the right
1698 found = found->children[kRight];
1699 }
1700 else
1701 {
1702 // Return position provided (it matches the node)
1703 return position;
1704 }
1705 }
1706 }
1707
1708 // Return root node if nothing was found
1709 return root_node;
1710 }
1711
1712 //*************************************************************************
1715 //*************************************************************************
1716 Node* find_parent_node(Node* position, const Node* node)
1717 {
1718 // Default to no parent node found
1719 Node* found = ETL_NULLPTR;
1720
1721 // If the position provided is the same as the node then there is no
1722 // parent
1723 if (position && node && position != node)
1724 {
1725 while (position)
1726 {
1727 // Is this position not the parent of the node we are looking for?
1728 if (position->children[kLeft] != node && position->children[kRight] != node)
1729 {
1730 // Downcast node and position to Data_Node references for key
1731 // comparisons
1732 const Data_Node& node_data_node = iset::data_cast(*node);
1733 Data_Node& position_data_node = iset::data_cast(*position);
1734 // Compare the node value to the current position value
1735 if (node_comp(node_data_node, position_data_node))
1736 {
1737 // Keep looking for parent on the left
1738 position = position->children[kLeft];
1739 }
1740 else if (node_comp(position_data_node, node_data_node))
1741 {
1742 // Keep looking for parent on the right
1743 position = position->children[kRight];
1744 }
1745 }
1746 else
1747 {
1748 // Return the current position as the parent node found
1749 found = position;
1750
1751 // Parent node found, exit loop
1752 break;
1753 }
1754 }
1755 }
1756
1757 // Return the parent node found (might be ETL_NULLPTR)
1758 return found;
1759 }
1760
1761 //*************************************************************************
1764 //*************************************************************************
1765 const Node* find_parent_node(const Node* position, const Node* node) const
1766 {
1767 // Default to no parent node found
1768 const Node* found = ETL_NULLPTR;
1769
1770 // If the position provided is the same as the node then there is no
1771 // parent
1772 if (position && node && position != node)
1773 {
1774 while (position)
1775 {
1776 // Is this position not the parent of the node we are looking for?
1777 if (position->children[kLeft] != node && position->children[kRight] != node)
1778 {
1779 // Downcast node and position to Data_Node references for key
1780 // comparisons
1781 const Data_Node& node_data_node = iset::data_cast(*node);
1782 const Data_Node& position_data_node = iset::data_cast(*position);
1783 // Compare the node value to the current position value
1784 if (node_comp(node_data_node, position_data_node))
1785 {
1786 // Keep looking for parent on the left
1787 position = position->children[kLeft];
1788 }
1789 else if (node_comp(position_data_node, node_data_node))
1790 {
1791 // Keep looking for parent on the right
1792 position = position->children[kRight];
1793 }
1794 }
1795 else
1796 {
1797 // Return the current position as the parent node found
1798 found = position;
1799
1800 // Parent node found, exit loop
1801 break;
1802 }
1803 }
1804 }
1805
1806 // Return the parent node found (might be ETL_NULLPTR)
1807 return found;
1808 }
1809
1810 //*************************************************************************
1812 //*************************************************************************
1813 Node* find_lower_node(Node* position, key_parameter_t key) const
1814 {
1815 // Something at this position? keep going
1816 Node* lower_node = ETL_NULLPTR;
1817 while (position)
1818 {
1819 // Downcast lower node to Data_Node reference for key comparisons
1820 Data_Node& data_node = iset::data_cast(*position);
1821 // Compare the key value to the current lower node key value
1822 if (node_comp(key, data_node))
1823 {
1824 lower_node = position;
1825 if (position->children[kLeft])
1826 {
1827 position = position->children[kLeft];
1828 }
1829 else
1830 {
1831 // Found lowest node
1832 break;
1833 }
1834 }
1835 else if (node_comp(data_node, key))
1836 {
1837 position = position->children[kRight];
1838 }
1839 else
1840 {
1841 // Make note of current position, but keep looking to left for more
1842 lower_node = position;
1843 position = position->children[kLeft];
1844 }
1845 }
1846
1847 // Return the lower_node position found
1848 return lower_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_lower_node(Node* position, const K& key) const
1855 {
1856 // Something at this position? keep going
1857 Node* lower_node = ETL_NULLPTR;
1858 while (position)
1859 {
1860 // Downcast lower node to Data_Node reference for key comparisons
1861 Data_Node& data_node = iset::data_cast(*position);
1862 // Compare the key value to the current lower node key value
1863 if (node_comp(key, data_node))
1864 {
1865 lower_node = position;
1866 if (position->children[kLeft])
1867 {
1868 position = position->children[kLeft];
1869 }
1870 else
1871 {
1872 // Found lowest node
1873 break;
1874 }
1875 }
1876 else if (node_comp(data_node, key))
1877 {
1878 position = position->children[kRight];
1879 }
1880 else
1881 {
1882 // Make note of current position, but keep looking to left for more
1883 lower_node = position;
1884 position = position->children[kLeft];
1885 }
1886 }
1887
1888 // Return the lower_node position found
1889 return lower_node;
1890 }
1891#endif
1892
1893 //*************************************************************************
1895 //*************************************************************************
1896 Node* find_upper_node(Node* position, key_parameter_t key) const
1897 {
1898 // Keep track of parent of last upper node
1899 Node* upper_node = ETL_NULLPTR;
1900 // Start with position provided
1901 Node* node = position;
1902 while (node)
1903 {
1904 // Downcast position to Data_Node reference for key comparisons
1905 Data_Node& data_node = iset::data_cast(*node);
1906 // Compare the key value to the current upper node key value
1907 if (node_comp(key, data_node))
1908 {
1909 upper_node = node;
1910 node = node->children[kLeft];
1911 }
1912 else if (node_comp(data_node, key))
1913 {
1914 node = node->children[kRight];
1915 }
1916 else if (node->children[kRight])
1917 {
1918 upper_node = find_limit_node(node->children[kRight], kLeft);
1919 break;
1920 }
1921 else
1922 {
1923 break;
1924 }
1925 }
1926
1927 // Return the upper node position found (might be ETL_NULLPTR)
1928 return upper_node;
1929 }
1930
1931#if ETL_USING_CPP11
1932 //*************************************************************************
1933 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
1934 Node* find_upper_node(Node* position, const K& key) const
1935 {
1936 // Keep track of parent of last upper node
1937 Node* upper_node = ETL_NULLPTR;
1938 // Start with position provided
1939 Node* node = position;
1940 while (node)
1941 {
1942 // Downcast position to Data_Node reference for key comparisons
1943 Data_Node& data_node = iset::data_cast(*node);
1944 // Compare the key value to the current upper node key value
1945 if (node_comp(key, data_node))
1946 {
1947 upper_node = node;
1948 node = node->children[kLeft];
1949 }
1950 else if (node_comp(data_node, key))
1951 {
1952 node = node->children[kRight];
1953 }
1954 else if (node->children[kRight])
1955 {
1956 upper_node = find_limit_node(node->children[kRight], kLeft);
1957 break;
1958 }
1959 else
1960 {
1961 break;
1962 }
1963 }
1964
1965 // Return the upper node position found (might be ETL_NULLPTR)
1966 return upper_node;
1967 }
1968#endif
1969
1970 //*************************************************************************
1972 //*************************************************************************
1973 Node* insert_node(Node*& position, Data_Node& node)
1974 {
1975 // Find the location where the node belongs
1976 Node* found = position;
1977
1978 // Was position provided not empty? then find where the node belongs
1979 if (position)
1980 {
1981 // Find the critical parent node (default to ETL_NULLPTR)
1982 Node* critical_parent_node = ETL_NULLPTR;
1983 Node* critical_node = root_node;
1984
1985 while (found)
1986 {
1987 // Search for critical weight node (all nodes whose weight factor
1988 // is set to kNeither (balanced)
1989 if (kNeither != found->weight)
1990 {
1991 critical_node = found;
1992 }
1993
1994 // Downcast found to Data_Node class for comparison and other
1995 // operations
1996 Data_Node& found_data_node = iset::data_cast(*found);
1997
1998 // Is the node provided to the left of the current position?
1999 if (node_comp(node, found_data_node))
2000 {
2001 // Update direction taken to insert new node in parent node
2002 found->dir = kLeft;
2003 }
2004 // Is the node provided to the right of the current position?
2005 else if (node_comp(found_data_node, node))
2006 {
2007 // Update direction taken to insert new node in parent node
2008 found->dir = kRight;
2009 }
2010 else
2011 {
2012 // Update direction taken to insert new node in parent node
2013 found->dir = kNeither;
2014
2015 // Clear critical node value to skip weight step below
2016 critical_node = ETL_NULLPTR;
2017
2018 // Destroy the node provided (its a duplicate)
2019 destroy_data_node(node);
2020
2021 // Exit loop, duplicate node found
2022 break;
2023 }
2024
2025 // Is there a child of this parent node?
2026 if (found->children[found->dir])
2027 {
2028 // Will this node be the parent of the next critical node whose
2029 // weight factor is set to kNeither (balanced)?
2030 if (kNeither != found->children[found->dir]->weight)
2031 {
2032 critical_parent_node = found;
2033 }
2034
2035 // Keep looking for empty spot to insert new node
2036 found = found->children[found->dir];
2037 }
2038 else
2039 {
2040 // Attach node to right
2041 attach_node(found->children[found->dir], node);
2042
2043 // Return newly added node
2044 found = found->children[found->dir];
2045
2046 // Exit loop
2047 break;
2048 }
2049 }
2050
2051 // Was a critical node found that should be checked for balance?
2052 if (critical_node)
2053 {
2054 if (critical_parent_node == ETL_NULLPTR && critical_node == root_node)
2055 {
2057 }
2058 else if (critical_parent_node == ETL_NULLPTR && critical_node == position)
2059 {
2060 balance_node(position);
2061 }
2062 else
2063 {
2064 if (critical_parent_node != ETL_NULLPTR)
2065 {
2066 balance_node(critical_parent_node->children[critical_parent_node->dir]);
2067 }
2068 }
2069 }
2070 }
2071 else
2072 {
2073 // Attach node to current position
2074 attach_node(position, node);
2075
2076 // Return newly added node at current position
2077 found = position;
2078 }
2079
2080 // Return the node found (might be ETL_NULLPTR)
2081 return found;
2082 }
2083
2084 //*************************************************************************
2086 //*************************************************************************
2087 void next_node(Node*& position)
2088 {
2089 if (position)
2090 {
2091 // Is there a tree on the right? then find the minimum of that tree
2092 if (position->children[kRight])
2093 {
2094 // Return minimum node found
2095 position = find_limit_node(position->children[kRight], kLeft);
2096 }
2097 // Otherwise find the parent of this node
2098 else
2099 {
2100 // Start with current position as parent
2101 Node* parent = position;
2102 do {
2103 // Update current position as previous parent
2104 position = parent;
2105 // Find parent of current position
2106 parent = find_parent_node(root_node, position);
2107 // Repeat while previous position was on right side of parent tree
2108 } while (parent && parent->children[kRight] == position);
2109
2110 // Set parent node as the next position
2111 position = parent;
2112 }
2113 }
2114 }
2115
2116 //*************************************************************************
2118 //*************************************************************************
2119 void next_node(const Node*& position) const
2120 {
2121 if (position)
2122 {
2123 // Is there a tree on the right? then find the minimum of that tree
2124 if (position->children[kRight])
2125 {
2126 // Return minimum node found
2127 position = find_limit_node(position->children[kRight], kLeft);
2128 }
2129 // Otherwise find the parent of this node
2130 else
2131 {
2132 // Start with current position as parent
2133 const Node* parent = position;
2134 do {
2135 // Update current position as previous parent
2136 position = parent;
2137 // Find parent of current position
2138 parent = find_parent_node(root_node, position);
2139 // Repeat while previous position was on right side of parent tree
2140 } while (parent && parent->children[kRight] == position);
2141
2142 // Set parent node as the next position
2143 position = parent;
2144 }
2145 }
2146 }
2147
2148 //*************************************************************************
2150 //*************************************************************************
2151 void prev_node(Node*& position)
2152 {
2153 // If starting at the terminal end, the previous node is the maximum node
2154 // from the root
2155 if (!position)
2156 {
2157 position = find_limit_node(root_node, kRight);
2158 }
2159 else
2160 {
2161 // Is there a tree on the left? then find the maximum of that tree
2162 if (position->children[kLeft])
2163 {
2164 // Return maximum node found
2165 position = find_limit_node(position->children[kLeft], kRight);
2166 }
2167 // Otherwise find the parent of this node
2168 else
2169 {
2170 // Start with current position as parent
2171 Node* parent = position;
2172 do {
2173 // Update current position as previous parent
2174 position = parent;
2175 // Find parent of current position
2176 parent = find_parent_node(root_node, position);
2177 // Repeat while previous position was on left side of parent tree
2178 } while (parent && parent->children[kLeft] == position);
2179
2180 // Set parent node as the next position
2181 position = parent;
2182 }
2183 }
2184 }
2185
2186 //*************************************************************************
2188 //*************************************************************************
2189 void prev_node(const Node*& position) const
2190 {
2191 // If starting at the terminal end, the previous node is the maximum node
2192 // from the root
2193 if (!position)
2194 {
2195 position = find_limit_node(root_node, kRight);
2196 }
2197 else
2198 {
2199 // Is there a tree on the left? then find the maximum of that tree
2200 if (position->children[kLeft])
2201 {
2202 // Return maximum node found
2203 position = find_limit_node(position->children[kLeft], kRight);
2204 }
2205 // Otherwise find the parent of this node
2206 else
2207 {
2208 // Start with current position as parent
2209 const Node* parent = position;
2210 do {
2211 // Update current position as previous parent
2212 position = parent;
2213 // Find parent of current position
2214 parent = find_parent_node(root_node, position);
2215 // Repeat while previous position was on left side of parent tree
2216 } while (parent && parent->children[kLeft] == position);
2217
2218 // Set parent node as the next position
2219 position = parent;
2220 }
2221 }
2222 }
2223
2224 //*************************************************************************
2227 //*************************************************************************
2228 Node* remove_node(Node*& position, key_parameter_t key)
2229 {
2230 // Step 1: Find the target node that matches the key provided, the
2231 // replacement node (might be the same as target node), and the critical
2232 // node to start rebalancing the tree from (up to the replacement node)
2233 Node* found_parent = ETL_NULLPTR;
2234 Node* found = ETL_NULLPTR;
2235 Node* replace_parent = ETL_NULLPTR;
2236 Node* replace = position;
2237 Node* balance_parent = ETL_NULLPTR;
2238 Node* balance = root_node;
2239 while (replace)
2240 {
2241 // Downcast found to Data_Node class for comparison and other operations
2242 Data_Node& replace_data_node = iset::data_cast(*replace);
2243
2244 // Compare the key provided to the replace data node key
2245 if (node_comp(key, replace_data_node))
2246 {
2247 // Update the direction to the target/replace node
2248 replace->dir = kLeft;
2249 }
2250 else if (node_comp(replace_data_node, key))
2251 {
2252 // Update the direction to the target/replace node
2253 replace->dir = kRight;
2254 }
2255 else
2256 {
2257 // Update the direction to the replace node (target node found here)
2258 replace->dir = replace->children[kLeft] ? kLeft : kRight;
2259
2260 // Note the target node was found (and its parent)
2261 found_parent = replace_parent;
2262 found = replace;
2263 }
2264 // Replacement node found if its missing a child in the replace->dir
2265 // value set above
2266 if (replace->children[replace->dir] == ETL_NULLPTR)
2267 {
2268 // Exit loop once replace node is found (target might not have been)
2269 break;
2270 }
2271
2272 // If replacement node weight is kNeither or we are taking the shorter
2273 // path of replacement node and our sibling (on longer path) is
2274 // balanced then we need to update the balance node to match this
2275 // replacement node but all our ancestors will not require rebalancing
2276 if ((replace->weight == kNeither) || (replace->weight == (1 - replace->dir) && replace->children[1 - replace->dir]->weight == kNeither))
2277 {
2278 // Update balance node (and its parent) to replacement node
2279 balance_parent = replace_parent;
2280 balance = replace;
2281 }
2282
2283 // Keep searching for the replacement node
2284 replace_parent = replace;
2285 replace = replace->children[replace->dir];
2286 }
2287
2288 // If target node was found, proceed with rebalancing and replacement
2289 if (found)
2290 {
2291 // Step 2: Update weights from critical node to replacement parent node
2292 while (balance)
2293 {
2294 if (balance->children[balance->dir] == ETL_NULLPTR)
2295 {
2296 break;
2297 }
2298
2299 if (balance->weight == kNeither)
2300 {
2301 balance->weight = 1 - balance->dir;
2302 }
2303 else if (balance->weight == balance->dir)
2304 {
2305 balance->weight = kNeither;
2306 }
2307 else
2308 {
2309 int weight = balance->children[1 - balance->dir]->weight;
2310 // Perform a 3 node rotation if weight is same as balance->dir
2311 if (weight == balance->dir)
2312 {
2313 // Is the root node being rebalanced (no parent)
2314 if (balance_parent == ETL_NULLPTR)
2315 {
2316 rotate_3node(root_node, 1 - balance->dir, balance->children[1 - balance->dir]->children[balance->dir]->weight);
2317 }
2318 else
2319 {
2320 rotate_3node(balance_parent->children[balance_parent->dir], 1 - balance->dir,
2321 balance->children[1 - balance->dir]->children[balance->dir]->weight);
2322 }
2323 }
2324 // Already balanced, rebalance and make it heavy in opposite
2325 // direction of the node being removed
2326 else if (weight == kNeither)
2327 {
2328 // Is the root node being rebalanced (no parent)
2329 if (balance_parent == ETL_NULLPTR)
2330 {
2331 rotate_2node(root_node, 1 - balance->dir);
2332 root_node->weight = balance->dir;
2333 }
2334 else
2335 {
2336 rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2337 balance_parent->children[balance_parent->dir]->weight = balance->dir;
2338 }
2339 // Update balance node weight in opposite direction of node
2340 // removed
2341 balance->weight = 1 - balance->dir;
2342 }
2343 // Rebalance and leave it balanced
2344 else
2345 {
2346 // Is the root node being rebalanced (no parent)
2347 if (balance_parent == ETL_NULLPTR)
2348 {
2349 rotate_2node(root_node, 1 - balance->dir);
2350 }
2351 else
2352 {
2353 rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2354 }
2355 }
2356
2357 // Is balance node the same as the target node found? then update
2358 // its parent after the rotation performed above
2359 if (balance == found)
2360 {
2361 if (balance_parent)
2362 {
2363 found_parent = balance_parent->children[balance_parent->dir];
2364 // Update dir since it is likely stale
2365 found_parent->dir = found_parent->children[kLeft] == found ? kLeft : kRight;
2366 }
2367 else
2368 {
2369 found_parent = root_node;
2370 root_node->dir = root_node->children[kLeft] == found ? kLeft : kRight;
2371 }
2372 }
2373 }
2374
2375 // Next balance node to consider
2376 balance_parent = balance;
2377 balance = balance->children[balance->dir];
2378 } // while(balance)
2379
2380 // Step 3: Swap found node with replacement node
2381 if (found_parent)
2382 {
2383 // Handle traditional case
2384 detach_node(found_parent->children[found_parent->dir], replace_parent->children[replace_parent->dir]);
2385 }
2386 // Handle root node removal
2387 else
2388 {
2389 // Valid replacement node for root node being removed?
2390 if (replace_parent)
2391 {
2392 detach_node(root_node, replace_parent->children[replace_parent->dir]);
2393 }
2394 else
2395 {
2396 // Target node and replacement node are both root node
2398 }
2399 }
2400
2401 // Downcast found into data node
2402 Data_Node& found_data_node = iset::data_cast(*found);
2403
2404 // One less.
2405 --current_size;
2406
2407 // Destroy the node removed
2408 destroy_data_node(found_data_node);
2409 } // if(found)
2410
2411 // Return node found (might be ETL_NULLPTR)
2412 return found;
2413 }
2414
2415#if ETL_USING_CPP11
2416 //*************************************************************************
2417 template <typename K, typename KC = TCompare, etl::enable_if_t<comparator_is_transparent<KC>::value, int> = 0>
2418 Node* remove_node(Node*& position, const K& key)
2419 {
2420 // Step 1: Find the target node that matches the key provided, the
2421 // replacement node (might be the same as target node), and the critical
2422 // node to start rebalancing the tree from (up to the replacement node)
2423 Node* found_parent = ETL_NULLPTR;
2424 Node* found = ETL_NULLPTR;
2425 Node* replace_parent = ETL_NULLPTR;
2426 Node* replace = position;
2427 Node* balance_parent = ETL_NULLPTR;
2428 Node* balance = root_node;
2429 while (replace)
2430 {
2431 // Downcast found to Data_Node class for comparison and other operations
2432 Data_Node& replace_data_node = iset::data_cast(*replace);
2433
2434 // Compare the key provided to the replace data node key
2435 if (node_comp(key, replace_data_node))
2436 {
2437 // Update the direction to the target/replace node
2438 replace->dir = kLeft;
2439 }
2440 else if (node_comp(replace_data_node, key))
2441 {
2442 // Update the direction to the target/replace node
2443 replace->dir = kRight;
2444 }
2445 else
2446 {
2447 // Update the direction to the replace node (target node found here)
2448 replace->dir = replace->children[kLeft] ? kLeft : kRight;
2449
2450 // Note the target node was found (and its parent)
2451 found_parent = replace_parent;
2452 found = replace;
2453 }
2454 // Replacement node found if its missing a child in the replace->dir
2455 // value set above
2456 if (replace->children[replace->dir] == ETL_NULLPTR)
2457 {
2458 // Exit loop once replace node is found (target might not have been)
2459 break;
2460 }
2461
2462 // If replacement node weight is kNeither or we are taking the shorter
2463 // path of replacement node and our sibling (on longer path) is
2464 // balanced then we need to update the balance node to match this
2465 // replacement node but all our ancestors will not require rebalancing
2466 if ((replace->weight == kNeither) || (replace->weight == (1 - replace->dir) && replace->children[1 - replace->dir]->weight == kNeither))
2467 {
2468 // Update balance node (and its parent) to replacement node
2469 balance_parent = replace_parent;
2470 balance = replace;
2471 }
2472
2473 // Keep searching for the replacement node
2474 replace_parent = replace;
2475 replace = replace->children[replace->dir];
2476 }
2477
2478 // If target node was found, proceed with rebalancing and replacement
2479 if (found)
2480 {
2481 // Step 2: Update weights from critical node to replacement parent node
2482 while (balance)
2483 {
2484 if (balance->children[balance->dir] == ETL_NULLPTR)
2485 {
2486 break;
2487 }
2488
2489 if (balance->weight == kNeither)
2490 {
2491 balance->weight = 1 - balance->dir;
2492 }
2493 else if (balance->weight == balance->dir)
2494 {
2495 balance->weight = kNeither;
2496 }
2497 else
2498 {
2499 int weight = balance->children[1 - balance->dir]->weight;
2500 // Perform a 3 node rotation if weight is same as balance->dir
2501 if (weight == balance->dir)
2502 {
2503 // Is the root node being rebalanced (no parent)
2504 if (balance_parent == ETL_NULLPTR)
2505 {
2506 rotate_3node(root_node, 1 - balance->dir, balance->children[1 - balance->dir]->children[balance->dir]->weight);
2507 }
2508 else
2509 {
2510 rotate_3node(balance_parent->children[balance_parent->dir], 1 - balance->dir,
2511 balance->children[1 - balance->dir]->children[balance->dir]->weight);
2512 }
2513 }
2514 // Already balanced, rebalance and make it heavy in opposite
2515 // direction of the node being removed
2516 else if (weight == kNeither)
2517 {
2518 // Is the root node being rebalanced (no parent)
2519 if (balance_parent == ETL_NULLPTR)
2520 {
2521 rotate_2node(root_node, 1 - balance->dir);
2522 root_node->weight = balance->dir;
2523 }
2524 else
2525 {
2526 rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2527 balance_parent->children[balance_parent->dir]->weight = balance->dir;
2528 }
2529 // Update balance node weight in opposite direction of node
2530 // removed
2531 balance->weight = 1 - balance->dir;
2532 }
2533 // Rebalance and leave it balanced
2534 else
2535 {
2536 // Is the root node being rebalanced (no parent)
2537 if (balance_parent == ETL_NULLPTR)
2538 {
2539 rotate_2node(root_node, 1 - balance->dir);
2540 }
2541 else
2542 {
2543 rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2544 }
2545 }
2546
2547 // Is balance node the same as the target node found? then update
2548 // its parent after the rotation performed above
2549 if (balance == found)
2550 {
2551 if (balance_parent)
2552 {
2553 found_parent = balance_parent->children[balance_parent->dir];
2554 // Update dir since it is likely stale
2555 found_parent->dir = found_parent->children[kLeft] == found ? kLeft : kRight;
2556 }
2557 else
2558 {
2559 found_parent = root_node;
2560 root_node->dir = root_node->children[kLeft] == found ? kLeft : kRight;
2561 }
2562 }
2563 }
2564
2565 // Next balance node to consider
2566 balance_parent = balance;
2567 balance = balance->children[balance->dir];
2568 } // while(balance)
2569
2570 // Step 3: Swap found node with replacement node
2571 if (found_parent)
2572 {
2573 // Handle traditional case
2574 detach_node(found_parent->children[found_parent->dir], replace_parent->children[replace_parent->dir]);
2575 }
2576 // Handle root node removal
2577 else
2578 {
2579 // Valid replacement node for root node being removed?
2580 if (replace_parent)
2581 {
2582 detach_node(root_node, replace_parent->children[replace_parent->dir]);
2583 }
2584 else
2585 {
2586 // Target node and replacement node are both root node
2588 }
2589 }
2590
2591 // Downcast found into data node
2592 Data_Node& found_data_node = iset::data_cast(*found);
2593
2594 // One less.
2595 --current_size;
2596
2597 // Destroy the node removed
2598 destroy_data_node(found_data_node);
2599 } // if(found)
2600
2601 // Return node found (might be ETL_NULLPTR)
2602 return found;
2603 }
2604#endif
2605
2606 // Disable copy construction.
2607 iset(const iset&);
2608
2609 //*************************************************************************
2611 //*************************************************************************
2612#if defined(ETL_POLYMORPHIC_SET) || defined(ETL_POLYMORPHIC_CONTAINERS)
2613
2614 public:
2615
2616 virtual ~iset() {}
2617#else
2618
2619 protected:
2620
2622#endif
2623 };
2624
2625 //*************************************************************************
2627 //*************************************************************************
2628 template <typename TKey, const size_t MAX_SIZE_, typename TCompare = etl::less<TKey> >
2629 class set : public etl::iset<TKey, TCompare>
2630 {
2631 public:
2632
2633 static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
2634
2635 //*************************************************************************
2637 //*************************************************************************
2639 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2640 {
2641 this->initialise();
2642 }
2643
2644 //*************************************************************************
2646 //*************************************************************************
2647 set(const set& other)
2648 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2649 {
2650 if (this != &other)
2651 {
2652 this->assign(other.cbegin(), other.cend());
2653 }
2654 }
2655
2656#if ETL_USING_CPP11
2657 //*************************************************************************
2659 //*************************************************************************
2660 set(set&& other)
2661 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2662 {
2663 if (this != &other)
2664 {
2665 typename etl::iset<TKey, TCompare>::iterator from = other.begin();
2666
2667 while (from != other.end())
2668 {
2669 typename etl::iset<TKey, TCompare>::iterator temp = from;
2670 ++temp;
2671
2672 this->insert(etl::move(*from));
2673 from = temp;
2674 }
2675 }
2676 }
2677#endif
2678
2679 //*************************************************************************
2684 //*************************************************************************
2685 template <typename TIterator>
2686 set(TIterator first, TIterator last)
2687 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2688 {
2689 this->assign(first, last);
2690 }
2691
2692#if ETL_HAS_INITIALIZER_LIST
2693 //*************************************************************************
2695 //*************************************************************************
2696 set(std::initializer_list<typename etl::iset<TKey, TCompare>::value_type> init)
2697 : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2698 {
2699 this->assign(init.begin(), init.end());
2700 }
2701#endif
2702
2703 //*************************************************************************
2705 //*************************************************************************
2707 {
2708 this->initialise();
2709 }
2710
2711 //*************************************************************************
2713 //*************************************************************************
2714 set& operator=(const set& rhs)
2715 {
2716 // Skip if doing self assignment
2717 if (this != &rhs)
2718 {
2719 this->assign(rhs.cbegin(), rhs.cend());
2720 }
2721
2722 return *this;
2723 }
2724
2725#if ETL_USING_CPP11
2726 //*************************************************************************
2728 //*************************************************************************
2729 set& operator=(set&& rhs)
2730 {
2731 // Skip if doing self assignment
2732 if (this != &rhs)
2733 {
2734 this->clear();
2735
2736 typename etl::iset<TKey, TCompare>::iterator from = rhs.begin();
2737
2738 while (from != rhs.end())
2739 {
2740 typename etl::iset<TKey, TCompare>::iterator temp = from;
2741 ++temp;
2742
2743 this->insert(etl::move(*from));
2744 from = temp;
2745 }
2746 }
2747
2748 return *this;
2749 }
2750#endif
2751
2752 private:
2753
2755 etl::pool<typename etl::iset<TKey, TCompare>::Data_Node, MAX_SIZE> node_pool;
2756 };
2757
2758 template <typename TKey, const size_t MAX_SIZE_, typename TCompare>
2759 ETL_CONSTANT size_t set<TKey, MAX_SIZE_, TCompare>::MAX_SIZE;
2760
2761 //*************************************************************************
2763 //*************************************************************************
2764#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
2765 template <typename... T>
2766 set(T...) -> set<etl::nth_type_t<0, T...>, sizeof...(T)>;
2767#endif
2768
2769 //*************************************************************************
2771 //*************************************************************************
2772#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
2773 template <typename TKey, typename TCompare = etl::less<TKey>, typename... T>
2774 constexpr auto make_set(T&&... keys) -> etl::set<TKey, sizeof...(T), TCompare>
2775 {
2776 return {etl::forward<T>(keys)...};
2777 }
2778#endif
2779
2780 //***************************************************************************
2786 //***************************************************************************
2787 template <typename TKey, typename TCompare>
2789 {
2790 return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
2791 }
2792
2793 //***************************************************************************
2799 //***************************************************************************
2800 template <typename TKey, typename TCompare>
2802 {
2803 return !(lhs == rhs);
2804 }
2805
2806 //*************************************************************************
2812 //*************************************************************************
2813 template <typename TKey, typename TCompare>
2815 {
2816 return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), etl::iset<TKey, TCompare>::value_compare());
2817 }
2818
2819 //*************************************************************************
2825 //*************************************************************************
2826 template <typename TKey, typename TCompare>
2828 {
2829 return (rhs < lhs);
2830 }
2831
2832 //*************************************************************************
2839 //*************************************************************************
2840 template <typename TKey, typename TCompare>
2842 {
2843 return !(lhs > rhs);
2844 }
2845
2846 //*************************************************************************
2852 //*************************************************************************
2853 template <typename TKey, typename TCompare>
2855 {
2856 return !(lhs < rhs);
2857 }
2858} // namespace etl
2859
2860#include "private/minmax_pop.h"
2861
2862#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:2630
set(const set &other)
Copy constructor.
Definition set.h:2647
set & operator=(const set &rhs)
Assignment operator.
Definition set.h:2714
set()
Default constructor.
Definition set.h:2638
set(TIterator first, TIterator last)
Definition set.h:2686
~set()
Destructor.
Definition set.h:2706
Definition exception.h:59
T * allocate()
Definition ipool.h:334
Definition ipool.h:110
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:2621
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:1396
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:1441
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:1433
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:1356
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:1416
const_iterator lower_bound(key_parameter_t key) const
Definition set.h:1376
bool contains(const TKey &key) const
Check if the set contains the key.
Definition set.h:1449
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
ETL_OR_STD::pair< iterator, bool > emplace(const T1 &value1)
Emplaces a value to the set.
Definition set.h:1319
iset(etl::ipool &node_pool, size_t max_size_)
Constructor.
Definition set.h:1468
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:1477
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
ETL_OR_STD::pair< iterator, bool > emplace(const_reference value)
Emplaces a value to the set.
Definition set.h:1310
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
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:1078
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1130
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1144
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1090
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1103
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1117
Definition compare.h:51
The data node element in the set.
Definition set.h:482
iterator
Definition iterator.h:482
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
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937