|
37 | 37 | #include <initializer_list> |
38 | 38 |
|
39 | 39 | namespace godot { |
40 | | - |
41 | | -// based on the very nice implementation of rb-trees by: |
42 | | -// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html |
43 | | - |
| 40 | +/** |
| 41 | + * Key-value container (aka dictionary) using a red-black tree for lookup. |
| 42 | + * |
| 43 | + * Elements are ordered by key (using the < comparison operator). |
| 44 | + * Key-Values are pointer-stable until removed. |
| 45 | + * |
| 46 | + * Implementation based on: |
| 47 | + * https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html |
| 48 | + * |
| 49 | + * Core container guidance: |
| 50 | + * https://docs.godotengine.org/en/latest/engine_details/architecture/core_types.html#containers |
| 51 | + */ |
44 | 52 | template <typename K, typename V, typename C = Comparator<K>, typename A = DefaultAllocator> |
45 | | -class RBMap { |
| 53 | +class _WARN_UNUSED_ RBMap { |
46 | 54 | enum Color { |
47 | 55 | RED, |
48 | 56 | BLACK |
@@ -124,7 +132,7 @@ class RBMap { |
124 | 132 | E = p_it.E; |
125 | 133 | return *this; |
126 | 134 | } |
127 | | - Iterator(Element *p_E) { E = p_E; } |
| 135 | + Iterator(Element *p_element) { E = p_element; } |
128 | 136 | Iterator() {} |
129 | 137 | Iterator(const Iterator &p_it) { E = p_it.E; } |
130 | 138 |
|
@@ -156,7 +164,7 @@ class RBMap { |
156 | 164 | E = p_it.E; |
157 | 165 | return *this; |
158 | 166 | } |
159 | | - ConstIterator(const Element *p_E) { E = p_E; } |
| 167 | + ConstIterator(const Element *p_element) { E = p_element; } |
160 | 168 | ConstIterator() {} |
161 | 169 | ConstIterator(const ConstIterator &p_it) { E = p_it.E; } |
162 | 170 |
|
@@ -360,6 +368,23 @@ class RBMap { |
360 | 368 | return prev; |
361 | 369 | } |
362 | 370 |
|
| 371 | + Element *_lower_bound(const K &p_key) const { |
| 372 | + Element *node = _data._root->left; |
| 373 | + Element *result = nullptr; |
| 374 | + C less; |
| 375 | + |
| 376 | + while (node != _data._nil) { |
| 377 | + if (!less(node->_data.key, p_key)) { |
| 378 | + result = node; |
| 379 | + node = node->left; |
| 380 | + } else { |
| 381 | + node = node->right; |
| 382 | + } |
| 383 | + } |
| 384 | + |
| 385 | + return result; |
| 386 | + } |
| 387 | + |
363 | 388 | void _insert_rb_fix(Element *p_new_node) { |
364 | 389 | Element *node = p_new_node; |
365 | 390 | Element *nparent = node->parent; |
@@ -568,16 +593,16 @@ class RBMap { |
568 | 593 | ERR_FAIL_COND(_data._nil->color == RED); |
569 | 594 | } |
570 | 595 |
|
571 | | - void _calculate_depth(Element *p_element, int &max_d, int d) const { |
| 596 | + void _calculate_depth(Element *p_element, int &p_max_d, int p_d) const { |
572 | 597 | if (p_element == _data._nil) { |
573 | 598 | return; |
574 | 599 | } |
575 | 600 |
|
576 | | - _calculate_depth(p_element->left, max_d, d + 1); |
577 | | - _calculate_depth(p_element->right, max_d, d + 1); |
| 601 | + _calculate_depth(p_element->left, p_max_d, p_d + 1); |
| 602 | + _calculate_depth(p_element->right, p_max_d, p_d + 1); |
578 | 603 |
|
579 | | - if (d > max_d) { |
580 | | - max_d = d; |
| 604 | + if (p_d > p_max_d) { |
| 605 | + p_max_d = p_d; |
581 | 606 | } |
582 | 607 | } |
583 | 608 |
|
@@ -636,6 +661,20 @@ class RBMap { |
636 | 661 | return res; |
637 | 662 | } |
638 | 663 |
|
| 664 | + Element *lower_bound(const K &p_key) { |
| 665 | + if (!_data._root) { |
| 666 | + return nullptr; |
| 667 | + } |
| 668 | + return _lower_bound(p_key); |
| 669 | + } |
| 670 | + |
| 671 | + const Element *lower_bound(const K &p_key) const { |
| 672 | + if (!_data._root) { |
| 673 | + return nullptr; |
| 674 | + } |
| 675 | + return _lower_bound(p_key); |
| 676 | + } |
| 677 | + |
639 | 678 | bool has(const K &p_key) const { |
640 | 679 | return find(p_key) != nullptr; |
641 | 680 | } |
@@ -759,13 +798,34 @@ class RBMap { |
759 | 798 | } |
760 | 799 |
|
761 | 800 | void operator=(const RBMap &p_map) { |
| 801 | + if (this == &p_map) { |
| 802 | + return; |
| 803 | + } |
| 804 | + |
762 | 805 | _copy_from(p_map); |
763 | 806 | } |
764 | 807 |
|
765 | | - RBMap(const RBMap &p_map) { |
| 808 | + void operator=(RBMap &&p_map) { |
| 809 | + if (this == &p_map) { |
| 810 | + return; |
| 811 | + } |
| 812 | + |
| 813 | + SWAP(_data._root, p_map._data._root); |
| 814 | + SWAP(_data.size_cache, p_map._data.size_cache); |
| 815 | + } |
| 816 | + |
| 817 | + explicit RBMap(const RBMap &p_map) { |
766 | 818 | _copy_from(p_map); |
767 | 819 | } |
768 | 820 |
|
| 821 | + RBMap(RBMap &&p_map) { |
| 822 | + _data._root = p_map._data._root; |
| 823 | + _data.size_cache = p_map._data.size_cache; |
| 824 | + |
| 825 | + p_map._data._root = nullptr; |
| 826 | + p_map._data.size_cache = 0; |
| 827 | + } |
| 828 | + |
769 | 829 | RBMap(std::initializer_list<KeyValue<K, V>> p_init) { |
770 | 830 | for (const KeyValue<K, V> &E : p_init) { |
771 | 831 | insert(E.key, E.value); |
|
0 commit comments