Embedded Template Library  1.0
set.h
Go to the documentation of this file.
1 
3 /******************************************************************************
4 The MIT License(MIT)
5 
6 Embedded Template Library.
7 https://github.com/ETLCPP/etl
8 https://www.etlcpp.com
9 
10 Copyright(c) 2014 jwellbelove, rlindeman
11 
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files(the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions :
18 
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21 
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29 ******************************************************************************/
30 
31 #ifndef ETL_SET_INCLUDED
32 #define ETL_SET_INCLUDED
33 
34 #include <stddef.h>
35 
36 #include "platform.h"
37 #include "container.h"
38 #include "pool.h"
39 #include "exception.h"
40 #include "error_handler.h"
41 #include "debug_count.h"
42 #include "nullptr.h"
43 #include "type_traits.h"
44 #include "parameter_type.h"
45 #include "iterator.h"
46 #include "utility.h"
47 #include "algorithm.h"
48 #include "iterator.h"
49 #include "functional.h"
50 #include "placement_new.h"
51 
52 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
53  #include <initializer_list>
54 #endif
55 
56 #include "private/minmax_push.h"
57 
58 #undef ETL_FILE
59 #define ETL_FILE "14"
60 
61 //*****************************************************************************
65 //*****************************************************************************
66 
67 namespace etl
68 {
69  //***************************************************************************
72  //***************************************************************************
74  {
75  public:
76 
77  set_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
78  : etl::exception(reason_, file_name_, line_number_)
79  {
80  }
81  };
82 
83  //***************************************************************************
86  //***************************************************************************
88  {
89  public:
90 
91  set_full(string_type file_name_, numeric_type line_number_)
92  : etl::set_exception(ETL_ERROR_TEXT("set:full", ETL_FILE"A"), file_name_, line_number_)
93  {
94  }
95  };
96 
97  //***************************************************************************
100  //***************************************************************************
102  {
103  public:
104 
105  set_out_of_bounds(string_type file_name_, numeric_type line_number_)
106  : etl::set_exception(ETL_ERROR_TEXT("set:bounds", ETL_FILE"B"), file_name_, line_number_)
107  {
108  }
109  };
110 
111  //***************************************************************************
114  //***************************************************************************
116  {
117  public:
118 
119  set_iterator(string_type file_name_, numeric_type line_number_)
120  : etl::set_exception(ETL_ERROR_TEXT("set:iterator problem", ETL_FILE"C"), file_name_, line_number_)
121  {
122  }
123  };
124 
125  //***************************************************************************
128  //***************************************************************************
129  class set_base
130  {
131  public:
132 
133  typedef size_t size_type;
134 
135  //*************************************************************************
137  //*************************************************************************
138  size_type size() const
139  {
140  return current_size;
141  }
142 
143  //*************************************************************************
145  //*************************************************************************
147  {
148  return CAPACITY;
149  }
150 
151  //*************************************************************************
153  //*************************************************************************
154  bool empty() const
155  {
156  return current_size == 0;
157  }
158 
159  //*************************************************************************
161  //*************************************************************************
162  bool full() const
163  {
164  return current_size == CAPACITY;
165  }
166 
167  //*************************************************************************
170  //*************************************************************************
172  {
173  return CAPACITY;
174  }
175 
176  //*************************************************************************
179  //*************************************************************************
180  size_t available() const
181  {
182  return max_size() - size();
183  }
184 
185  protected:
186 
187  enum
188  {
189  kLeft = 0,
190  kRight = 1,
191  kNeither = 2
192  };
193 
194  //*************************************************************************
196  //*************************************************************************
197  struct Node
198  {
199  //***********************************************************************
201  //***********************************************************************
202  Node() :
203  weight(kNeither),
204  dir(kNeither)
205  {
206  }
207 
208  //***********************************************************************
210  //***********************************************************************
212  {
213  weight = kNeither;
214  dir = kNeither;
215  children[0] = ETL_NULLPTR;
216  children[1] = ETL_NULLPTR;
217  }
218 
219  Node* children[2];
220  uint_least8_t weight;
221  uint_least8_t dir;
222  };
223 
224  //*************************************************************************
226  //*************************************************************************
227  set_base(size_type max_size_)
228  : current_size(0)
229  , CAPACITY(max_size_)
230  , root_node(ETL_NULLPTR)
231 
232  {
233  }
234 
235  //*************************************************************************
237  //*************************************************************************
239  {
240  }
241 
242  //*************************************************************************
244  //*************************************************************************
245  void attach_node(Node*& position, Node& node)
246  {
247  // Mark new node as leaf on attach to tree at position provided
248  node.mark_as_leaf();
249 
250  // Add the node here
251  position = &node;
252 
253  // One more.
254  ++current_size;
255  }
256 
257  //*************************************************************************
259  //*************************************************************************
260  void detach_node(Node*& position, Node*& replacement)
261  {
262  // Make temporary copy of actual nodes involved because we might lose
263  // their references in the process (e.g. position is the same as
264  // replacement or replacement is a child of position)
265  Node* detached = position;
266  Node* swap = replacement;
267 
268  // Update current position to point to swap (replacement) node first
269  position = swap;
270 
271  // Update replacement node to point to child in opposite direction
272  // otherwise we might lose the other child of the swap node
273  replacement = swap->children[1 - swap->dir];
274 
275  // Point swap node to detached node's children and weight
276  swap->children[kLeft] = detached->children[kLeft];
277  swap->children[kRight] = detached->children[kRight];
278  swap->weight = detached->weight;
279  }
280 
281  //*************************************************************************
283  //*************************************************************************
284  void balance_node(Node*& critical_node)
285  {
286  // Step 1: Update weights for all children of the critical node up to the
287  // newly inserted node. This step is costly (in terms of traversing nodes
288  // multiple times during insertion) but doesn't require as much recursion
289  Node* weight_node = critical_node->children[critical_node->dir];
290  while (weight_node)
291  {
292  // Keep going until we reach a terminal node (dir == kNeither)
293  if (uint_least8_t(kNeither) != weight_node->dir)
294  {
295  // Does this insert balance the previous weight factor value?
296  if (weight_node->weight == 1 - weight_node->dir)
297  {
298  weight_node->weight = uint_least8_t(kNeither);
299  }
300  else
301  {
302  weight_node->weight = weight_node->dir;
303  }
304 
305  // Update weight factor node to point to next node
306  weight_node = weight_node->children[weight_node->dir];
307  }
308  else
309  {
310  // Stop loop, terminal node found
311  break;
312  }
313  } // while(weight_node)
314 
315  // Step 2: Update weight for critical_node or rotate tree to balance node
316  if (uint_least8_t(kNeither) == critical_node->weight)
317  {
318  critical_node->weight = critical_node->dir;
319  }
320  // If direction is different than weight, then it will now be balanced
321  else if (critical_node->dir != critical_node->weight)
322  {
323  critical_node->weight = uint_least8_t(kNeither);
324  }
325  // Rotate is required to balance the tree at the critical node
326  else
327  {
328  // If critical node matches child node direction then perform a two
329  // node rotate in the direction of the critical node
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  rotate_3node(critical_node, critical_node->dir,
339  critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
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 different than dir
428  position->children[dir]->weight = third != uint_least8_t(kNeither) && third != dir ? dir : uint_least8_t(kNeither);
429 
430  // Detach new root from its tree (replace with new roots child)
431  position->children[dir]->children[1 - dir] =
432  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 
455  //***************************************************************************
458  //***************************************************************************
459  template <typename TKey, typename TCompare = etl::less<TKey> >
460  class iset : public etl::set_base
461  {
462  public:
463 
464  typedef TKey key_type;
465  typedef TKey value_type;
466  typedef TCompare key_compare;
467  typedef TCompare value_compare;
468  typedef value_type& reference;
469  typedef const value_type& const_reference;
470 #if ETL_CPP11_SUPPORTED
471  typedef value_type&& rvalue_reference;
472 #endif
473  typedef value_type* pointer;
474  typedef const value_type* const_pointer;
475  typedef size_t size_type;
476 
477  protected:
478 
479  //*************************************************************************
481  //*************************************************************************
482  struct Data_Node : public Node
483  {
484  explicit Data_Node(value_type value_)
485  : value(value_)
486  {
487  }
488 
489  value_type value;
490  };
491 
494 
495  //*************************************************************************
497  //*************************************************************************
498  bool node_comp(const Data_Node& node1, const Data_Node& node2) const
499  {
500  return compare(node1.value, node2.value);
501  }
502 
503  bool node_comp(const Data_Node& node, key_parameter_t key) const
504  {
505  return compare(node.value, key);
506  }
507 
508  bool node_comp(key_parameter_t key, const Data_Node& node) const
509 
510  {
511  return compare(key, node.value);
512  }
513 
514  private:
515 
517  etl::ipool* p_node_pool;
518 
519  key_compare compare;
520 
521  //*************************************************************************
523  //*************************************************************************
524  static Data_Node* data_cast(Node* p_node)
525  {
526  return static_cast<Data_Node*>(p_node);
527  }
528 
529  //*************************************************************************
531  //*************************************************************************
532  static Data_Node& data_cast(Node& node)
533  {
534  return static_cast<Data_Node&>(node);
535  }
536 
537  //*************************************************************************
539  //*************************************************************************
540  static const Data_Node* data_cast(const Node* p_node)
541  {
542  return static_cast<const Data_Node*>(p_node);
543  }
544 
545  //*************************************************************************
547  //*************************************************************************
548  static const Data_Node& data_cast(const Node& node)
549  {
550  return static_cast<const Data_Node&>(node);
551  }
552 
553  public:
554  //*************************************************************************
556  //*************************************************************************
557  class iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, value_type>
558  {
559  public:
560 
561  friend class iset;
562  friend class const_iterator;
563 
564  iterator()
565  : p_set(ETL_NULLPTR)
566  , p_node(ETL_NULLPTR)
567  {
568  }
569 
570  iterator(iset& set)
571  : p_set(&set)
572  , p_node(ETL_NULLPTR)
573  {
574  }
575 
576  iterator(iset& set, Node* node)
577  : p_set(&set)
578  , p_node(node)
579  {
580  }
581 
582  iterator(const iterator& other)
583  : p_set(other.p_set)
584  , p_node(other.p_node)
585  {
586  }
587 
588  ~iterator()
589  {
590  }
591 
592  iterator& operator ++()
593  {
594  p_set->next_node(p_node);
595  return *this;
596  }
597 
598  iterator operator ++(int)
599  {
600  iterator temp(*this);
601  p_set->next_node(p_node);
602  return temp;
603  }
604 
605  iterator& operator --()
606  {
607  p_set->prev_node(p_node);
608  return *this;
609  }
610 
611  iterator operator --(int)
612  {
613  iterator temp(*this);
614  p_set->prev_node(p_node);
615  return temp;
616  }
617 
618  iterator& operator =(const iterator& other)
619  {
620  p_set = other.p_set;
621  p_node = other.p_node;
622  return *this;
623  }
624 
625  reference operator *()
626  {
627  return iset::data_cast(p_node)->value;
628  }
629 
630  const_reference operator *() const
631  {
632  return iset::data_cast(p_node)->value;
633  }
634 
635  pointer operator &()
636  {
637  return &(iset::data_cast(p_node)->value);
638  }
639 
640  const_pointer operator &() const
641  {
642  return &(iset::data_cast(p_node)->value);
643  }
644 
645  pointer operator ->()
646  {
647  return &(iset::data_cast(p_node)->value);
648  }
649 
650  const_pointer operator ->() const
651  {
652  return &(iset::data_cast(p_node)->value);
653  }
654 
655  friend bool operator == (const iterator& lhs, const iterator& rhs)
656  {
657  return lhs.p_set == rhs.p_set && lhs.p_node == rhs.p_node;
658  }
659 
660  friend bool operator != (const iterator& lhs, const iterator& rhs)
661  {
662  return !(lhs == rhs);
663  }
664 
665  private:
666 
667  // Pointer to set associated with this iterator
668  iset* p_set;
669 
670  // Pointer to the current node for this iterator
671  Node* p_node;
672  };
673  friend class iterator;
674 
675  //*************************************************************************
677  //*************************************************************************
678  class const_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const value_type>
679  {
680  public:
681 
682  friend class iset;
683 
685  : p_set(ETL_NULLPTR)
686  , p_node(ETL_NULLPTR)
687  {
688  }
689 
690  const_iterator(const iset& set)
691  : p_set(&set)
692  , p_node(ETL_NULLPTR)
693  {
694  }
695 
696  const_iterator(const iset& set, const Node* node)
697  : p_set(&set)
698  , p_node(node)
699  {
700  }
701 
702  const_iterator(const typename iset::iterator& other)
703  : p_set(other.p_set)
704  , p_node(other.p_node)
705  {
706  }
707 
708  const_iterator(const const_iterator& other)
709  : p_set(other.p_set)
710  , p_node(other.p_node)
711  {
712  }
713 
714  ~const_iterator()
715  {
716  }
717 
718  const_iterator& operator ++()
719  {
720  p_set->next_node(p_node);
721  return *this;
722  }
723 
724  const_iterator operator ++(int)
725  {
726  const_iterator temp(*this);
727  p_set->next_node(p_node);
728  return temp;
729  }
730 
731  const_iterator& operator --()
732  {
733  p_set->prev_node(p_node);
734  return *this;
735  }
736 
737  const_iterator operator --(int)
738  {
739  const_iterator temp(*this);
740  p_set->prev_node(p_node);
741  return temp;
742  }
743 
744  const_iterator& operator =(const const_iterator& other)
745  {
746  p_set = other.p_set;
747  p_node = other.p_node;
748  return *this;
749  }
750 
751  const_reference operator *() const
752  {
753  return iset::data_cast(p_node)->value;
754  }
755 
756  const_pointer operator &() const
757  {
758  return iset::data_cast(p_node)->value;
759  }
760 
761  const_pointer operator ->() const
762  {
763  return &(iset::data_cast(p_node)->value);
764  }
765 
766  friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
767  {
768  return lhs.p_set == rhs.p_set && lhs.p_node == rhs.p_node;
769  }
770 
771  friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
772  {
773  return !(lhs == rhs);
774  }
775 
776  private:
777  // Pointer to set associated with this iterator
778  const iset* p_set;
779 
780  // Pointer to the current node for this iterator
781  const Node* p_node;
782  };
783  friend class const_iterator;
784 
785  typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
786 
787  typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
788  typedef ETL_OR_STD::reverse_iterator<const_iterator> const_reverse_iterator;
789 
790  //*************************************************************************
792  //*************************************************************************
793  iset& operator = (const iset& rhs)
794  {
795  // Skip if doing self assignment
796  if (this != &rhs)
797  {
798  assign(rhs.cbegin(), rhs.cend());
799  }
800 
801  return *this;
802  }
803 
804 #if ETL_CPP11_SUPPORTED
805  //*************************************************************************
807  //*************************************************************************
808  iset& operator = (iset&& rhs)
809  {
810  // Skip if doing self assignment
811  if (this != &rhs)
812  {
813  typename etl::iset<TKey, TCompare>::iterator from = rhs.begin();
814 
815  while (from != rhs.end())
816  {
817  insert(etl::move(*from++));
818  }
819  }
820 
821  return *this;
822  }
823 #endif
824 
825  //*************************************************************************
827  //*************************************************************************
829  {
830  return iterator(*this, find_limit_node(root_node, kLeft));
831  }
832 
833  //*************************************************************************
835  //*************************************************************************
837  {
838  return const_iterator(*this, find_limit_node(root_node, kLeft));
839  }
840 
841  //*************************************************************************
843  //*************************************************************************
845  {
846  return iterator(*this);
847  }
848 
849  //*************************************************************************
851  //*************************************************************************
853  {
854  return const_iterator(*this);
855  }
856 
857  //*************************************************************************
859  //*************************************************************************
861  {
862  return const_iterator(*this, find_limit_node(root_node, kLeft));
863  }
864 
865  //*************************************************************************
867  //*************************************************************************
869  {
870  return const_iterator(*this);
871  }
872 
873  //*************************************************************************
875  //*************************************************************************
876  reverse_iterator rbegin()
877  {
878  return reverse_iterator(iterator(*this));
879  }
880 
881  //*************************************************************************
883  //*************************************************************************
884  const_reverse_iterator rbegin() const
885  {
886  return const_reverse_iterator(const_iterator(*this));
887  }
888 
889  //*************************************************************************
891  //*************************************************************************
892  reverse_iterator rend()
893  {
894  return reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft)));
895  }
896 
897  //*************************************************************************
899  //*************************************************************************
900  const_reverse_iterator rend() const
901  {
902  return const_reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft)));
903  }
904 
905  //*************************************************************************
907  //*************************************************************************
908  const_reverse_iterator crbegin() const
909  {
910  return const_reverse_iterator(const_iterator(*this));
911  }
912 
913  //*************************************************************************
915  //*************************************************************************
916  const_reverse_iterator crend() const
917  {
918  return const_reverse_iterator(const_iterator(*this, find_limit_node(root_node, kLeft)));
919  }
920 
921  //*********************************************************************
927  //*********************************************************************
928  template <typename TIterator>
929  void assign(TIterator first, TIterator last)
930  {
931  initialise();
932  insert(first, last);
933  }
934 
935  //*************************************************************************
937  //*************************************************************************
938  void clear()
939  {
940  initialise();
941  }
942 
943  //*********************************************************************
947  //*********************************************************************
949  {
950  return find_node(root_node, key) ? 1 : 0;
951  }
952 
953  //*************************************************************************
956  //*************************************************************************
957  ETL_OR_STD::pair<iterator, iterator> equal_range(const_reference value)
958  {
959  return ETL_OR_STD::make_pair<iterator, iterator>(
960  iterator(*this, find_lower_node(root_node, value)),
961  iterator(*this, find_upper_node(root_node, value)));
962  }
963 
964  //*************************************************************************
967  //*************************************************************************
968  ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const_reference value) const
969  {
970  return ETL_OR_STD::make_pair<const_iterator, const_iterator>(
971  const_iterator(*this, find_lower_node(root_node, value)),
972  const_iterator(*this, find_upper_node(root_node, value)));
973  }
974 
975  //*************************************************************************
977  //*************************************************************************
978  void erase(iterator position)
979  {
980  // Remove the node by its key
981  erase((*position));
982  }
983 
984  //*************************************************************************
986  //*************************************************************************
988  {
989  // Find the parent node to be removed
990  Node*& reference_node = find_node(root_node, position.p_node);
991  iterator next(*this, reference_node);
992  ++next;
993 
994  remove_node(root_node, (*position));
995 
996  return next;
997  }
998 
999  //*************************************************************************
1000  // Erase the key specified.
1001  //*************************************************************************
1002  size_type erase(key_parameter_t key_value)
1003  {
1004  // Return 1 if key value was found and removed
1005  return remove_node(root_node, key_value) ? 1 : 0;
1006  }
1007 
1008  //*************************************************************************
1010  //*************************************************************************
1012  {
1013  iterator next;
1014  while (first != last)
1015  {
1016  next = erase(const_iterator(first++));
1017  }
1018 
1019  return next;
1020  }
1021 
1022  //*************************************************************************
1024  //*************************************************************************
1026  {
1027  iterator next;
1028  while (first != last)
1029  {
1030  next = erase(first++);
1031  }
1032 
1033  return next;
1034  }
1035 
1036  //*********************************************************************
1040  //*********************************************************************
1042  {
1043  return iterator(*this, find_node(root_node, key_value));
1044  }
1045 
1046  //*********************************************************************
1050  //*********************************************************************
1052  {
1053  return const_iterator(*this, find_node(root_node, key_value));
1054  }
1055 
1056  //*********************************************************************
1060  //*********************************************************************
1061  ETL_OR_STD::pair<iterator, bool> insert(const_reference value)
1062  {
1063  // Default to no inserted node
1064  Node* inserted_node = ETL_NULLPTR;
1065  bool inserted = false;
1066 
1067  ETL_ASSERT(!full(), ETL_ERROR(set_full));
1068 
1069  // Get next available free node
1070  Data_Node& node = allocate_data_node(value);
1071 
1072  // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1073  inserted_node = insert_node(root_node, node);
1074  inserted = inserted_node == &node;
1075 
1076  // Insert node into tree and return iterator to new node location in tree
1077  return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted);
1078  }
1079 
1080 #if ETL_CPP11_SUPPORTED
1081  //*********************************************************************
1085  //*********************************************************************
1086  ETL_OR_STD::pair<iterator, bool> insert(rvalue_reference value)
1087  {
1088  // Default to no inserted node
1089  Node* inserted_node = ETL_NULLPTR;
1090  bool inserted = false;
1091 
1092  ETL_ASSERT(!full(), ETL_ERROR(set_full));
1093 
1094  // Get next available free node
1095  Data_Node& node = allocate_data_node(etl::move(value));
1096 
1097  // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1098  inserted_node = insert_node(root_node, node);
1099  inserted = inserted_node == &node;
1100 
1101  // Insert node into tree and return iterator to new node location in tree
1102  return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted);
1103  }
1104 #endif
1105 
1106  //*********************************************************************
1111  //*********************************************************************
1112  iterator insert(iterator, const_reference value)
1113  {
1114  // Default to no inserted node
1115  Node* inserted_node = ETL_NULLPTR;
1116 
1117  ETL_ASSERT(!full(), ETL_ERROR(set_full));
1118 
1119  // Get next available free node
1120  Data_Node& node = allocate_data_node(value);
1121 
1122  // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1123  inserted_node = insert_node(root_node, node);
1124 
1125  // Insert node into tree and return iterator to new node location in tree
1126  return iterator(*this, inserted_node);
1127  }
1128 
1129 #if ETL_CPP11_SUPPORTED
1130  //*********************************************************************
1135  //*********************************************************************
1136  iterator insert(iterator, rvalue_reference value)
1137  {
1138  // Default to no inserted node
1139  Node* inserted_node = ETL_NULLPTR;
1140 
1141  ETL_ASSERT(!full(), ETL_ERROR(set_full));
1142 
1143  // Get next available free node
1144  Data_Node& node = allocate_data_node(etl::move(value));
1145 
1146  // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1147  inserted_node = insert_node(root_node, node);
1148 
1149  // Insert node into tree and return iterator to new node location in tree
1150  return iterator(*this, inserted_node);
1151  }
1152 #endif
1153 
1154  //*********************************************************************
1159  //*********************************************************************
1160  iterator insert(const_iterator, const_reference value)
1161  {
1162  // Default to no inserted node
1163  Node* inserted_node = ETL_NULLPTR;
1164 
1165  ETL_ASSERT(!full(), ETL_ERROR(set_full));
1166 
1167  // Get next available free node
1168  Data_Node& node = allocate_data_node(value);
1169 
1170  // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1171  inserted_node = insert_node(root_node, node);
1172 
1173  // Insert node into tree and return iterator to new node location in tree
1174  return iterator(*this, inserted_node);
1175  }
1176 
1177 #if ETL_CPP11_SUPPORTED
1178  //*********************************************************************
1183  //*********************************************************************
1184  iterator insert(const_iterator, rvalue_reference value)
1185  {
1186  // Default to no inserted node
1187  Node* inserted_node = ETL_NULLPTR;
1188 
1189  ETL_ASSERT(!full(), ETL_ERROR(set_full));
1190 
1191  // Get next available free node
1192  Data_Node& node = allocate_data_node(etl::move(value));
1193 
1194  // Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
1195  inserted_node = insert_node(root_node, node);
1196 
1197  // Insert node into tree and return iterator to new node location in tree
1198  return iterator(*this, inserted_node);
1199  }
1200 #endif
1201 
1202  //*********************************************************************
1208  //*********************************************************************
1209  template <class TIterator>
1210  void insert(TIterator first, TIterator last)
1211  {
1212  while (first != last)
1213  {
1214  insert(*first++);
1215  }
1216  }
1217 
1218  //*********************************************************************
1223  //*********************************************************************
1225  {
1226  return iterator(*this, find_lower_node(root_node, key));
1227  }
1228 
1229  //*********************************************************************
1234  //*********************************************************************
1236  {
1237  return const_iterator(*this, find_lower_node(root_node, key));
1238  }
1239 
1240  //*********************************************************************
1245  //*********************************************************************
1247  {
1248  return iterator(*this, find_upper_node(root_node, key));
1249  }
1250 
1251  //*********************************************************************
1256  //*********************************************************************
1258  {
1259  return const_iterator(*this, find_upper_node(root_node, key));
1260  }
1261 
1262  //*************************************************************************
1264  //*************************************************************************
1265  key_compare key_comp() const
1266  {
1267  return compare;
1268  };
1269 
1270  //*************************************************************************
1272  //*************************************************************************
1273  value_compare value_comp() const
1274  {
1275  return compare;
1276  };
1277 
1278  protected:
1279 
1280  //*************************************************************************
1282  //*************************************************************************
1283  iset(etl::ipool& node_pool, size_t max_size_)
1284  : etl::set_base(max_size_)
1285  , p_node_pool(&node_pool)
1286  {
1287  }
1288 
1289  //*************************************************************************
1291  //*************************************************************************
1292  void initialise()
1293  {
1294  const_iterator item = begin();
1295 
1296  while (item != end())
1297  {
1298  item = erase(item);
1299  }
1300  }
1301 
1302  private:
1303 
1304  //*************************************************************************
1306  //*************************************************************************
1307  Data_Node& allocate_data_node(const_reference value)
1308  {
1309  Data_Node& node = create_data_node();
1310  ::new ((void*)&node.value) value_type(value);
1311  ETL_INCREMENT_DEBUG_COUNT
1312  return node;
1313  }
1314 
1315 #if ETL_CPP11_SUPPORTED
1316  //*************************************************************************
1318  //*************************************************************************
1319  Data_Node& allocate_data_node(rvalue_reference value)
1320  {
1321  Data_Node& node = create_data_node();
1322  ::new ((void*)&node.value) value_type(etl::move(value));
1323  ETL_INCREMENT_DEBUG_COUNT
1324  return node;
1325  }
1326 #endif
1327 
1328  //*************************************************************************
1330  //*************************************************************************
1331  Data_Node& create_data_node()
1332  {
1333  Data_Node* (etl::ipool::*func)() = &etl::ipool::allocate<Data_Node>;
1334  return *(p_node_pool->*func)();
1335  }
1336 
1337  //*************************************************************************
1339  //*************************************************************************
1340  void destroy_data_node(Data_Node& node)
1341  {
1342  node.value.~value_type();
1343  p_node_pool->release(&node);
1344  ETL_DECREMENT_DEBUG_COUNT
1345  }
1346 
1347  //*************************************************************************
1349  //*************************************************************************
1350  Node* find_node(Node* position, key_parameter_t key)
1351  {
1352  Node* found = position;
1353  while (found)
1354  {
1355  // Downcast found to Data_Node class for comparison and other operations
1356  Data_Node& found_data_node = iset::data_cast(*found);
1357 
1358  // Compare the node value to the current position value
1359  if (node_comp(key, found_data_node))
1360  {
1361  // Keep searching for the node on the left
1362  found = found->children[kLeft];
1363  }
1364  else if (node_comp(found_data_node, key))
1365  {
1366  // Keep searching for the node on the right
1367  found = found->children[kRight];
1368  }
1369  else
1370  {
1371  // Node that matches the key provided was found, exit loop
1372  break;
1373  }
1374  }
1375 
1376  // Return the node found (might be ETL_NULLPTR)
1377  return found;
1378  }
1379 
1380  //*************************************************************************
1382  //*************************************************************************
1383  const Node* find_node(const Node* position, key_parameter_t key) const
1384  {
1385  const Node* found = position;
1386  while (found)
1387  {
1388  // Downcast found to Data_Node class for comparison and other operations
1389  const Data_Node& found_data_node = iset::data_cast(*found);
1390 
1391  // Compare the node value to the current position value
1392  if (node_comp(key, found_data_node))
1393  {
1394  // Keep searching for the node on the left
1395  found = found->children[kLeft];
1396  }
1397  else if (node_comp(found_data_node, key))
1398  {
1399  // Keep searching for the node on the right
1400  found = found->children[kRight];
1401  }
1402  else
1403  {
1404  // Node that matches the key provided was found, exit loop
1405  break;
1406  }
1407  }
1408 
1409  // Return the node found (might be ETL_NULLPTR)
1410  return found;
1411  }
1412 
1413  //*************************************************************************
1415  //*************************************************************************
1416  Node*& find_node(Node*& position, const Node* node)
1417  {
1418  Node* found = position;
1419  while (found)
1420  {
1421  if (found->children[kLeft] == node)
1422  {
1423  return found->children[kLeft];
1424  }
1425  else if (found->children[kRight] == node)
1426  {
1427  return found->children[kRight];
1428  }
1429  else
1430  {
1431  // Downcast found to Data_Node class for comparison and other operations
1432  Data_Node& found_data_node = iset::data_cast(*found);
1433  const Data_Node& data_node = iset::data_cast(*node);
1434 
1435  // Compare the node value to the current position value
1436  if (node_comp(data_node, found_data_node))
1437  {
1438  // Keep searching for the node on the left
1439  found = found->children[kLeft];
1440  }
1441  else if (node_comp(found_data_node, data_node))
1442  {
1443  // Keep searching for the node on the right
1444  found = found->children[kRight];
1445  }
1446  else
1447  {
1448  // Return position provided (it matches the node)
1449  return position;
1450  }
1451  }
1452  }
1453 
1454  // Return root node if nothing was found
1455  return root_node;
1456  }
1457 
1458  //*************************************************************************
1461  //*************************************************************************
1462  Node* find_parent_node(Node* position, const Node* node)
1463  {
1464  // Default to no parent node found
1465  Node* found = ETL_NULLPTR;
1466 
1467  // If the position provided is the same as the node then there is no parent
1468  if (position && node && position != node)
1469  {
1470  while (position)
1471  {
1472  // Is this position not the parent of the node we are looking for?
1473  if (position->children[kLeft] != node &&
1474  position->children[kRight] != node)
1475  {
1476  // Downcast node and position to Data_Node references for key comparisons
1477  const Data_Node& node_data_node = iset::data_cast(*node);
1478  Data_Node& position_data_node = iset::data_cast(*position);
1479  // Compare the node value to the current position value
1480  if (node_comp(node_data_node, position_data_node))
1481  {
1482  // Keep looking for parent on the left
1483  position = position->children[kLeft];
1484  }
1485  else if (node_comp(position_data_node, node_data_node))
1486  {
1487  // Keep looking for parent on the right
1488  position = position->children[kRight];
1489  }
1490  }
1491  else
1492  {
1493  // Return the current position as the parent node found
1494  found = position;
1495 
1496  // Parent node found, exit loop
1497  break;
1498  }
1499  }
1500  }
1501 
1502  // Return the parent node found (might be ETL_NULLPTR)
1503  return found;
1504  }
1505 
1506  //*************************************************************************
1509  //*************************************************************************
1510  const Node* find_parent_node(const Node* position, const Node* node) const
1511  {
1512  // Default to no parent node found
1513  const Node* found = ETL_NULLPTR;
1514 
1515  // If the position provided is the same as the node then there is no parent
1516  if (position && node && position != node)
1517  {
1518  while (position)
1519  {
1520  // Is this position not the parent of the node we are looking for?
1521  if (position->children[kLeft] != node &&
1522  position->children[kRight] != node)
1523  {
1524  // Downcast node and position to Data_Node references for key comparisons
1525  const Data_Node& node_data_node = iset::data_cast(*node);
1526  const Data_Node& position_data_node = iset::data_cast(*position);
1527  // Compare the node value to the current position value
1528  if (node_comp(node_data_node, position_data_node))
1529  {
1530  // Keep looking for parent on the left
1531  position = position->children[kLeft];
1532  }
1533  else if (node_comp(position_data_node, node_data_node))
1534  {
1535  // Keep looking for parent on the right
1536  position = position->children[kRight];
1537  }
1538  }
1539  else
1540  {
1541  // Return the current position as the parent node found
1542  found = position;
1543 
1544  // Parent node found, exit loop
1545  break;
1546  }
1547  }
1548  }
1549 
1550  // Return the parent node found (might be ETL_NULLPTR)
1551  return found;
1552  }
1553 
1554  //*************************************************************************
1556  //*************************************************************************
1557  Node* find_lower_node(Node* position, key_parameter_t key) const
1558  {
1559  // Something at this position? keep going
1560  Node* lower_node = ETL_NULLPTR;
1561  while (position)
1562  {
1563  // Downcast lower node to Data_Node reference for key comparisons
1564  Data_Node& data_node = iset::data_cast(*position);
1565  // Compare the key value to the current lower node key value
1566  if (node_comp(key, data_node))
1567  {
1568  lower_node = position;
1569  if (position->children[kLeft])
1570  {
1571  position = position->children[kLeft];
1572  }
1573  else
1574  {
1575  // Found lowest node
1576  break;
1577  }
1578  }
1579  else if (node_comp(data_node, key))
1580  {
1581  position = position->children[kRight];
1582  }
1583  else
1584  {
1585  // Make note of current position, but keep looking to left for more
1586  lower_node = position;
1587  position = position->children[kLeft];
1588  }
1589  }
1590 
1591  // Return the lower_node position found
1592  return lower_node;
1593  }
1594 
1595  //*************************************************************************
1597  //*************************************************************************
1598  Node* find_upper_node(Node* position, key_parameter_t key) const
1599  {
1600  // Keep track of parent of last upper node
1601  Node* upper_node = ETL_NULLPTR;
1602  // Start with position provided
1603  Node* node = position;
1604  while (node)
1605  {
1606  // Downcast position to Data_Node reference for key comparisons
1607  Data_Node& data_node = iset::data_cast(*node);
1608  // Compare the key value to the current upper node key value
1609  if (node_comp(key, data_node))
1610  {
1611  upper_node = node;
1612  node = node->children[kLeft];
1613  }
1614  else if (node_comp(data_node, key))
1615  {
1616  node = node->children[kRight];
1617  }
1618  else if (node->children[kRight])
1619  {
1620  upper_node = find_limit_node(node->children[kRight], kLeft);
1621  break;
1622  }
1623  else
1624  {
1625  break;
1626  }
1627  }
1628 
1629  // Return the upper node position found (might be ETL_NULLPTR)
1630  return upper_node;
1631  }
1632 
1633  //*************************************************************************
1635  //*************************************************************************
1636  Node* insert_node(Node*& position, Data_Node& node)
1637  {
1638  // Find the location where the node belongs
1639  Node* found = position;
1640 
1641  // Was position provided not empty? then find where the node belongs
1642  if (position)
1643  {
1644  // Find the critical parent node (default to ETL_NULLPTR)
1645  Node* critical_parent_node = ETL_NULLPTR;
1646  Node* critical_node = root_node;
1647 
1648  while (found)
1649  {
1650  // Search for critical weight node (all nodes whose weight factor
1651  // is set to kNeither (balanced)
1652  if (kNeither != found->weight)
1653  {
1654  critical_node = found;
1655  }
1656 
1657  // Downcast found to Data_Node class for comparison and other operations
1658  Data_Node& found_data_node = iset::data_cast(*found);
1659 
1660  // Is the node provided to the left of the current position?
1661  if (node_comp(node, found_data_node))
1662  {
1663  // Update direction taken to insert new node in parent node
1664  found->dir = kLeft;
1665  }
1666  // Is the node provided to the right of the current position?
1667  else if (node_comp(found_data_node, node))
1668  {
1669  // Update direction taken to insert new node in parent node
1670  found->dir = kRight;
1671  }
1672  else
1673  {
1674  // Update direction taken to insert new node in parent node
1675  found->dir = kNeither;
1676 
1677  // Clear critical node value to skip weight step below
1678  critical_node = ETL_NULLPTR;
1679 
1680  // Destroy the node provided (its a duplicate)
1681  destroy_data_node(node);
1682 
1683  // Exit loop, duplicate node found
1684  break;
1685  }
1686 
1687  // Is there a child of this parent node?
1688  if (found->children[found->dir])
1689  {
1690  // Will this node be the parent of the next critical node whose
1691  // weight factor is set to kNeither (balanced)?
1692  if (kNeither != found->children[found->dir]->weight)
1693  {
1694  critical_parent_node = found;
1695  }
1696 
1697  // Keep looking for empty spot to insert new node
1698  found = found->children[found->dir];
1699  }
1700  else
1701  {
1702  // Attatch node to right
1703  attach_node(found->children[found->dir], node);
1704 
1705  // Return newly added node
1706  found = found->children[found->dir];
1707 
1708  // Exit loop
1709  break;
1710  }
1711  }
1712 
1713  // Was a critical node found that should be checked for balance?
1714  if (critical_node)
1715  {
1716  if (critical_parent_node == ETL_NULLPTR && critical_node == root_node)
1717  {
1719  }
1720  else if (critical_parent_node == ETL_NULLPTR && critical_node == position)
1721  {
1722  balance_node(position);
1723  }
1724  else
1725  {
1726  if (critical_parent_node != ETL_NULLPTR)
1727  {
1728  balance_node(critical_parent_node->children[critical_parent_node->dir]);
1729  }
1730  }
1731  }
1732  }
1733  else
1734  {
1735  // Attatch node to current position
1736  attach_node(position, node);
1737 
1738  // Return newly added node at current position
1739  found = position;
1740  }
1741 
1742  // Return the node found (might be ETL_NULLPTR)
1743  return found;
1744  }
1745 
1746  //*************************************************************************
1748  //*************************************************************************
1749  void next_node(Node*&position)
1750  {
1751  if (position)
1752  {
1753  // Is there a tree on the right? then find the minimum of that tree
1754  if (position->children[kRight])
1755  {
1756  // Return minimum node found
1757  position = find_limit_node(position->children[kRight], kLeft);
1758  }
1759  // Otherwise find the parent of this node
1760  else
1761  {
1762  // Start with current position as parent
1763  Node* parent = position;
1764  do {
1765  // Update current position as previous parent
1766  position = parent;
1767  // Find parent of current position
1768  parent = find_parent_node(root_node, position);
1769  // Repeat while previous position was on right side of parent tree
1770  } while (parent && parent->children[kRight] == position);
1771 
1772  // Set parent node as the next position
1773  position = parent;
1774  }
1775  }
1776  }
1777 
1778  //*************************************************************************
1780  //*************************************************************************
1781  void next_node(const Node*& position) const
1782  {
1783  if (position)
1784  {
1785  // Is there a tree on the right? then find the minimum of that tree
1786  if (position->children[kRight])
1787  {
1788  // Return minimum node found
1789  position = find_limit_node(position->children[kRight], kLeft);
1790  }
1791  // Otherwise find the parent of this node
1792  else
1793  {
1794  // Start with current position as parent
1795  const Node* parent = position;
1796  do {
1797  // Update current position as previous parent
1798  position = parent;
1799  // Find parent of current position
1800  parent = find_parent_node(root_node, position);
1801  // Repeat while previous position was on right side of parent tree
1802  } while (parent && parent->children[kRight] == position);
1803 
1804  // Set parent node as the next position
1805  position = parent;
1806  }
1807  }
1808  }
1809 
1810  //*************************************************************************
1812  //*************************************************************************
1813  void prev_node(Node*&position)
1814  {
1815  // If starting at the terminal end, the previous node is the maximum node
1816  // from the root
1817  if (!position)
1818  {
1819  position = find_limit_node(root_node, kRight);
1820  }
1821  else
1822  {
1823  // Is there a tree on the left? then find the maximum of that tree
1824  if (position->children[kLeft])
1825  {
1826  // Return maximum node found
1827  position = find_limit_node(position->children[kLeft], kRight);
1828  }
1829  // Otherwise find the parent of this node
1830  else
1831  {
1832  // Start with current position as parent
1833  Node* parent = position;
1834  do {
1835  // Update current position as previous parent
1836  position = parent;
1837  // Find parent of current position
1838  parent = find_parent_node(root_node, position);
1839  // Repeat while previous position was on left side of parent tree
1840  } while (parent && parent->children[kLeft] == position);
1841 
1842  // Set parent node as the next position
1843  position = parent;
1844  }
1845  }
1846  }
1847 
1848  //*************************************************************************
1850  //*************************************************************************
1851  void prev_node(const Node*& position) const
1852  {
1853  // If starting at the terminal end, the previous node is the maximum node
1854  // from the root
1855  if (!position)
1856  {
1857  position = find_limit_node(root_node, kRight);
1858  }
1859  else
1860  {
1861  // Is there a tree on the left? then find the maximum of that tree
1862  if (position->children[kLeft])
1863  {
1864  // Return maximum node found
1865  position = find_limit_node(position->children[kLeft], kRight);
1866  }
1867  // Otherwise find the parent of this node
1868  else
1869  {
1870  // Start with current position as parent
1871  const Node* parent = position;
1872  do {
1873  // Update current position as previous parent
1874  position = parent;
1875  // Find parent of current position
1876  parent = find_parent_node(root_node, position);
1877  // Repeat while previous position was on left side of parent tree
1878  } while (parent && parent->children[kLeft] == position);
1879 
1880  // Set parent node as the next position
1881  position = parent;
1882  }
1883  }
1884  }
1885 
1886  //*************************************************************************
1889  //*************************************************************************
1890  Node* remove_node(Node*& position, key_parameter_t key)
1891  {
1892  // Step 1: Find the target node that matches the key provided, the
1893  // replacement node (might be the same as target node), and the critical
1894  // node to start rebalancing the tree from (up to the replacement node)
1895  Node* found_parent = ETL_NULLPTR;
1896  Node* found = ETL_NULLPTR;
1897  Node* replace_parent = ETL_NULLPTR;
1898  Node* replace = position;
1899  Node* balance_parent = ETL_NULLPTR;
1900  Node* balance = root_node;
1901  while (replace)
1902  {
1903  // Downcast found to Data_Node class for comparison and other operations
1904  Data_Node& replace_data_node = iset::data_cast(*replace);
1905 
1906  // Compare the key provided to the replace data node key
1907  if (node_comp(key, replace_data_node))
1908  {
1909  // Update the direction to the target/replace node
1910  replace->dir = kLeft;
1911  }
1912  else if (node_comp(replace_data_node, key))
1913  {
1914  // Update the direction to the target/replace node
1915  replace->dir = kRight;
1916  }
1917  else
1918  {
1919  // Update the direction to the replace node (target node found here)
1920  replace->dir = replace->children[kLeft] ? kLeft : kRight;
1921 
1922  // Note the target node was found (and its parent)
1923  found_parent = replace_parent;
1924  found = replace;
1925  }
1926  // Replacement node found if its missing a child in the replace->dir
1927  // value set above
1928  if (replace->children[replace->dir] == ETL_NULLPTR)
1929  {
1930  // Exit loop once replace node is found (target might not have been)
1931  break;
1932  }
1933 
1934  // If replacement node weight is kNeither or we are taking the shorter
1935  // path of replacement node and our sibling (on longer path) is
1936  // balanced then we need to update the balance node to match this
1937  // replacement node but all our ancestors will not require rebalancing
1938  if ((replace->weight == kNeither) ||
1939  (replace->weight == (1 - replace->dir) &&
1940  replace->children[1 - replace->dir]->weight == kNeither))
1941  {
1942  // Update balance node (and its parent) to replacement node
1943  balance_parent = replace_parent;
1944  balance = replace;
1945  }
1946 
1947  // Keep searching for the replacement node
1948  replace_parent = replace;
1949  replace = replace->children[replace->dir];
1950  }
1951 
1952  // If target node was found, proceed with rebalancing and replacement
1953  if (found)
1954  {
1955  // Step 2: Update weights from critical node to replacement parent node
1956  while (balance)
1957  {
1958  if (balance->children[balance->dir] == ETL_NULLPTR)
1959  {
1960  break;
1961  }
1962 
1963  if (balance->weight == kNeither)
1964  {
1965  balance->weight = 1 - balance->dir;
1966  }
1967  else if (balance->weight == balance->dir)
1968  {
1969  balance->weight = kNeither;
1970  }
1971  else
1972  {
1973  int weight = balance->children[1 - balance->dir]->weight;
1974  // Perform a 3 node rotation if weight is same as balance->dir
1975  if (weight == balance->dir)
1976  {
1977  // Is the root node being rebalanced (no parent)
1978  if (balance_parent == ETL_NULLPTR)
1979  {
1980  rotate_3node(root_node, 1 - balance->dir,
1981  balance->children[1 - balance->dir]->children[balance->dir]->weight);
1982  }
1983  else
1984  {
1985  rotate_3node(balance_parent->children[balance_parent->dir], 1 - balance->dir,
1986  balance->children[1 - balance->dir]->children[balance->dir]->weight);
1987  }
1988  }
1989  // Already balanced, rebalance and make it heavy in opposite
1990  // direction of the node being removed
1991  else if (weight == kNeither)
1992  {
1993  // Is the root node being rebalanced (no parent)
1994  if (balance_parent == ETL_NULLPTR)
1995  {
1996  rotate_2node(root_node, 1 - balance->dir);
1997  root_node->weight = balance->dir;
1998  }
1999  else
2000  {
2001  rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2002  balance_parent->children[balance_parent->dir]->weight = balance->dir;
2003  }
2004  // Update balance node weight in opposite direction of node removed
2005  balance->weight = 1 - balance->dir;
2006  }
2007  // Rebalance and leave it balanced
2008  else
2009  {
2010  // Is the root node being rebalanced (no parent)
2011  if (balance_parent == ETL_NULLPTR)
2012  {
2013  rotate_2node(root_node, 1 - balance->dir);
2014  }
2015  else
2016  {
2017  rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir);
2018  }
2019  }
2020 
2021  // Is balance node the same as the target node found? then update
2022  // its parent after the rotation performed above
2023  if (balance == found)
2024  {
2025  if (balance_parent)
2026  {
2027  found_parent = balance_parent->children[balance_parent->dir];
2028  // Update dir since it is likely stale
2029  found_parent->dir = found_parent->children[kLeft] == found ? kLeft : kRight;
2030  }
2031  else
2032  {
2033  found_parent = root_node;
2034  root_node->dir = root_node->children[kLeft] == found ? kLeft : kRight;
2035  }
2036  }
2037  }
2038 
2039  // Next balance node to consider
2040  balance_parent = balance;
2041  balance = balance->children[balance->dir];
2042  } // while(balance)
2043 
2044  // Step 3: Swap found node with replacement node
2045  if (found_parent)
2046  {
2047  // Handle traditional case
2048  detach_node(found_parent->children[found_parent->dir],
2049  replace_parent->children[replace_parent->dir]);
2050  }
2051  // Handle root node removal
2052  else
2053  {
2054  // Valid replacement node for root node being removed?
2055  if (replace_parent)
2056  {
2057  detach_node(root_node, replace_parent->children[replace_parent->dir]);
2058  }
2059  else
2060  {
2061  // Target node and replacement node are both root node
2063  }
2064  }
2065 
2066  // Downcast found into data node
2067  Data_Node& found_data_node = iset::data_cast(*found);
2068 
2069  // One less.
2070  --current_size;
2071 
2072  // Destroy the node removed
2073  destroy_data_node(found_data_node);
2074  } // if(found)
2075 
2076  // Return node found (might be ETL_NULLPTR)
2077  return found;
2078  }
2079 
2080  // Disable copy construction.
2081  iset(const iset&);
2082 
2083  //*************************************************************************
2085  //*************************************************************************
2086 #if defined(ETL_POLYMORPHIC_SET) || defined(ETL_POLYMORPHIC_CONTAINERS)
2087  public:
2088  virtual ~iset()
2089  {
2090  }
2091 #else
2092  protected:
2094  {
2095  }
2096 #endif
2097  };
2098 
2099  //*************************************************************************
2101  //*************************************************************************
2102  template <typename TKey, const size_t MAX_SIZE_, typename TCompare = etl::less<TKey> >
2103  class set : public etl::iset<TKey, TCompare>
2104  {
2105  public:
2106 
2107  static const size_t MAX_SIZE = MAX_SIZE_;
2108 
2109  //*************************************************************************
2111  //*************************************************************************
2113  : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2114  {
2115  this->initialise();
2116  }
2117 
2118  //*************************************************************************
2120  //*************************************************************************
2121  set(const set& other)
2122  : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2123  {
2124  if (this != &other)
2125  {
2126  this->assign(other.cbegin(), other.cend());
2127  }
2128  }
2129 
2130 #if ETL_CPP11_SUPPORTED
2131  //*************************************************************************
2133  //*************************************************************************
2134  set(set&& other)
2135  : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2136  {
2137  if (this != &other)
2138  {
2139  typename etl::iset<TKey, TCompare>::iterator from = other.begin();
2140 
2141  while (from != other.end())
2142  {
2143  this->insert(etl::move(*from++));
2144  }
2145  }
2146  }
2147 #endif
2148 
2149  //*************************************************************************
2154  //*************************************************************************
2155  template <typename TIterator>
2156  set(TIterator first, TIterator last)
2157  : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2158  {
2159  this->assign(first, last);
2160  }
2161 
2162 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
2163  //*************************************************************************
2165  //*************************************************************************
2166  set(std::initializer_list<typename etl::iset<TKey, TCompare>::value_type> init)
2167  : etl::iset<TKey, TCompare>(node_pool, MAX_SIZE)
2168  {
2169  this->assign(init.begin(), init.end());
2170  }
2171 #endif
2172 
2173  //*************************************************************************
2175  //*************************************************************************
2177  {
2178  this->initialise();
2179  }
2180 
2181  //*************************************************************************
2183  //*************************************************************************
2184  set& operator = (const set& rhs)
2185  {
2186  // Skip if doing self assignment
2187  if (this != &rhs)
2188  {
2189  this->assign(rhs.cbegin(), rhs.cend());
2190  }
2191 
2192  return *this;
2193  }
2194 
2195 #if ETL_CPP11_SUPPORTED
2196  //*************************************************************************
2198  //*************************************************************************
2199  set& operator = (set&& rhs)
2200  {
2201  // Skip if doing self assignment
2202  if (this != &rhs)
2203  {
2204  typename etl::iset<TKey, TCompare>::iterator from = rhs.begin();
2205 
2206  while (from != rhs.end())
2207  {
2208  this->insert(etl::move(*from++));
2209  }
2210  }
2211 
2212  return *this;
2213  }
2214 #endif
2215 
2216  private:
2217 
2220  };
2221 
2222  //*************************************************************************
2224  //*************************************************************************
2225 #if ETL_CPP17_SUPPORTED && ETL_NOT_USING_STLPORT && ETL_USING_STL
2226  template <typename T, typename... Ts>
2227  set(T, Ts...)
2228  ->set<etl::enable_if_t<(etl::is_same_v<T, Ts> && ...), T>, 1U + sizeof...(Ts)>;
2229 #endif
2230 
2231  //***************************************************************************
2237  //***************************************************************************
2238  template <typename TKey, typename TCompare>
2240  {
2241  return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin());
2242  }
2243 
2244  //***************************************************************************
2250  //***************************************************************************
2251  template <typename TKey, typename TCompare>
2253  {
2254  return !(lhs == rhs);
2255  }
2256 
2257  //*************************************************************************
2263  //*************************************************************************
2264  template <typename TKey, typename TCompare>
2266  {
2267  return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
2268  }
2269 
2270  //*************************************************************************
2276  //*************************************************************************
2277  template <typename TKey, typename TCompare>
2279  {
2280  return (rhs < lhs);
2281  }
2282 
2283  //*************************************************************************
2289  //*************************************************************************
2290  template <typename TKey, typename TCompare>
2292  {
2293  return !(lhs > rhs);
2294  }
2295 
2296  //*************************************************************************
2302  //*************************************************************************
2303  template <typename TKey, typename TCompare>
2305  {
2306  return !(lhs < rhs);
2307  }
2308 }
2309 
2310 #include "private/minmax_pop.h"
2311 
2312 #undef ETL_FILE
2313 
2314 #endif
const_iterator
Definition: set.h:679
iterator.
Definition: set.h:558
A templated set implementation that uses a fixed size buffer.
Definition: set.h:2104
set(const set &other)
Copy constructor.
Definition: set.h:2121
set()
Default constructor.
Definition: set.h:2112
set(TIterator first, TIterator last)
Definition: set.h:2156
~set()
Destructor.
Definition: set.h:2176
set & operator=(const set &rhs)
Assignment operator.
Definition: set.h:2184
bitset< MAXN > operator&(const bitset< MAXN > &lhs, const bitset< MAXN > &rhs)
Definition: bitset.h:1157
#define ETL_ASSERT(b, e)
Definition: error_handler.h:290
Definition: exception.h:47
void release(const void *const p_object)
Definition: pool.h:255
Definition: pool.h:118
Definition: pool.h:617
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:227
~iset()
Destructor.
Definition: set.h:2093
void balance_node(Node *&critical_node)
Balance the critical node at the position provided as needed.
Definition: set.h:284
size_type count(key_parameter_t key) const
Definition: set.h:948
bool node_comp(const Data_Node &node1, const Data_Node &node2) const
How to compare node elements.
Definition: set.h:498
const_reverse_iterator crbegin() const
Gets the reverse beginning of the list.
Definition: set.h:908
ETL_OR_STD::pair< const_iterator, const_iterator > equal_range(const_reference value) const
Definition: set.h:968
size_type capacity() const
Definition: set.h:171
size_type size() const
Gets the size of the set.
Definition: set.h:138
const_reverse_iterator crend() const
Gets the reverse end of the list.
Definition: set.h:916
iterator erase(const_iterator first, const_iterator last)
Erases a range of elements.
Definition: set.h:1025
const_iterator find(key_parameter_t key_value) const
Definition: set.h:1051
iterator upper_bound(key_parameter_t key)
Definition: set.h:1246
const_iterator begin() const
Gets the beginning of the set.
Definition: set.h:836
size_type max_size() const
Gets the maximum possible size of the set.
Definition: set.h:146
void detach_node(Node *&position, Node *&replacement)
Detach the node at the position provided.
Definition: set.h:260
ETL_OR_STD::pair< iterator, iterator > equal_range(const_reference value)
Definition: set.h:957
iterator end()
Gets the end of the set.
Definition: set.h:844
const_iterator cbegin() const
Gets the beginning of the set.
Definition: set.h:860
bool empty() const
Checks to see if the set is empty.
Definition: set.h:154
void insert(TIterator first, TIterator last)
Definition: set.h:1210
value_compare value_comp() const
How to compare two value elements.
Definition: set.h:1273
const_iterator end() const
Gets the end of the set.
Definition: set.h:852
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
void assign(TIterator first, TIterator last)
Definition: set.h:929
key_compare key_comp() const
How to compare two key elements.
Definition: set.h:1265
reverse_iterator rbegin()
Gets the reverse beginning of the list.
Definition: set.h:876
const_reverse_iterator rbegin() const
Gets the reverse beginning of the list.
Definition: set.h:884
bool full() const
Checks to see if the set is full.
Definition: set.h:162
iterator lower_bound(key_parameter_t key)
Definition: set.h:1224
reverse_iterator rend()
Gets the reverse end of the list.
Definition: set.h:892
const_iterator upper_bound(key_parameter_t key) const
Definition: set.h:1257
const_iterator lower_bound(key_parameter_t key) const
Definition: set.h:1235
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:238
const Node * find_limit_node(const Node *position, const int8_t dir) const
Definition: set.h:365
iset(etl::ipool &node_pool, size_t max_size_)
Constructor.
Definition: set.h:1283
iterator insert(iterator, const_reference value)
Definition: set.h:1112
size_t size_type
The type used for determining the size of set.
Definition: set.h:133
iterator begin()
Gets the beginning of the set.
Definition: set.h:828
void initialise()
Initialise the set.
Definition: set.h:1292
void attach_node(Node *&position, Node &node)
Attach the provided node to the position provided.
Definition: set.h:245
size_t available() const
Definition: set.h:180
void clear()
Clears the set.
Definition: set.h:938
iterator erase(const_iterator position)
Erases the value at the specified position.
Definition: set.h:987
iterator find(key_parameter_t key_value)
Definition: set.h:1041
iset & operator=(const iset &rhs)
Assignment operator.
Definition: set.h:793
iterator insert(const_iterator, const_reference value)
Definition: set.h:1160
iterator erase(iterator first, iterator last)
Erases a range of elements.
Definition: set.h:1011
const_reverse_iterator rend() const
Gets the reverse end of the list.
Definition: set.h:900
Node * root_node
The node that acts as the set root.
Definition: set.h:450
ETL_OR_STD::pair< iterator, bool > insert(const_reference value)
Definition: set.h:1061
const_iterator cend() const
Gets the end of the set.
Definition: set.h:868
void erase(iterator position)
Erases the value at the specified position.
Definition: set.h:978
const size_type CAPACITY
The maximum size of the set.
Definition: set.h:449
Node * find_limit_node(Node *position, const int8_t dir) const
Definition: set.h:348
etl::parameter_type< TKey >::type key_parameter_t
Defines the key value parameter type.
Definition: set.h:493
Definition: set.h:461
Definition: set.h:130
Definition: set.h:74
Definition: set.h:88
Definition: set.h:116
Definition: set.h:102
Definition: absolute.h:37
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:633
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:645
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:594
void swap(etl::array< T, SIZE > &lhs, etl::array< T, SIZE > &rhs)
Template deduction guides.
Definition: array.h:570
bool operator==(const etl::iset< TKey, TCompare > &lhs, const etl::iset< TKey, TCompare > &rhs)
Template deduction guides.
Definition: set.h:2239
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:582
bool operator!=(const etl::iset< TKey, TCompare > &lhs, const etl::iset< TKey, TCompare > &rhs)
Definition: set.h:2252
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:606
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:621
Definition: compare.h:52
The data node element in the set.
Definition: set.h:483
iterator
Definition: iterator.h:422
etl::conditional< etl::is_fundamental< T >::value||etl::is_pointer< T >::value, T, const T & >::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:198
Node()
Constructor.
Definition: set.h:202
void mark_as_leaf()
Marks the node as a leaf.
Definition: set.h:211