FastLED 3.9.15
Loading...
Searching...
No Matches
rbtree.h
Go to the documentation of this file.
1#pragma once
2
3// IWYU pragma: no_forward_declare RedBlackTree::const_iterator
4// IWYU pragma: no_forward_declare RedBlackTree::const_reverse_iterator
5// IWYU pragma: no_forward_declare RedBlackTree::reverse_iterator
6
7#include "fl/stl/algorithm.h"
8#include "fl/stl/allocator.h"
9#include "fl/stl/assert.h" // IWYU pragma: keep
10#include "fl/stl/comparators.h" // IWYU pragma: keep
11#include "fl/stl/initializer_list.h" // IWYU pragma: keep
12#include "fl/stl/iterator.h"
13#include "fl/stl/pair.h"
14#include "fl/stl/type_traits.h"
15#include "fl/stl/noexcept.h"
16
17namespace fl {
18
19// Generic Red-Black Tree implementation
20// This is a self-balancing binary search tree with O(log n) operations
21// T is the value type stored in the tree
22// Compare is a comparator that can compare T values
23template <typename T, typename Compare = less<T>, typename Allocator = allocator_slab<char>>
25public:
26 class iterator;
27 class const_iterator; // IWYU pragma: keep
28 class reverse_iterator; // IWYU pragma: keep
29 class const_reverse_iterator; // IWYU pragma: keep
30 using value_type = T;
31 using size_type = fl::size;
33 using compare_type = Compare;
37 using const_pointer = const value_type*;
38 using allocator_type = Allocator;
39
40 // Red-Black Tree colors
41 enum class Color { kRed, kBlack };
42
43private:
44 struct RBNode {
50
51 RBNode(const value_type& val, Color c = Color::kRed, RBNode* p = nullptr)
52 : data(val), color(c), left(nullptr), right(nullptr), parent(p) {}
53
54 template<typename... Args>
55 RBNode(Color c, RBNode* p, Args&&... args)
56 : data(fl::forward<Args>(args)...), color(c), left(nullptr), right(nullptr), parent(p) {}
57 };
58
59 using NodeAllocator = typename Allocator::template rebind<RBNode>::other;
60
61 RBNode* mRoot;
62 fl::size mSize;
63 Compare mComp;
65
66 // Helper methods
67 void rotateLeft(RBNode* x) {
68 RBNode* y = x->right;
69 x->right = y->left;
70 if (y->left != nullptr) {
71 y->left->parent = x;
72 }
73 y->parent = x->parent;
74 if (x->parent == nullptr) {
75 mRoot = y;
76 } else if (x == x->parent->left) {
77 x->parent->left = y;
78 } else {
79 x->parent->right = y;
80 }
81 y->left = x;
82 x->parent = y;
83 }
84
85 void rotateRight(RBNode* x) {
86 RBNode* y = x->left;
87 x->left = y->right;
88 if (y->right != nullptr) {
89 y->right->parent = x;
90 }
91 y->parent = x->parent;
92 if (x->parent == nullptr) {
93 mRoot = y;
94 } else if (x == x->parent->right) {
95 x->parent->right = y;
96 } else {
97 x->parent->left = y;
98 }
99 y->right = x;
100 x->parent = y;
101 }
102
103 void insertFixup(RBNode* z) {
104 while (z->parent != nullptr && z->parent->parent != nullptr && z->parent->color == Color::kRed) {
105 if (z->parent == z->parent->parent->left) {
106 RBNode* y = z->parent->parent->right;
107 if (y != nullptr && y->color == Color::kRed) {
108 z->parent->color = Color::kBlack;
109 y->color = Color::kBlack;
110 z->parent->parent->color = Color::kRed;
111 z = z->parent->parent;
112 } else {
113 if (z == z->parent->right) {
114 z = z->parent;
115 rotateLeft(z);
116 }
117 z->parent->color = Color::kBlack;
118 z->parent->parent->color = Color::kRed;
119 rotateRight(z->parent->parent);
120 }
121 } else {
122 RBNode* y = z->parent->parent->left;
123 if (y != nullptr && y->color == Color::kRed) {
124 z->parent->color = Color::kBlack;
125 y->color = Color::kBlack;
126 z->parent->parent->color = Color::kRed;
127 z = z->parent->parent;
128 } else {
129 if (z == z->parent->left) {
130 z = z->parent;
131 rotateRight(z);
132 }
133 z->parent->color = Color::kBlack;
134 z->parent->parent->color = Color::kRed;
135 rotateLeft(z->parent->parent);
136 }
137 }
138 }
139 mRoot->color = Color::kBlack;
140 }
141
142 void transplant(RBNode* u, RBNode* v) {
143 if (u->parent == nullptr) {
144 mRoot = v;
145 } else if (u == u->parent->left) {
146 u->parent->left = v;
147 } else {
148 u->parent->right = v;
149 }
150 if (v != nullptr) {
151 v->parent = u->parent;
152 }
153 }
154
155 RBNode* minimum(RBNode* x) const {
156 while (x->left != nullptr) {
157 x = x->left;
158 }
159 return x;
160 }
161
162 RBNode* maximum(RBNode* x) const {
163 while (x->right != nullptr) {
164 x = x->right;
165 }
166 return x;
167 }
168
169 // Fixed to properly use xParent when x is nullptr; removes unused parameter warning and centralizes erase fixup
170 void deleteFixup(RBNode* x, RBNode* xParent) {
171 while ((x != mRoot) && (x == nullptr || x->color == Color::kBlack)) {
172 if (x == (xParent ? xParent->left : nullptr)) {
173 RBNode* w = xParent ? xParent->right : nullptr;
174 if (w && w->color == Color::kRed) {
175 w->color = Color::kBlack;
176 if (xParent) { xParent->color = Color::kRed; rotateLeft(xParent); }
177 w = xParent ? xParent->right : nullptr;
178 }
179 bool wLeftBlack = (!w || !w->left || w->left->color == Color::kBlack);
180 bool wRightBlack = (!w || !w->right || w->right->color == Color::kBlack);
181 if (wLeftBlack && wRightBlack) {
182 if (w) w->color = Color::kRed;
183 x = xParent;
184 xParent = xParent ? xParent->parent : nullptr;
185 } else {
186 if (!w || (w->right == nullptr || w->right->color == Color::kBlack)) {
187 if (w && w->left) w->left->color = Color::kBlack;
188 if (w) { w->color = Color::kRed; rotateRight(w); }
189 w = xParent ? xParent->right : nullptr;
190 }
191 if (w) w->color = xParent ? xParent->color : Color::kBlack;
192 if (xParent) xParent->color = Color::kBlack;
193 if (w && w->right) w->right->color = Color::kBlack;
194 if (xParent) rotateLeft(xParent);
195 x = mRoot;
196 }
197 } else {
198 RBNode* w = xParent ? xParent->left : nullptr;
199 if (w && w->color == Color::kRed) {
200 w->color = Color::kBlack;
201 if (xParent) { xParent->color = Color::kRed; rotateRight(xParent); }
202 w = xParent ? xParent->left : nullptr;
203 }
204 bool wRightBlack = (!w || !w->right || w->right->color == Color::kBlack);
205 bool wLeftBlack = (!w || !w->left || w->left->color == Color::kBlack);
206 if (wRightBlack && wLeftBlack) {
207 if (w) w->color = Color::kRed;
208 x = xParent;
209 xParent = xParent ? xParent->parent : nullptr;
210 } else {
211 if (!w || (w->left == nullptr || w->left->color == Color::kBlack)) {
212 if (w && w->right) w->right->color = Color::kBlack;
213 if (w) { w->color = Color::kRed; rotateLeft(w); }
214 w = xParent ? xParent->left : nullptr;
215 }
216 if (w) w->color = xParent ? xParent->color : Color::kBlack;
217 if (xParent) xParent->color = Color::kBlack;
218 if (w && w->left) w->left->color = Color::kBlack;
219 if (xParent) rotateRight(xParent);
220 x = mRoot;
221 }
222 }
223 }
224 if (x) x->color = Color::kBlack;
225 }
226
227 RBNode* findNode(const value_type& value) const {
228 RBNode* current = mRoot;
229 while (current != nullptr) {
230 if (mComp(value, current->data)) {
231 current = current->left;
232 } else if (mComp(current->data, value)) {
233 current = current->right;
234 } else {
235 return current;
236 }
237 }
238 return nullptr;
239 }
240
241 void destroyTree(RBNode* node) {
242 if (node != nullptr) {
243 destroyTree(node->left);
244 destroyTree(node->right);
245 mAlloc.destroy(node);
246 mAlloc.deallocate(node, 1);
247 }
248 }
249
250 RBNode* copyTree(RBNode* node, RBNode* parent = nullptr) {
251 if (node == nullptr) return nullptr;
252
253 RBNode* newNode = mAlloc.allocate(1);
254 if (newNode == nullptr) {
255 return nullptr;
256 }
257
258 mAlloc.construct(newNode, node->color, parent, node->data);
259 newNode->left = copyTree(node->left, newNode);
260 newNode->right = copyTree(node->right, newNode);
261 return newNode;
262 }
263
264 // Shared insert implementation to reduce duplication
265 template <typename U>
267 RBNode* parent = nullptr;
268 RBNode* current = mRoot;
269
270 while (current != nullptr) {
271 parent = current;
272 if (mComp(value, current->data)) {
273 current = current->left;
274 } else if (mComp(current->data, value)) {
275 current = current->right;
276 } else {
277 return fl::pair<iterator, bool>(iterator(current, this), false);
278 }
279 }
280
281 RBNode* newNode = mAlloc.allocate(1);
282 if (newNode == nullptr) {
283 return fl::pair<iterator, bool>(iterator(nullptr, this), false);
284 }
285
286 mAlloc.construct(newNode, Color::kRed, parent, fl::forward<U>(value));
287
288 if (parent == nullptr) {
289 mRoot = newNode;
290 } else if (mComp(newNode->data, parent->data)) {
291 parent->left = newNode;
292 } else {
293 parent->right = newNode;
294 }
295
296 insertFixup(newNode);
297 ++mSize;
298
299 return fl::pair<iterator, bool>(iterator(newNode, this), true);
300 }
301
302 // Bound helpers to avoid duplication between const/non-const
303 RBNode* lowerBoundNode(const value_type& value) const {
304 RBNode* current = mRoot;
305 RBNode* result = nullptr;
306 while (current != nullptr) {
307 if (!mComp(current->data, value)) {
308 result = current;
309 current = current->left;
310 } else {
311 current = current->right;
312 }
313 }
314 return result;
315 }
316
317 RBNode* upperBoundNode(const value_type& value) const {
318 RBNode* current = mRoot;
319 RBNode* result = nullptr;
320 while (current != nullptr) {
321 if (mComp(value, current->data)) {
322 result = current;
323 current = current->left;
324 } else {
325 current = current->right;
326 }
327 }
328 return result;
329 }
330
331public:
332 // Iterator implementation
333 class iterator {
334 friend class RedBlackTree;
335 friend class const_iterator;
336 public:
337 using value_type = T;
339 private:
342
344 if (x == nullptr) return nullptr;
345 if (x->right != nullptr) {
346 return mTree->minimum(x->right);
347 }
348 RBNode* y = x->parent;
349 while (y != nullptr && x == y->right) {
350 x = y;
351 y = y->parent;
352 }
353 return y;
354 }
355
357 if (x == nullptr) return nullptr;
358 if (x->left != nullptr) {
359 return mTree->maximum(x->left);
360 }
361 RBNode* y = x->parent;
362 while (y != nullptr && x == y->left) {
363 x = y;
364 y = y->parent;
365 }
366 return y;
367 }
368
369 public:
370 iterator() FL_NOEXCEPT : mNode(nullptr), mTree(nullptr) {}
371 iterator(RBNode* n, const RedBlackTree* t) : mNode(n), mTree(t) {}
372
374 FASTLED_ASSERT(mNode != nullptr, "RedBlackTree::iterator: dereferencing end iterator");
375 return mNode->data;
376 }
378 FASTLED_ASSERT(mNode != nullptr, "RedBlackTree::iterator: dereferencing end iterator");
379 return &(mNode->data);
380 }
381
383 if (mNode) {
385 }
386 return *this;
387 }
388
390 iterator temp = *this;
391 ++(*this);
392 return temp;
393 }
394
396 if (mNode) {
398 } else if (mTree && mTree->mRoot) {
399 mNode = mTree->maximum(mTree->mRoot);
400 }
401 return *this;
402 }
403
405 iterator temp = *this;
406 --(*this);
407 return temp;
408 }
409
410 bool operator==(const iterator& other) const {
411 return mNode == other.mNode;
412 }
413
414 bool operator!=(const iterator& other) const {
415 return mNode != other.mNode;
416 }
417 };
418
420 friend class RedBlackTree;
421 friend class iterator;
422 private:
423 const RBNode* mNode;
425
426 const RBNode* successor(const RBNode* x) const {
427 if (x == nullptr) return nullptr;
428 if (x->right != nullptr) {
429 return mTree->minimum(x->right);
430 }
431 const RBNode* y = x->parent;
432 while (y != nullptr && x == y->right) {
433 x = y;
434 y = y->parent;
435 }
436 return y;
437 }
438
439 const RBNode* predecessor(const RBNode* x) const {
440 if (x == nullptr) return nullptr;
441 if (x->left != nullptr) {
442 return mTree->maximum(x->left);
443 }
444 const RBNode* y = x->parent;
445 while (y != nullptr && x == y->left) {
446 x = y;
447 y = y->parent;
448 }
449 return y;
450 }
451
452 public:
453 using value_type = T;
455
456 const_iterator() FL_NOEXCEPT : mNode(nullptr), mTree(nullptr) {}
457 const_iterator(const RBNode* n, const RedBlackTree* t) : mNode(n), mTree(t) {}
458 const_iterator(const iterator& it) : mNode(it.mNode), mTree(it.mTree) {}
459
460 const value_type& operator*() const {
461 FASTLED_ASSERT(mNode != nullptr, "RedBlackTree::iterator: dereferencing end iterator");
462 return mNode->data;
463 }
464 const value_type* operator->() const {
465 FASTLED_ASSERT(mNode != nullptr, "RedBlackTree::iterator: dereferencing end iterator");
466 return &(mNode->data);
467 }
468
470 if (mNode) {
472 }
473 return *this;
474 }
475
477 const_iterator temp = *this;
478 ++(*this);
479 return temp;
480 }
481
483 if (mNode) {
485 } else if (mTree && mTree->mRoot) {
486 // Decrementing from end() should give us the maximum element
487 mNode = mTree->maximum(mTree->mRoot);
488 }
489 return *this;
490 }
491
493 const_iterator temp = *this;
494 --(*this);
495 return temp;
496 }
497
498 bool operator==(const const_iterator& other) const {
499 return mNode == other.mNode;
500 }
501
502 bool operator!=(const const_iterator& other) const {
503 return mNode != other.mNode;
504 }
505
506 // Cross-type comparison: const_iterator with iterator
507 bool operator==(const iterator& other) const {
508 return mNode == other.mNode;
509 }
510
511 bool operator!=(const iterator& other) const {
512 return mNode != other.mNode;
513 }
514
515 // Friend functions for cross-type comparison (iterator with const_iterator)
516 friend bool operator==(const iterator& lhs, const const_iterator& rhs) {
517 return lhs.mNode == rhs.mNode;
518 }
519
520 friend bool operator!=(const iterator& lhs, const const_iterator& rhs) {
521 return lhs.mNode != rhs.mNode;
522 }
523 };
524
525 // Reverse iterator implementation
527 friend class RedBlackTree;
529 private:
532
534 if (x == nullptr) return nullptr;
535 if (x->right != nullptr) {
536 return mTree->minimum(x->right);
537 }
538 RBNode* y = x->parent;
539 while (y != nullptr && x == y->right) {
540 x = y;
541 y = y->parent;
542 }
543 return y;
544 }
545
547 if (x == nullptr) return nullptr;
548 if (x->left != nullptr) {
549 return mTree->maximum(x->left);
550 }
551 RBNode* y = x->parent;
552 while (y != nullptr && x == y->left) {
553 x = y;
554 y = y->parent;
555 }
556 return y;
557 }
558
559 public:
560 using value_type = T;
562
563 reverse_iterator() FL_NOEXCEPT : mNode(nullptr), mTree(nullptr) {}
565
567 FASTLED_ASSERT(mNode != nullptr, "RedBlackTree::reverse_iterator: dereferencing end iterator");
568 return mNode->data;
569 }
571 FASTLED_ASSERT(mNode != nullptr, "RedBlackTree::reverse_iterator: dereferencing end iterator");
572 return &(mNode->data);
573 }
574
575 // Increment goes backward (predecessor)
577 if (mNode) {
579 }
580 return *this;
581 }
582
584 reverse_iterator temp = *this;
585 ++(*this);
586 return temp;
587 }
588
589 // Decrement goes forward (successor)
591 if (mNode) {
593 } else if (mTree && mTree->mRoot) {
594 // Decrementing from rend() should give us the minimum element
595 mNode = mTree->minimum(mTree->mRoot);
596 }
597 return *this;
598 }
599
601 reverse_iterator temp = *this;
602 --(*this);
603 return temp;
604 }
605
606 bool operator==(const reverse_iterator& other) const {
607 return mNode == other.mNode;
608 }
609
610 bool operator!=(const reverse_iterator& other) const {
611 return mNode != other.mNode;
612 }
613 };
614
616 friend class RedBlackTree;
617 friend class reverse_iterator;
618 private:
619 const RBNode* mNode;
621
622 const RBNode* successor(const RBNode* x) const {
623 if (x == nullptr) return nullptr;
624 if (x->right != nullptr) {
625 return mTree->minimum(x->right);
626 }
627 const RBNode* y = x->parent;
628 while (y != nullptr && x == y->right) {
629 x = y;
630 y = y->parent;
631 }
632 return y;
633 }
634
635 const RBNode* predecessor(const RBNode* x) const {
636 if (x == nullptr) return nullptr;
637 if (x->left != nullptr) {
638 return mTree->maximum(x->left);
639 }
640 const RBNode* y = x->parent;
641 while (y != nullptr && x == y->left) {
642 x = y;
643 y = y->parent;
644 }
645 return y;
646 }
647
648 public:
649 using value_type = T;
651
655
656 const value_type& operator*() const {
657 FASTLED_ASSERT(mNode != nullptr, "RedBlackTree::const_reverse_iterator: dereferencing end iterator");
658 return mNode->data;
659 }
660 const value_type* operator->() const {
661 FASTLED_ASSERT(mNode != nullptr, "RedBlackTree::const_reverse_iterator: dereferencing end iterator");
662 return &(mNode->data);
663 }
664
665 // Increment goes backward (predecessor)
667 if (mNode) {
669 }
670 return *this;
671 }
672
674 const_reverse_iterator temp = *this;
675 ++(*this);
676 return temp;
677 }
678
679 // Decrement goes forward (successor)
681 if (mNode) {
683 } else if (mTree && mTree->mRoot) {
684 // Decrementing from rend() should give us the minimum element
685 mNode = mTree->minimum(mTree->mRoot);
686 }
687 return *this;
688 }
689
691 const_reverse_iterator temp = *this;
692 --(*this);
693 return temp;
694 }
695
696 bool operator==(const const_reverse_iterator& other) const {
697 return mNode == other.mNode;
698 }
699
700 bool operator!=(const const_reverse_iterator& other) const {
701 return mNode != other.mNode;
702 }
703 };
704
705 // Constructors and destructor
706 RedBlackTree(const Compare& comp = Compare(), const Allocator& alloc = Allocator())
707 : mRoot(nullptr), mSize(0), mComp(comp), mAlloc(alloc) {}
708
710 : mRoot(nullptr), mSize(other.mSize), mComp(other.mComp), mAlloc(other.mAlloc) {
711 if (other.mRoot) {
712 mRoot = copyTree(other.mRoot);
713 }
714 }
715
717 if (this != &other) {
718 clear();
719 mSize = other.mSize;
720 mComp = other.mComp;
721 mAlloc = other.mAlloc;
722 if (other.mRoot) {
723 mRoot = copyTree(other.mRoot);
724 }
725 }
726 return *this;
727 }
728
729 // Move constructor
731 : mRoot(other.mRoot), mSize(other.mSize), mComp(fl::move(other.mComp)), mAlloc(fl::move(other.mAlloc)) {
732 other.mRoot = nullptr;
733 other.mSize = 0;
734 }
735
736 // Move assignment operator
738 if (this != &other) {
739 clear();
740 mRoot = other.mRoot;
741 mSize = other.mSize;
742 mComp = fl::move(other.mComp);
743 mAlloc = fl::move(other.mAlloc);
744 other.mRoot = nullptr;
745 other.mSize = 0;
746 }
747 return *this;
748 }
749
753
754 // Iterators
755 iterator begin() {
756 if (mRoot == nullptr) return iterator(nullptr, this);
757 return iterator(minimum(mRoot), this);
758 }
759
760 const_iterator begin() const {
761 if (mRoot == nullptr) return const_iterator(nullptr, this);
762 return const_iterator(minimum(mRoot), this);
763 }
764
765 const_iterator cbegin() const {
766 return begin();
767 }
768
769 iterator end() {
770 return iterator(nullptr, this);
771 }
772
773 const_iterator end() const {
774 return const_iterator(nullptr, this);
775 }
776
777 const_iterator cend() const {
778 return end();
779 }
780
781 // Reverse iterators
782 reverse_iterator rbegin() {
783 if (mRoot == nullptr) return reverse_iterator(nullptr, this);
784 return reverse_iterator(maximum(mRoot), this);
785 }
786
787 reverse_iterator rend() {
788 return reverse_iterator(nullptr, this);
789 }
790
791 const_reverse_iterator rbegin() const {
792 if (mRoot == nullptr) return const_reverse_iterator(nullptr, this);
793 return const_reverse_iterator(maximum(mRoot), this);
794 }
795
796 const_reverse_iterator rend() const {
797 return const_reverse_iterator(nullptr, this);
798 }
799
800 const_reverse_iterator crbegin() const {
801 return rbegin();
802 }
803
804 const_reverse_iterator crend() const {
805 return rend();
806 }
807
808 // Capacity
809 bool empty() const { return mSize == 0; }
810 fl::size size() const { return mSize; }
811 fl::size max_size() const { return fl::size(-1); }
812
813 // Modifiers
814 void clear() {
816 mRoot = nullptr;
817 mSize = 0;
818 }
819
823
827
828 template<typename... Args>
833
834 iterator erase(const_iterator pos) {
835 if (pos.mNode == nullptr) return end();
836
837 RBNode* nodeToDelete = const_cast<RBNode*>(pos.mNode);
838 RBNode* successor = nullptr;
839
840 if (nodeToDelete->right != nullptr) {
841 successor = minimum(nodeToDelete->right);
842 } else {
843 RBNode* current = nodeToDelete;
844 RBNode* parent = current->parent;
845 while (parent != nullptr && current == parent->right) {
846 current = parent;
847 parent = parent->parent;
848 }
849 successor = parent;
850 }
851
852 RBNode* y = nodeToDelete;
853 RBNode* x = nullptr;
854 RBNode* xParent = nullptr;
855 Color originalColor = y->color;
856
857 if (nodeToDelete->left == nullptr) {
858 x = nodeToDelete->right;
859 xParent = nodeToDelete->parent;
860 transplant(nodeToDelete, nodeToDelete->right);
861 } else if (nodeToDelete->right == nullptr) {
862 x = nodeToDelete->left;
863 xParent = nodeToDelete->parent;
864 transplant(nodeToDelete, nodeToDelete->left);
865 } else {
866 y = minimum(nodeToDelete->right);
867 originalColor = y->color;
868 x = y->right;
869 if (y->parent == nodeToDelete) {
870 xParent = y;
871 if (x) x->parent = y;
872 } else {
873 xParent = y->parent;
874 transplant(y, y->right);
875 y->right = nodeToDelete->right;
876 y->right->parent = y;
877 }
878
879 transplant(nodeToDelete, y);
880 y->left = nodeToDelete->left;
881 y->left->parent = y;
882 y->color = nodeToDelete->color;
883 }
884
885 mAlloc.destroy(nodeToDelete);
886 mAlloc.deallocate(nodeToDelete, 1);
887 --mSize;
888
889 if (originalColor == Color::kBlack) {
890 deleteFixup(x, xParent);
891 }
892
893 return iterator(successor, this);
894 }
895
896 fl::size erase(const value_type& value) {
897 RBNode* node = findNode(value);
898 if (node == nullptr) return 0;
899
900 erase(const_iterator(node, this));
901 return 1;
902 }
903
904 void swap(RedBlackTree& other) {
905 fl::swap(mRoot, other.mRoot);
906 fl::swap(mSize, other.mSize);
907 fl::swap(mComp, other.mComp);
908 fl::swap(mAlloc, other.mAlloc);
909 }
910
911 // Lookup
912 fl::size count(const value_type& value) const {
913 return findNode(value) != nullptr ? 1 : 0;
914 }
915
916 iterator find(const value_type& value) {
917 RBNode* node = findNode(value);
918 return node ? iterator(node, this) : end();
919 }
920
921 const_iterator find(const value_type& value) const {
922 RBNode* node = findNode(value);
923 return node ? const_iterator(node, this) : end();
924 }
925
926 bool contains(const value_type& value) const {
927 return findNode(value) != nullptr;
928 }
929
931 iterator lower = lower_bound(value);
932 iterator upper = upper_bound(value);
933 return fl::pair<iterator, iterator>(lower, upper);
934 }
935
937 const_iterator lower = lower_bound(value);
938 const_iterator upper = upper_bound(value);
939 return fl::pair<const_iterator, const_iterator>(lower, upper);
940 }
941
942 iterator lower_bound(const value_type& value) {
943 RBNode* n = lowerBoundNode(value);
944 return n ? iterator(n, this) : end();
945 }
946
947 const_iterator lower_bound(const value_type& value) const {
948 RBNode* n = lowerBoundNode(value);
949 return n ? const_iterator(n, this) : end();
950 }
951
952 iterator upper_bound(const value_type& value) {
953 RBNode* n = upperBoundNode(value);
954 return n ? iterator(n, this) : end();
955 }
956
957 const_iterator upper_bound(const value_type& value) const {
958 RBNode* n = upperBoundNode(value);
959 return n ? const_iterator(n, this) : end();
960 }
961
962 // Observers
964 return mComp;
965 }
966
967 // Returns a copy of the allocator object associated with the tree
969 return allocator_type(mAlloc);
970 }
971
972 // Comparison operators
973 bool operator==(const RedBlackTree& other) const {
974 if (mSize != other.mSize) return false;
975
976 const_iterator it1 = begin();
977 const_iterator it2 = other.begin();
978
979 while (it1 != end() && it2 != other.end()) {
980 // Two values are equal if neither is less than the other
981 if (mComp(*it1, *it2) || mComp(*it2, *it1)) {
982 return false;
983 }
984 ++it1;
985 ++it2;
986 }
987
988 return it1 == end() && it2 == other.end();
989 }
990
991 bool operator!=(const RedBlackTree& other) const {
992 return !(*this == other);
993 }
994};
995
996// Specialized Red-Black Tree for key-value pairs (maps)
997template <typename Key, typename Value, typename Compare = less<Key>, typename Allocator = allocator_slab<char>>
999public:
1000 using key_type = Key;
1001 using mapped_type = Value;
1003 using size_type = fl::size;
1005 using key_compare = Compare;
1010 using allocator_type = Allocator;
1011
1012private:
1013 // Comparator for pairs that compares only the key
1015 Compare mComp;
1016
1017 PairCompare(const Compare& comp = Compare()) : mComp(comp) {}
1018
1019 bool operator()(const value_type& a, const value_type& b) const {
1020 return mComp(a.first, b.first);
1021 }
1022 };
1023
1026
1027public:
1028 // Value comparison class for std::map compatibility
1030 friend class MapRedBlackTree;
1031 Compare mComp;
1032 value_compare(Compare c) : mComp(c) {}
1033 public:
1034 bool operator()(const value_type& x, const value_type& y) const {
1035 return mComp(x.first, y.first);
1036 }
1037 };
1038
1039private:
1040
1041public:
1042 using iterator = typename TreeType::iterator;
1043 using const_iterator = typename TreeType::const_iterator;
1044 using reverse_iterator = typename TreeType::reverse_iterator;
1045 using const_reverse_iterator = typename TreeType::const_reverse_iterator;
1046
1047 // Constructors and destructor
1048 MapRedBlackTree(const Compare& comp = Compare(), const Allocator& alloc = Allocator())
1049 : mTree(PairCompare(comp), alloc) {}
1050
1053
1054 // Move constructor
1056
1057 // Move assignment operator
1059
1060 // Initializer list assignment operator
1061 // Replaces the contents of the map with the contents of the initializer list
1062 MapRedBlackTree& operator=(fl::initializer_list<value_type> ilist) FL_NOEXCEPT {
1063 clear();
1064 for (const auto& value : ilist) {
1065 mTree.insert(value);
1066 }
1067 return *this;
1068 }
1069
1070 // Range constructor - construct map from range [first, last)
1071 // Constructs a map with the contents of the range [first, last)
1072 // If the range contains duplicate keys, the first occurrence is kept
1073 template <typename InputIt>
1074 MapRedBlackTree(InputIt first, InputIt last,
1075 const Compare& comp = Compare(),
1076 const Allocator& alloc = Allocator())
1077 : mTree(PairCompare(comp), alloc) {
1078 // Insert all elements from the range
1079 for (InputIt it = first; it != last; ++it) {
1080 mTree.insert(*it);
1081 }
1082 }
1083
1084 // Initializer list constructor - construct map from initializer list
1085 // Constructs a map with the contents of the initializer list
1086 // If the list contains duplicate keys, the first occurrence is kept
1087 MapRedBlackTree(fl::initializer_list<value_type> init,
1088 const Compare& comp = Compare(),
1089 const Allocator& alloc = Allocator())
1090 : mTree(PairCompare(comp), alloc) {
1091 // Insert all elements from the initializer list
1092 for (const auto& value : init) {
1093 mTree.insert(value);
1094 }
1095 }
1096
1098
1099 // Iterators
1100 iterator begin() { return mTree.begin(); }
1101 const_iterator begin() const { return mTree.begin(); }
1102 const_iterator cbegin() const { return mTree.cbegin(); }
1103 iterator end() { return mTree.end(); }
1104 const_iterator end() const { return mTree.end(); }
1105 const_iterator cend() const { return mTree.cend(); }
1106
1107 // Reverse iterators
1108 reverse_iterator rbegin() { return mTree.rbegin(); }
1109 reverse_iterator rend() { return mTree.rend(); }
1110 const_reverse_iterator rbegin() const { return mTree.rbegin(); }
1111 const_reverse_iterator rend() const { return mTree.rend(); }
1112 const_reverse_iterator crbegin() const { return mTree.crbegin(); }
1113 const_reverse_iterator crend() const { return mTree.crend(); }
1114
1115 // Capacity
1116 bool empty() const { return mTree.empty(); }
1117 fl::size size() const { return mTree.size(); }
1118 fl::size max_size() const { return mTree.max_size(); }
1119
1120 // Element access
1121 Value& operator[](const Key& key) {
1122 auto result = mTree.insert(value_type(key, Value()));
1123 return result.first->second;
1124 }
1125
1126 Value& at(const Key& key) {
1127 auto it = mTree.find(value_type(key, Value()));
1128 FASTLED_ASSERT(it != mTree.end(), "MapRedBlackTree::at: key not found");
1129 return it->second;
1130 }
1131
1132 const Value& at(const Key& key) const {
1133 auto it = mTree.find(value_type(key, Value()));
1134 FASTLED_ASSERT(it != mTree.end(), "MapRedBlackTree::at: key not found");
1135 return it->second;
1136 }
1137
1138 // Modifiers
1139 void clear() { mTree.clear(); }
1140
1142 return mTree.insert(value);
1143 }
1144
1148
1149 template<typename... Args>
1151 return mTree.emplace(fl::forward<Args>(args)...);
1152 }
1153
1154 // Range insert - insert elements from range [first, last)
1155 // Duplicates are ignored (existing keys are not overwritten)
1156 template <typename InputIt>
1157 void insert(InputIt first, InputIt last) {
1158 for (InputIt it = first; it != last; ++it) {
1159 mTree.insert(*it);
1160 }
1161 }
1162
1163 // Initializer list insert - insert elements from initializer list
1164 // Duplicates are ignored (existing keys are not overwritten)
1165 void insert(fl::initializer_list<value_type> ilist) {
1166 for (const auto& value : ilist) {
1167 mTree.insert(value);
1168 }
1169 }
1170
1171 // Hint-based insert - insert with iterator hint for potential optimization
1172 // Returns iterator to inserted element or existing element if key already exists
1173 // Note: Current implementation ignores hint parameter; optimization can be added later
1175 (void)hint; // Hint parameter not currently used in implementation
1176 auto result = mTree.insert(value);
1177 return result.first;
1178 }
1179
1181 (void)hint; // Hint parameter not currently used in implementation
1182 auto result = mTree.insert(fl::move(value));
1183 return result.first;
1184 }
1185
1186 // Hint-based emplace - construct element in-place with iterator hint for potential optimization
1187 // Returns iterator to emplaced element or existing element if key already exists
1188 // Note: Current implementation ignores hint parameter; optimization can be added later
1189 template<typename... Args>
1191 (void)hint; // Hint parameter not currently used in implementation
1192 auto result = mTree.emplace(fl::forward<Args>(args)...);
1193 return result.first;
1194 }
1195
1196 // Insert or assign - insert if key doesn't exist, assign if it does
1197 // Returns pair<iterator, bool> where bool indicates if insertion took place
1198 template <typename M>
1200 auto it = mTree.find(value_type(key, Value()));
1201 if (it != mTree.end()) {
1202 // Key exists, assign new value
1203 it->second = fl::forward<M>(obj);
1204 return fl::pair<iterator, bool>(it, false);
1205 } else {
1206 // Key doesn't exist, insert
1207 return mTree.insert(value_type(key, fl::forward<M>(obj)));
1208 }
1209 }
1210
1211 template <typename M>
1213 auto it = mTree.find(value_type(key, Value()));
1214 if (it != mTree.end()) {
1215 // Key exists, assign new value
1216 it->second = fl::forward<M>(obj);
1217 return fl::pair<iterator, bool>(it, false);
1218 } else {
1219 // Key doesn't exist, insert with moved key
1220 return mTree.insert(value_type(fl::move(key), fl::forward<M>(obj)));
1221 }
1222 }
1223
1224 // Hint-based insert_or_assign (hint parameter currently ignored, same as non-hint version)
1225 template <typename M>
1226 iterator insert_or_assign(const_iterator hint, const Key& key, M&& obj) {
1227 (void)hint; // Hint parameter not currently used in implementation
1228 auto result = insert_or_assign(key, fl::forward<M>(obj));
1229 return result.first;
1230 }
1231
1232 template <typename M>
1234 (void)hint; // Hint parameter not currently used in implementation
1236 return result.first;
1237 }
1238
1239 // try_emplace - insert if key doesn't exist (constructing value in-place), do nothing if it does
1240 // Returns pair<iterator, bool> where bool indicates if insertion took place
1241 // More efficient than insert_or_assign when value construction is expensive
1242 //
1243 // Key difference from insert_or_assign:
1244 // - try_emplace: Does NOT construct value_args if key exists (but does construct Value() for search)
1245 // - insert_or_assign: Constructs value first, then either inserts or assigns
1246 //
1247 // Note: This implementation constructs Value() once for the lower_bound search,
1248 // but does NOT construct the actual value from args... if the key already exists.
1249 // This is still more efficient than insert_or_assign when args... is expensive.
1250 template <typename... Args>
1252 // Use lower_bound to find position (constructs Value() once for search)
1253 auto it = mTree.lower_bound(value_type(key, Value()));
1254
1255 // Check if key already exists
1256 if (it != mTree.end() && it->first == key) {
1257 // Key exists, do NOT construct value from args
1258 return fl::pair<iterator, bool>(it, false);
1259 }
1260
1261 // Key doesn't exist, now construct value from args and insert
1262 return mTree.emplace(key, fl::forward<Args>(args)...);
1263 }
1264
1265 template <typename... Args>
1267 // Use lower_bound to find position
1268 auto it = mTree.lower_bound(value_type(key, Value()));
1269
1270 // Check if key already exists
1271 if (it != mTree.end() && it->first == key) {
1272 // Key exists, do NOT construct value from args
1273 return fl::pair<iterator, bool>(it, false);
1274 }
1275
1276 // Key doesn't exist, construct value from args and insert with moved key
1277 return mTree.emplace(fl::move(key), fl::forward<Args>(args)...);
1278 }
1279
1280 // Hint-based try_emplace (hint parameter currently ignored, same as non-hint version)
1281 template <typename... Args>
1282 iterator try_emplace(const_iterator hint, const Key& key, Args&&... args) {
1283 (void)hint; // Hint parameter not currently used in implementation
1284 auto result = try_emplace(key, fl::forward<Args>(args)...);
1285 return result.first;
1286 }
1287
1288 template <typename... Args>
1289 iterator try_emplace(const_iterator hint, Key&& key, Args&&... args) {
1290 (void)hint; // Hint parameter not currently used in implementation
1292 return result.first;
1293 }
1294
1296 return mTree.erase(pos);
1297 }
1298
1299 fl::size erase(const Key& key) {
1300 return mTree.erase(value_type(key, Value()));
1301 }
1302
1303 // Range erase - erase all elements in range [first, last)
1304 // Returns iterator following the last removed element
1306 // Handle empty range case
1307 if (first == last) {
1308 // Convert const_iterator to iterator for empty range
1309 // We need to find the same position as an iterator
1310 if (first == mTree.cend()) {
1311 return mTree.end();
1312 }
1313 // For non-end iterator, find by constructing the full value_type for search
1314 return mTree.find(value_type(first->first, Value()));
1315 }
1316
1317 // Erase elements one by one from first to last
1318 // Use an iterator to track position since erase returns iterator
1319 iterator current = mTree.erase(first); // Erase first element and get iterator to next
1320
1321 // Continue erasing while we haven't reached last
1322 // We need to compare with last, but current is iterator and last is const_iterator
1323 // This works because iterator can be compared with const_iterator
1324 while (current != last) {
1325 current = mTree.erase(current);
1326 }
1327
1328 // Return iterator following the last removed element
1329 return current;
1330 }
1331
1332 void swap(MapRedBlackTree& other) {
1333 mTree.swap(other.mTree);
1334 }
1335
1336 // Lookup
1337 fl::size count(const Key& key) const {
1338 return mTree.count(value_type(key, Value()));
1339 }
1340
1341 iterator find(const Key& key) {
1342 return mTree.find(value_type(key, Value()));
1343 }
1344
1345 const_iterator find(const Key& key) const {
1346 return mTree.find(value_type(key, Value()));
1347 }
1348
1349 bool contains(const Key& key) const {
1350 return mTree.contains(value_type(key, Value()));
1351 }
1352
1354 return mTree.equal_range(value_type(key, Value()));
1355 }
1356
1358 return mTree.equal_range(value_type(key, Value()));
1359 }
1360
1362 return mTree.lower_bound(value_type(key, Value()));
1363 }
1364
1365 const_iterator lower_bound(const Key& key) const {
1366 return mTree.lower_bound(value_type(key, Value()));
1367 }
1368
1370 return mTree.upper_bound(value_type(key, Value()));
1371 }
1372
1373 const_iterator upper_bound(const Key& key) const {
1374 return mTree.upper_bound(value_type(key, Value()));
1375 }
1376
1377 // Observers
1379 return mTree.value_comp().mComp;
1380 }
1381
1382 value_compare value_comp() const {
1383 return value_compare(key_comp());
1384 }
1385
1386 // Returns a copy of the allocator object associated with the map
1388 return mTree.get_allocator();
1389 }
1390
1391 // Comparison operators
1392 bool operator==(const MapRedBlackTree& other) const {
1393 if (mTree.size() != other.mTree.size()) return false;
1394
1395 auto it1 = mTree.begin();
1396 auto it2 = other.mTree.begin();
1397
1398 while (it1 != mTree.end() && it2 != other.mTree.end()) {
1399 // Compare both key and value
1400 if (it1->first != it2->first || it1->second != it2->second) {
1401 return false;
1402 }
1403 ++it1;
1404 ++it2;
1405 }
1406
1407 return it1 == mTree.end() && it2 == other.mTree.end();
1408 }
1409
1410 bool operator!=(const MapRedBlackTree& other) const {
1411 return !(*this == other);
1412 }
1413
1414 // Lexicographic comparison operators
1415 // Compare maps element by element in sorted order
1416 // Returns true if this map is lexicographically less than other
1417 bool operator<(const MapRedBlackTree& other) const {
1418 return fl::lexicographical_compare(mTree.begin(), mTree.end(),
1419 other.mTree.begin(), other.mTree.end());
1420 }
1421
1422 // Returns true if this map is lexicographically less than or equal to other
1423 bool operator<=(const MapRedBlackTree& other) const {
1424 return !(other < *this);
1425 }
1426
1427 // Returns true if this map is lexicographically greater than other
1428 bool operator>(const MapRedBlackTree& other) const {
1429 return other < *this;
1430 }
1431
1432 // Returns true if this map is lexicographically greater than or equal to other
1433 bool operator>=(const MapRedBlackTree& other) const {
1434 return !(*this < other);
1435 }
1436};
1437
1438// Specialized Red-Black Tree for sets (just keys, no values)
1439template <typename Key, typename Compare = less<Key>, typename Allocator = allocator_slab<char>>
1441public:
1442 using key_type = Key;
1444 using size_type = fl::size;
1446 using key_compare = Compare;
1447 using reference = const value_type&;
1449 using pointer = const value_type*;
1451 using allocator_type = Allocator;
1452
1453private:
1456
1457public:
1458 using iterator = typename TreeType::const_iterator; // Set iterators are always const
1459 using const_iterator = typename TreeType::const_iterator;
1460 using reverse_iterator = typename TreeType::const_reverse_iterator; // Set reverse iterators are always const
1461 using const_reverse_iterator = typename TreeType::const_reverse_iterator;
1462
1463 // Constructors and destructor
1464 SetRedBlackTree(const Compare& comp = Compare(), const Allocator& alloc = Allocator())
1465 : mTree(comp, alloc) {}
1466
1472
1473 // Iterators
1474 const_iterator begin() const { return mTree.begin(); }
1475 const_iterator cbegin() const { return mTree.cbegin(); }
1476 const_iterator end() const { return mTree.end(); }
1477 const_iterator cend() const { return mTree.cend(); }
1478
1479 // Reverse iterators
1480 const_reverse_iterator rbegin() const { return mTree.rbegin(); }
1481 const_reverse_iterator rend() const { return mTree.rend(); }
1482
1483 // Capacity
1484 bool empty() const { return mTree.empty(); }
1485 fl::size size() const { return mTree.size(); }
1486 fl::size max_size() const { return mTree.max_size(); }
1487
1488 // Allocator
1489 allocator_type get_allocator() const { return mTree.get_allocator(); }
1490
1491 // Modifiers
1492 void clear() { mTree.clear(); }
1493
1495 auto result = mTree.insert(value);
1496 return fl::pair<const_iterator, bool>(result.first, result.second);
1497 }
1498
1503
1504 template<typename... Args>
1506 auto result = mTree.emplace(fl::forward<Args>(args)...);
1507 return fl::pair<const_iterator, bool>(result.first, result.second);
1508 }
1509
1511 return mTree.erase(pos);
1512 }
1513
1514 fl::size erase(const Key& key) {
1515 return mTree.erase(key);
1516 }
1517
1518 void swap(SetRedBlackTree& other) {
1519 mTree.swap(other.mTree);
1520 }
1521
1522 // Lookup
1523 fl::size count(const Key& key) const {
1524 return mTree.count(key);
1525 }
1526
1527 const_iterator find(const Key& key) const {
1528 return mTree.find(key);
1529 }
1530
1531 bool contains(const Key& key) const {
1532 return mTree.contains(key);
1533 }
1534
1536 return mTree.equal_range(key);
1537 }
1538
1539 const_iterator lower_bound(const Key& key) const {
1540 return mTree.lower_bound(key);
1541 }
1542
1543 const_iterator upper_bound(const Key& key) const {
1544 return mTree.upper_bound(key);
1545 }
1546
1547 // Observers
1549 return mTree.value_comp();
1550 }
1551
1552 // Comparison operators
1553 bool operator==(const SetRedBlackTree& other) const {
1554 return mTree == other.mTree;
1555 }
1556
1557 bool operator!=(const SetRedBlackTree& other) const {
1558 return mTree != other.mTree;
1559 }
1560};
1561
1562} // namespace fl
uint8_t pos
Definition Blur.ino:11
uint32_t z[NUM_LAYERS]
Definition Fire2023.h:93
bool operator()(const value_type &x, const value_type &y) const
Definition rbtree.h:1034
MapRedBlackTree(const MapRedBlackTree &other) FL_NOEXCEPT=default
MapRedBlackTree(MapRedBlackTree &&other) FL_NOEXCEPT=default
bool operator<=(const MapRedBlackTree &other) const
Definition rbtree.h:1423
typename TreeType::const_reverse_iterator const_reverse_iterator
Definition rbtree.h:1045
iterator insert(const_iterator hint, value_type &&value)
Definition rbtree.h:1180
const value_type * const_pointer
Definition rbtree.h:1009
MapRedBlackTree(InputIt first, InputIt last, const Compare &comp=Compare(), const fl::allocator_slab< char > &alloc=fl::allocator_slab< char >())
Definition rbtree.h:1074
MapRedBlackTree & operator=(fl::initializer_list< value_type > ilist) FL_NOEXCEPT
Definition rbtree.h:1062
ptrdiff_t difference_type
Definition rbtree.h:1004
MapRedBlackTree & operator=(MapRedBlackTree &&other) FL_NOEXCEPT=default
MapRedBlackTree & operator=(const MapRedBlackTree &other) FL_NOEXCEPT=default
fl::pair< iterator, bool > insert_or_assign(const Key &key, M &&obj)
Definition rbtree.h:1199
iterator insert_or_assign(const_iterator hint, const Key &key, M &&obj)
Definition rbtree.h:1226
iterator erase(const_iterator first, const_iterator last)
Definition rbtree.h:1305
bool operator!=(const MapRedBlackTree &other) const
Definition rbtree.h:1410
typename TreeType::iterator iterator
Definition rbtree.h:1042
Compare key_compare
Definition rbtree.h:1005
fl::pair< iterator, bool > try_emplace(Key &&key, Args &&... args)
Definition rbtree.h:1266
RedBlackTree< value_type, PairCompare, Allocator > TreeType
Definition rbtree.h:1024
fl::pair< iterator, iterator > equal_range(const Key &key)
Definition rbtree.h:1353
value_type * pointer
Definition rbtree.h:1008
iterator try_emplace(const_iterator hint, const Key &key, Args &&... args)
Definition rbtree.h:1282
typename TreeType::const_iterator const_iterator
Definition rbtree.h:1043
bool operator<(const MapRedBlackTree &other) const
Definition rbtree.h:1417
fl::pair< iterator, bool > emplace(Args &&... args)
Definition rbtree.h:1150
iterator try_emplace(const_iterator hint, Key &&key, Args &&... args)
Definition rbtree.h:1289
iterator insert(const_iterator hint, const value_type &value)
Definition rbtree.h:1174
fl::pair< Key, Value > value_type
Definition rbtree.h:1002
fl::pair< iterator, bool > try_emplace(const Key &key, Args &&... args)
Definition rbtree.h:1251
MapRedBlackTree(const Compare &comp=Compare(), const Allocator &alloc=Allocator())
Definition rbtree.h:1048
value_type & reference
Definition rbtree.h:1006
bool operator==(const MapRedBlackTree &other) const
Definition rbtree.h:1392
fl::pair< const_iterator, const_iterator > equal_range(const Key &key) const
Definition rbtree.h:1357
iterator insert_or_assign(const_iterator hint, Key &&key, M &&obj)
Definition rbtree.h:1233
fl::pair< iterator, bool > insert(value_type &&value)
Definition rbtree.h:1145
fl::pair< iterator, bool > insert(const value_type &value)
Definition rbtree.h:1141
bool operator>=(const MapRedBlackTree &other) const
Definition rbtree.h:1433
bool operator>(const MapRedBlackTree &other) const
Definition rbtree.h:1428
void insert(fl::initializer_list< value_type > ilist)
Definition rbtree.h:1165
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition rbtree.h:1190
MapRedBlackTree(fl::initializer_list< value_type > init, const Compare &comp=Compare(), const fl::allocator_slab< char > &alloc=fl::allocator_slab< char >())
Definition rbtree.h:1087
fl::size size_type
Definition rbtree.h:1003
Allocator allocator_type
Definition rbtree.h:1010
typename TreeType::reverse_iterator reverse_iterator
Definition rbtree.h:1044
const value_type & const_reference
Definition rbtree.h:1007
fl::pair< iterator, bool > insert_or_assign(Key &&key, M &&obj)
Definition rbtree.h:1212
const RBNode * predecessor(const RBNode *x) const
Definition rbtree.h:439
friend bool operator==(const iterator &lhs, const const_iterator &rhs)
Definition rbtree.h:516
const RBNode * successor(const RBNode *x) const
Definition rbtree.h:426
const_iterator & operator--()
Definition rbtree.h:482
const value_type & operator*() const
Definition rbtree.h:460
bool operator!=(const iterator &other) const
Definition rbtree.h:511
bool operator==(const const_iterator &other) const
Definition rbtree.h:498
const RedBlackTree * mTree
Definition rbtree.h:424
const value_type * operator->() const
Definition rbtree.h:464
fl::bidirectional_iterator_tag iterator_category
Definition rbtree.h:454
const_iterator operator++(int)
Definition rbtree.h:476
const_iterator & operator++()
Definition rbtree.h:469
const_iterator operator--(int)
Definition rbtree.h:492
bool operator==(const iterator &other) const
Definition rbtree.h:507
friend bool operator!=(const iterator &lhs, const const_iterator &rhs)
Definition rbtree.h:520
const_iterator(const iterator &it)
Definition rbtree.h:458
bool operator!=(const const_iterator &other) const
Definition rbtree.h:502
const_iterator(const RBNode *n, const RedBlackTree *t)
Definition rbtree.h:457
const RBNode * predecessor(const RBNode *x) const
Definition rbtree.h:635
const_reverse_iterator & operator++()
Definition rbtree.h:666
const_reverse_iterator operator--(int)
Definition rbtree.h:690
bool operator==(const const_reverse_iterator &other) const
Definition rbtree.h:696
const_reverse_iterator & operator--()
Definition rbtree.h:680
const_reverse_iterator(const RBNode *n, const RedBlackTree *t)
Definition rbtree.h:653
const value_type * operator->() const
Definition rbtree.h:660
fl::bidirectional_iterator_tag iterator_category
Definition rbtree.h:650
const_reverse_iterator operator++(int)
Definition rbtree.h:673
const RBNode * successor(const RBNode *x) const
Definition rbtree.h:622
bool operator!=(const const_reverse_iterator &other) const
Definition rbtree.h:700
const_reverse_iterator(const reverse_iterator &it)
Definition rbtree.h:654
const value_type & operator*() const
Definition rbtree.h:656
friend class RedBlackTree
Definition rbtree.h:334
iterator & operator--()
Definition rbtree.h:395
bool operator==(const iterator &other) const
Definition rbtree.h:410
value_type & operator*() const
Definition rbtree.h:373
value_type * operator->() const
Definition rbtree.h:377
iterator operator++(int)
Definition rbtree.h:389
const RedBlackTree * mTree
Definition rbtree.h:341
iterator & operator++()
Definition rbtree.h:382
fl::bidirectional_iterator_tag iterator_category
Definition rbtree.h:338
iterator() FL_NOEXCEPT
Definition rbtree.h:370
iterator operator--(int)
Definition rbtree.h:404
friend class const_iterator
Definition rbtree.h:335
RBNode * predecessor(RBNode *x) const
Definition rbtree.h:356
RBNode * successor(RBNode *x) const
Definition rbtree.h:343
bool operator!=(const iterator &other) const
Definition rbtree.h:414
iterator(RBNode *n, const RedBlackTree *t)
Definition rbtree.h:371
reverse_iterator operator++(int)
Definition rbtree.h:583
reverse_iterator(RBNode *n, const RedBlackTree *t)
Definition rbtree.h:564
RBNode * successor(RBNode *x) const
Definition rbtree.h:533
const RedBlackTree * mTree
Definition rbtree.h:531
value_type & operator*() const
Definition rbtree.h:566
value_type * operator->() const
Definition rbtree.h:570
reverse_iterator & operator++()
Definition rbtree.h:576
bool operator!=(const reverse_iterator &other) const
Definition rbtree.h:610
RBNode * predecessor(RBNode *x) const
Definition rbtree.h:546
bool operator==(const reverse_iterator &other) const
Definition rbtree.h:606
fl::bidirectional_iterator_tag iterator_category
Definition rbtree.h:561
reverse_iterator & operator--()
Definition rbtree.h:590
reverse_iterator operator--(int)
Definition rbtree.h:600
Allocator allocator_type
Definition rbtree.h:38
RedBlackTree & operator=(RedBlackTree &&other) FL_NOEXCEPT
Definition rbtree.h:737
fl::size erase(const value_type &value)
Definition rbtree.h:896
iterator upper_bound(const value_type &value)
Definition rbtree.h:952
Compare compare_type
Definition rbtree.h:33
RBNode * minimum(RBNode *x) const
Definition rbtree.h:155
RedBlackTree(const Compare &comp=Compare(), const Allocator &alloc=Allocator())
Definition rbtree.h:706
reverse_iterator rend()
Definition rbtree.h:787
fl::pair< iterator, iterator > equal_range(const value_type &value)
Definition rbtree.h:930
fl::pair< iterator, bool > emplace(Args &&... args)
Definition rbtree.h:829
bool empty() const
Definition rbtree.h:809
const_iterator upper_bound(const value_type &value) const
Definition rbtree.h:957
compare_type value_comp() const
Definition rbtree.h:963
fl::size size_type
Definition rbtree.h:31
RBNode * upperBoundNode(const value_type &value) const
Definition rbtree.h:317
bool operator!=(const RedBlackTree &other) const
Definition rbtree.h:991
fl::size size() const
Definition rbtree.h:810
iterator end()
Definition rbtree.h:769
iterator erase(const_iterator pos)
Definition rbtree.h:834
iterator begin()
Definition rbtree.h:755
void swap(RedBlackTree &other)
Definition rbtree.h:904
fl::size count(const value_type &value) const
Definition rbtree.h:912
fl::size max_size() const
Definition rbtree.h:811
void rotateRight(RBNode *x)
Definition rbtree.h:85
const_iterator end() const
Definition rbtree.h:773
reverse_iterator rbegin()
Definition rbtree.h:782
RedBlackTree(RedBlackTree &&other) FL_NOEXCEPT
Definition rbtree.h:730
bool operator==(const RedBlackTree &other) const
Definition rbtree.h:973
allocator_type get_allocator() const
Definition rbtree.h:968
const value_type & const_reference
Definition rbtree.h:35
RedBlackTree & operator=(const RedBlackTree &other) FL_NOEXCEPT
Definition rbtree.h:716
const_iterator begin() const
Definition rbtree.h:760
void transplant(RBNode *u, RBNode *v)
Definition rbtree.h:142
RedBlackTree(const RedBlackTree &other) FL_NOEXCEPT
Definition rbtree.h:709
fl::pair< iterator, bool > insertImpl(U &&value)
Definition rbtree.h:266
RBNode * maximum(RBNode *x) const
Definition rbtree.h:162
void rotateLeft(RBNode *x)
Definition rbtree.h:67
~RedBlackTree() FL_NOEXCEPT
Definition rbtree.h:750
iterator find(const value_type &value)
Definition rbtree.h:916
bool contains(const value_type &value) const
Definition rbtree.h:926
const_reverse_iterator rbegin() const
Definition rbtree.h:791
const_iterator cbegin() const
Definition rbtree.h:765
const_reverse_iterator rend() const
Definition rbtree.h:796
iterator lower_bound(const value_type &value)
Definition rbtree.h:942
void insertFixup(RBNode *z)
Definition rbtree.h:103
const_iterator find(const value_type &value) const
Definition rbtree.h:921
const_iterator cend() const
Definition rbtree.h:777
const_iterator lower_bound(const value_type &value) const
Definition rbtree.h:947
RBNode * copyTree(RBNode *node, RBNode *parent=nullptr)
Definition rbtree.h:250
fl::pair< iterator, bool > insert(const value_type &value)
Definition rbtree.h:820
void destroyTree(RBNode *node)
Definition rbtree.h:241
value_type & reference
Definition rbtree.h:34
const_reverse_iterator crend() const
Definition rbtree.h:804
ptrdiff_t difference_type
Definition rbtree.h:32
const value_type * const_pointer
Definition rbtree.h:37
const_reverse_iterator crbegin() const
Definition rbtree.h:800
fl::pair< const_iterator, const_iterator > equal_range(const value_type &value) const
Definition rbtree.h:936
fl::pair< iterator, bool > insert(value_type &&value)
Definition rbtree.h:824
RBNode * lowerBoundNode(const value_type &value) const
Definition rbtree.h:303
typename Allocator::template rebind< RBNode >::other NodeAllocator
Definition rbtree.h:59
RBNode * findNode(const value_type &value) const
Definition rbtree.h:227
value_type * pointer
Definition rbtree.h:36
void deleteFixup(RBNode *x, RBNode *xParent)
Definition rbtree.h:170
fl::size erase(const Key &key)
Definition rbtree.h:1514
Compare key_compare
Definition rbtree.h:1446
const value_type * pointer
Definition rbtree.h:1449
const_iterator cbegin() const
Definition rbtree.h:1475
fl::size size_type
Definition rbtree.h:1444
bool contains(const Key &key) const
Definition rbtree.h:1531
void swap(SetRedBlackTree &other)
Definition rbtree.h:1518
fl::pair< const_iterator, bool > insert(value_type &&value)
Definition rbtree.h:1499
fl::size size() const
Definition rbtree.h:1485
const_iterator lower_bound(const Key &key) const
Definition rbtree.h:1539
key_compare key_comp() const
Definition rbtree.h:1548
fl::pair< const_iterator, const_iterator > equal_range(const Key &key) const
Definition rbtree.h:1535
allocator_type get_allocator() const
Definition rbtree.h:1489
fl::pair< const_iterator, bool > emplace(Args &&... args)
Definition rbtree.h:1505
ptrdiff_t difference_type
Definition rbtree.h:1445
const_iterator erase(const_iterator pos)
Definition rbtree.h:1510
const_reverse_iterator rbegin() const
Definition rbtree.h:1480
typename TreeType::const_reverse_iterator const_reverse_iterator
Definition rbtree.h:1461
fl::pair< const_iterator, bool > insert(const value_type &value)
Definition rbtree.h:1494
const value_type & reference
Definition rbtree.h:1447
typename TreeType::const_iterator iterator
Definition rbtree.h:1458
Allocator allocator_type
Definition rbtree.h:1451
typename TreeType::const_reverse_iterator reverse_iterator
Definition rbtree.h:1460
const_iterator upper_bound(const Key &key) const
Definition rbtree.h:1543
SetRedBlackTree(const Compare &comp=Compare(), const Allocator &alloc=Allocator())
Definition rbtree.h:1464
RedBlackTree< Key, Compare, Allocator > TreeType
Definition rbtree.h:1454
SetRedBlackTree & operator=(const SetRedBlackTree &other) FL_NOEXCEPT=default
typename TreeType::const_iterator const_iterator
Definition rbtree.h:1459
bool operator!=(const SetRedBlackTree &other) const
Definition rbtree.h:1557
const_iterator find(const Key &key) const
Definition rbtree.h:1527
const value_type * const_pointer
Definition rbtree.h:1450
fl::size max_size() const
Definition rbtree.h:1486
bool empty() const
Definition rbtree.h:1484
SetRedBlackTree & operator=(SetRedBlackTree &&other) FL_NOEXCEPT=default
const_reverse_iterator rend() const
Definition rbtree.h:1481
fl::size count(const Key &key) const
Definition rbtree.h:1523
const_iterator end() const
Definition rbtree.h:1476
bool operator==(const SetRedBlackTree &other) const
Definition rbtree.h:1553
const value_type & const_reference
Definition rbtree.h:1448
SetRedBlackTree(const SetRedBlackTree &other) FL_NOEXCEPT=default
SetRedBlackTree(SetRedBlackTree &&other) FL_NOEXCEPT=default
const_iterator cend() const
Definition rbtree.h:1477
~SetRedBlackTree() FL_NOEXCEPT=default
constexpr T && forward(typename remove_reference< T >::type &t) FL_NOEXCEPT
Definition s16x16x4.h:234
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
Definition s16x16x4.h:28
void swap(T &a, T &b) FL_NOEXCEPT
Definition s16x16x4.h:877
constexpr int type_rank< T >::value
void init(Context &ctx, int w, int h)
Definition engine.h:133
bool lexicographical_compare(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) FL_NOEXCEPT
Definition algorithm.h:146
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
fl::ptrdiff ptrdiff_t
Definition s16x16x4.h:226
constexpr T && forward(typename remove_reference< T >::type &t) FL_NOEXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179
corkscrew_args args
Definition old.h:149
#define FL_NOEXCEPT
Definition Keyboard.h:22
PairCompare(const Compare &comp=Compare())
Definition rbtree.h:1017
bool operator()(const value_type &a, const value_type &b) const
Definition rbtree.h:1019
RBNode(const value_type &val, Color c=Color::kRed, RBNode *p=nullptr)
Definition rbtree.h:51
RBNode(Color c, RBNode *p, Args &&... args)
Definition rbtree.h:55
T1 first
Definition pair.h:16