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