Coverage Report

Created: 2026-02-16 07:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/AK/RedBlackTree.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/Concepts.h>
10
#include <AK/Error.h>
11
#include <AK/Noncopyable.h>
12
#include <AK/kmalloc.h>
13
14
namespace AK {
15
16
template<Integral K>
17
class BaseRedBlackTree {
18
    AK_MAKE_NONCOPYABLE(BaseRedBlackTree);
19
    AK_MAKE_NONMOVABLE(BaseRedBlackTree);
20
21
public:
22
8.76M
    [[nodiscard]] size_t size() const { return m_size; }
23
1.58M
    [[nodiscard]] bool is_empty() const { return m_size == 0; }
AK::BaseRedBlackTree<unsigned long>::is_empty() const
Line
Count
Source
23
151k
    [[nodiscard]] bool is_empty() const { return m_size == 0; }
AK::BaseRedBlackTree<unsigned int>::is_empty() const
Line
Count
Source
23
1.43M
    [[nodiscard]] bool is_empty() const { return m_size == 0; }
24
25
    enum class Color : bool {
26
        Red,
27
        Black
28
    };
29
    struct Node {
30
        Node* left_child { nullptr };
31
        Node* right_child { nullptr };
32
        Node* parent { nullptr };
33
34
        Color color { Color::Red };
35
36
        K key;
37
38
        Node(K key)
39
65.4M
            : key(key)
40
65.4M
        {
41
65.4M
        }
AK::BaseRedBlackTree<unsigned long>::Node::Node(unsigned long)
Line
Count
Source
39
53.9M
            : key(key)
40
53.9M
        {
41
53.9M
        }
AK::BaseRedBlackTree<unsigned int>::Node::Node(unsigned int)
Line
Count
Source
39
11.4M
            : key(key)
40
11.4M
        {
41
11.4M
        }
42
        Node()
43
        {
44
        }
45
65.4M
        virtual ~Node() = default;
AK::BaseRedBlackTree<unsigned long>::Node::~Node()
Line
Count
Source
45
53.9M
        virtual ~Node() = default;
AK::BaseRedBlackTree<unsigned int>::Node::~Node()
Line
Count
Source
45
11.4M
        virtual ~Node() = default;
46
    };
47
48
protected:
49
9.13M
    BaseRedBlackTree() = default; // These are protected to ensure no one instantiates the leaky base red black tree directly
AK::BaseRedBlackTree<unsigned long>::BaseRedBlackTree()
Line
Count
Source
49
4.04M
    BaseRedBlackTree() = default; // These are protected to ensure no one instantiates the leaky base red black tree directly
AK::BaseRedBlackTree<unsigned int>::BaseRedBlackTree()
Line
Count
Source
49
5.08M
    BaseRedBlackTree() = default; // These are protected to ensure no one instantiates the leaky base red black tree directly
50
9.13M
    virtual ~BaseRedBlackTree() = default;
AK::BaseRedBlackTree<unsigned long>::~BaseRedBlackTree()
Line
Count
Source
50
4.04M
    virtual ~BaseRedBlackTree() = default;
AK::BaseRedBlackTree<unsigned int>::~BaseRedBlackTree()
Line
Count
Source
50
5.08M
    virtual ~BaseRedBlackTree() = default;
51
52
    void rotate_left(Node* subtree_root)
53
57.5M
    {
54
57.5M
        VERIFY(subtree_root);
55
57.5M
        auto* pivot = subtree_root->right_child;
56
57.5M
        VERIFY(pivot);
57
57.5M
        auto* parent = subtree_root->parent;
58
59
        // stage 1 - subtree_root's right child is now pivot's left child
60
57.5M
        subtree_root->right_child = pivot->left_child;
61
57.5M
        if (subtree_root->right_child)
62
28.5M
            subtree_root->right_child->parent = subtree_root;
63
64
        // stage 2 - pivot's left child is now subtree_root
65
57.5M
        pivot->left_child = subtree_root;
66
57.5M
        subtree_root->parent = pivot;
67
68
        // stage 3 - update pivot's parent
69
57.5M
        pivot->parent = parent;
70
57.5M
        if (!parent) { // new root
71
201k
            m_root = pivot;
72
57.3M
        } else if (parent->left_child == subtree_root) { // we are the left child
73
12.1M
            parent->left_child = pivot;
74
45.2M
        } else { // we are the right child
75
45.2M
            parent->right_child = pivot;
76
45.2M
        }
77
57.5M
    }
AK::BaseRedBlackTree<unsigned long>::rotate_left(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
53
49.4M
    {
54
49.4M
        VERIFY(subtree_root);
55
49.4M
        auto* pivot = subtree_root->right_child;
56
49.4M
        VERIFY(pivot);
57
49.4M
        auto* parent = subtree_root->parent;
58
59
        // stage 1 - subtree_root's right child is now pivot's left child
60
49.4M
        subtree_root->right_child = pivot->left_child;
61
49.4M
        if (subtree_root->right_child)
62
24.5M
            subtree_root->right_child->parent = subtree_root;
63
64
        // stage 2 - pivot's left child is now subtree_root
65
49.4M
        pivot->left_child = subtree_root;
66
49.4M
        subtree_root->parent = pivot;
67
68
        // stage 3 - update pivot's parent
69
49.4M
        pivot->parent = parent;
70
49.4M
        if (!parent) { // new root
71
124k
            m_root = pivot;
72
49.3M
        } else if (parent->left_child == subtree_root) { // we are the left child
73
11.3M
            parent->left_child = pivot;
74
37.9M
        } else { // we are the right child
75
37.9M
            parent->right_child = pivot;
76
37.9M
        }
77
49.4M
    }
AK::BaseRedBlackTree<unsigned int>::rotate_left(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
53
8.15M
    {
54
8.15M
        VERIFY(subtree_root);
55
8.15M
        auto* pivot = subtree_root->right_child;
56
8.15M
        VERIFY(pivot);
57
8.15M
        auto* parent = subtree_root->parent;
58
59
        // stage 1 - subtree_root's right child is now pivot's left child
60
8.15M
        subtree_root->right_child = pivot->left_child;
61
8.15M
        if (subtree_root->right_child)
62
4.00M
            subtree_root->right_child->parent = subtree_root;
63
64
        // stage 2 - pivot's left child is now subtree_root
65
8.15M
        pivot->left_child = subtree_root;
66
8.15M
        subtree_root->parent = pivot;
67
68
        // stage 3 - update pivot's parent
69
8.15M
        pivot->parent = parent;
70
8.15M
        if (!parent) { // new root
71
76.9k
            m_root = pivot;
72
8.07M
        } else if (parent->left_child == subtree_root) { // we are the left child
73
774k
            parent->left_child = pivot;
74
7.29M
        } else { // we are the right child
75
7.29M
            parent->right_child = pivot;
76
7.29M
        }
77
8.15M
    }
78
79
    void rotate_right(Node* subtree_root)
80
9.15M
    {
81
9.15M
        VERIFY(subtree_root);
82
9.15M
        auto* pivot = subtree_root->left_child;
83
9.15M
        VERIFY(pivot);
84
9.15M
        auto* parent = subtree_root->parent;
85
86
        // stage 1 - subtree_root's left child is now pivot's right child
87
9.15M
        subtree_root->left_child = pivot->right_child;
88
9.15M
        if (subtree_root->left_child)
89
4.41M
            subtree_root->left_child->parent = subtree_root;
90
91
        // stage 2 - pivot's right child is now subtree_root
92
9.15M
        pivot->right_child = subtree_root;
93
9.15M
        subtree_root->parent = pivot;
94
95
        // stage 3 - update pivot's parent
96
9.15M
        pivot->parent = parent;
97
9.15M
        if (!parent) { // new root
98
269k
            m_root = pivot;
99
8.88M
        } else if (parent->left_child == subtree_root) { // we are the left child
100
1.18M
            parent->left_child = pivot;
101
7.70M
        } else { // we are the right child
102
7.70M
            parent->right_child = pivot;
103
7.70M
        }
104
9.15M
    }
AK::BaseRedBlackTree<unsigned long>::rotate_right(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
80
8.42M
    {
81
8.42M
        VERIFY(subtree_root);
82
8.42M
        auto* pivot = subtree_root->left_child;
83
8.42M
        VERIFY(pivot);
84
8.42M
        auto* parent = subtree_root->parent;
85
86
        // stage 1 - subtree_root's left child is now pivot's right child
87
8.42M
        subtree_root->left_child = pivot->right_child;
88
8.42M
        if (subtree_root->left_child)
89
4.06M
            subtree_root->left_child->parent = subtree_root;
90
91
        // stage 2 - pivot's right child is now subtree_root
92
8.42M
        pivot->right_child = subtree_root;
93
8.42M
        subtree_root->parent = pivot;
94
95
        // stage 3 - update pivot's parent
96
8.42M
        pivot->parent = parent;
97
8.42M
        if (!parent) { // new root
98
3.92k
            m_root = pivot;
99
8.41M
        } else if (parent->left_child == subtree_root) { // we are the left child
100
1.14M
            parent->left_child = pivot;
101
7.26M
        } else { // we are the right child
102
7.26M
            parent->right_child = pivot;
103
7.26M
        }
104
8.42M
    }
AK::BaseRedBlackTree<unsigned int>::rotate_right(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
80
735k
    {
81
735k
        VERIFY(subtree_root);
82
735k
        auto* pivot = subtree_root->left_child;
83
735k
        VERIFY(pivot);
84
735k
        auto* parent = subtree_root->parent;
85
86
        // stage 1 - subtree_root's left child is now pivot's right child
87
735k
        subtree_root->left_child = pivot->right_child;
88
735k
        if (subtree_root->left_child)
89
350k
            subtree_root->left_child->parent = subtree_root;
90
91
        // stage 2 - pivot's right child is now subtree_root
92
735k
        pivot->right_child = subtree_root;
93
735k
        subtree_root->parent = pivot;
94
95
        // stage 3 - update pivot's parent
96
735k
        pivot->parent = parent;
97
735k
        if (!parent) { // new root
98
265k
            m_root = pivot;
99
469k
        } else if (parent->left_child == subtree_root) { // we are the left child
100
37.1k
            parent->left_child = pivot;
101
432k
        } else { // we are the right child
102
432k
            parent->right_child = pivot;
103
432k
        }
104
735k
    }
105
106
    static Node* find(Node* node, K key)
107
16.4k
    {
108
59.5k
        while (node && node->key != key) {
109
43.0k
            if (key < node->key) {
110
7.49k
                node = node->left_child;
111
35.5k
            } else {
112
35.5k
                node = node->right_child;
113
35.5k
            }
114
43.0k
        }
115
16.4k
        return node;
116
16.4k
    }
AK::BaseRedBlackTree<unsigned long>::find(AK::BaseRedBlackTree<unsigned long>::Node*, unsigned long)
Line
Count
Source
107
16.4k
    {
108
59.5k
        while (node && node->key != key) {
109
43.0k
            if (key < node->key) {
110
7.49k
                node = node->left_child;
111
35.5k
            } else {
112
35.5k
                node = node->right_child;
113
35.5k
            }
114
43.0k
        }
115
16.4k
        return node;
116
16.4k
    }
Unexecuted instantiation: AK::BaseRedBlackTree<unsigned int>::find(AK::BaseRedBlackTree<unsigned int>::Node*, unsigned int)
117
118
    static Node* find_largest_not_above(Node* node, K key)
119
40.5M
    {
120
40.5M
        Node* candidate = nullptr;
121
154M
        while (node) {
122
116M
            if (key == node->key)
123
1.85M
                return node;
124
114M
            if (key < node->key) {
125
42.2M
                node = node->left_child;
126
72.1M
            } else {
127
72.1M
                candidate = node;
128
72.1M
                node = node->right_child;
129
72.1M
            }
130
114M
        }
131
38.7M
        return candidate;
132
40.5M
    }
AK::BaseRedBlackTree<unsigned long>::find_largest_not_above(AK::BaseRedBlackTree<unsigned long>::Node*, unsigned long)
Line
Count
Source
119
40.5M
    {
120
40.5M
        Node* candidate = nullptr;
121
154M
        while (node) {
122
116M
            if (key == node->key)
123
1.85M
                return node;
124
114M
            if (key < node->key) {
125
42.2M
                node = node->left_child;
126
72.1M
            } else {
127
72.1M
                candidate = node;
128
72.1M
                node = node->right_child;
129
72.1M
            }
130
114M
        }
131
38.7M
        return candidate;
132
40.5M
    }
Unexecuted instantiation: AK::BaseRedBlackTree<unsigned int>::find_largest_not_above(AK::BaseRedBlackTree<unsigned int>::Node*, unsigned int)
133
134
    static Node* find_smallest_not_below(Node* node, K key)
135
6.67M
    {
136
6.67M
        Node* candidate = nullptr;
137
17.8M
        while (node) {
138
11.4M
            if (node->key == key)
139
273k
                return node;
140
141
11.1M
            if (node->key <= key) {
142
1.60M
                node = node->right_child;
143
9.56M
            } else {
144
9.56M
                candidate = node;
145
9.56M
                node = node->left_child;
146
9.56M
            }
147
11.1M
        }
148
6.39M
        return candidate;
149
6.67M
    }
Unexecuted instantiation: AK::BaseRedBlackTree<unsigned long>::find_smallest_not_below(AK::BaseRedBlackTree<unsigned long>::Node*, unsigned long)
AK::BaseRedBlackTree<unsigned int>::find_smallest_not_below(AK::BaseRedBlackTree<unsigned int>::Node*, unsigned int)
Line
Count
Source
135
6.67M
    {
136
6.67M
        Node* candidate = nullptr;
137
17.8M
        while (node) {
138
11.4M
            if (node->key == key)
139
273k
                return node;
140
141
11.1M
            if (node->key <= key) {
142
1.60M
                node = node->right_child;
143
9.56M
            } else {
144
9.56M
                candidate = node;
145
9.56M
                node = node->left_child;
146
9.56M
            }
147
11.1M
        }
148
6.39M
        return candidate;
149
6.67M
    }
150
151
    void insert(Node* node)
152
65.4M
    {
153
65.4M
        VERIFY(node);
154
65.4M
        Node* parent = nullptr;
155
65.4M
        Node* temp = m_root;
156
1.71G
        while (temp) {
157
1.65G
            parent = temp;
158
1.65G
            if (node->key < temp->key)
159
111M
                temp = temp->left_child;
160
1.54G
            else
161
1.54G
                temp = temp->right_child;
162
1.65G
        }
163
65.4M
        if (!parent) { // new root
164
6.51M
            node->color = Color::Black;
165
6.51M
            m_root = node;
166
6.51M
            m_size = 1;
167
6.51M
            m_minimum = node;
168
6.51M
            return;
169
6.51M
        }
170
58.8M
        if (node->key < parent->key) // we are the left child
171
5.06M
            parent->left_child = node;
172
53.8M
        else // we are the right child
173
53.8M
            parent->right_child = node;
174
58.8M
        node->parent = parent;
175
176
58.8M
        if (node->parent->parent) // no fixups to be done for a height <= 2 tree
177
58.3M
            insert_fixups(node);
178
179
58.8M
        m_size++;
180
58.8M
        if (m_minimum->left_child == node)
181
551k
            m_minimum = node;
182
58.8M
    }
AK::BaseRedBlackTree<unsigned long>::insert(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
152
53.9M
    {
153
53.9M
        VERIFY(node);
154
53.9M
        Node* parent = nullptr;
155
53.9M
        Node* temp = m_root;
156
1.51G
        while (temp) {
157
1.46G
            parent = temp;
158
1.46G
            if (node->key < temp->key)
159
106M
                temp = temp->left_child;
160
1.35G
            else
161
1.35G
                temp = temp->right_child;
162
1.46G
        }
163
53.9M
        if (!parent) { // new root
164
3.97M
            node->color = Color::Black;
165
3.97M
            m_root = node;
166
3.97M
            m_size = 1;
167
3.97M
            m_minimum = node;
168
3.97M
            return;
169
3.97M
        }
170
50.0M
        if (node->key < parent->key) // we are the left child
171
4.39M
            parent->left_child = node;
172
45.6M
        else // we are the right child
173
45.6M
            parent->right_child = node;
174
50.0M
        node->parent = parent;
175
176
50.0M
        if (node->parent->parent) // no fixups to be done for a height <= 2 tree
177
49.7M
            insert_fixups(node);
178
179
50.0M
        m_size++;
180
50.0M
        if (m_minimum->left_child == node)
181
12.0k
            m_minimum = node;
182
50.0M
    }
AK::BaseRedBlackTree<unsigned int>::insert(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
152
11.4M
    {
153
11.4M
        VERIFY(node);
154
11.4M
        Node* parent = nullptr;
155
11.4M
        Node* temp = m_root;
156
202M
        while (temp) {
157
191M
            parent = temp;
158
191M
            if (node->key < temp->key)
159
4.37M
                temp = temp->left_child;
160
186M
            else
161
186M
                temp = temp->right_child;
162
191M
        }
163
11.4M
        if (!parent) { // new root
164
2.53M
            node->color = Color::Black;
165
2.53M
            m_root = node;
166
2.53M
            m_size = 1;
167
2.53M
            m_minimum = node;
168
2.53M
            return;
169
2.53M
        }
170
8.87M
        if (node->key < parent->key) // we are the left child
171
667k
            parent->left_child = node;
172
8.20M
        else // we are the right child
173
8.20M
            parent->right_child = node;
174
8.87M
        node->parent = parent;
175
176
8.87M
        if (node->parent->parent) // no fixups to be done for a height <= 2 tree
177
8.58M
            insert_fixups(node);
178
179
8.87M
        m_size++;
180
8.87M
        if (m_minimum->left_child == node)
181
539k
            m_minimum = node;
182
8.87M
    }
183
184
    void insert_fixups(Node* node)
185
58.3M
    {
186
58.3M
        VERIFY(node && node->color == Color::Red);
187
173M
        while (node->parent && node->parent->color == Color::Red) {
188
115M
            auto* grand_parent = node->parent->parent;
189
115M
            if (grand_parent->right_child == node->parent) {
190
106M
                auto* uncle = grand_parent->left_child;
191
106M
                if (uncle && uncle->color == Color::Red) {
192
57.4M
                    node->parent->color = Color::Black;
193
57.4M
                    uncle->color = Color::Black;
194
57.4M
                    grand_parent->color = Color::Red;
195
57.4M
                    node = grand_parent;
196
57.4M
                } else {
197
48.7M
                    if (node->parent->left_child == node) {
198
48.2k
                        node = node->parent;
199
48.2k
                        rotate_right(node);
200
48.2k
                    }
201
48.7M
                    node->parent->color = Color::Black;
202
48.7M
                    grand_parent->color = Color::Red;
203
48.7M
                    rotate_left(grand_parent);
204
48.7M
                }
205
106M
            } else {
206
9.19M
                auto* uncle = grand_parent->right_child;
207
9.19M
                if (uncle && uncle->color == Color::Red) {
208
87.1k
                    node->parent->color = Color::Black;
209
87.1k
                    uncle->color = Color::Black;
210
87.1k
                    grand_parent->color = Color::Red;
211
87.1k
                    node = grand_parent;
212
9.10M
                } else {
213
9.10M
                    if (node->parent->right_child == node) {
214
8.82M
                        node = node->parent;
215
8.82M
                        rotate_left(node);
216
8.82M
                    }
217
9.10M
                    node->parent->color = Color::Black;
218
9.10M
                    grand_parent->color = Color::Red;
219
9.10M
                    rotate_right(grand_parent);
220
9.10M
                }
221
9.19M
            }
222
115M
        }
223
58.3M
        m_root->color = Color::Black; // the root should always be black
224
58.3M
    }
AK::BaseRedBlackTree<unsigned long>::insert_fixups(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
185
49.7M
    {
186
49.7M
        VERIFY(node && node->color == Color::Red);
187
148M
        while (node->parent && node->parent->color == Color::Red) {
188
98.8M
            auto* grand_parent = node->parent->parent;
189
98.8M
            if (grand_parent->right_child == node->parent) {
190
90.3M
                auto* uncle = grand_parent->left_child;
191
90.3M
                if (uncle && uncle->color == Color::Red) {
192
49.3M
                    node->parent->color = Color::Black;
193
49.3M
                    uncle->color = Color::Black;
194
49.3M
                    grand_parent->color = Color::Red;
195
49.3M
                    node = grand_parent;
196
49.3M
                } else {
197
41.0M
                    if (node->parent->left_child == node) {
198
30.6k
                        node = node->parent;
199
30.6k
                        rotate_right(node);
200
30.6k
                    }
201
41.0M
                    node->parent->color = Color::Black;
202
41.0M
                    grand_parent->color = Color::Red;
203
41.0M
                    rotate_left(grand_parent);
204
41.0M
                }
205
90.3M
            } else {
206
8.46M
                auto* uncle = grand_parent->right_child;
207
8.46M
                if (uncle && uncle->color == Color::Red) {
208
77.6k
                    node->parent->color = Color::Black;
209
77.6k
                    uncle->color = Color::Black;
210
77.6k
                    grand_parent->color = Color::Red;
211
77.6k
                    node = grand_parent;
212
8.38M
                } else {
213
8.38M
                    if (node->parent->right_child == node) {
214
8.37M
                        node = node->parent;
215
8.37M
                        rotate_left(node);
216
8.37M
                    }
217
8.38M
                    node->parent->color = Color::Black;
218
8.38M
                    grand_parent->color = Color::Red;
219
8.38M
                    rotate_right(grand_parent);
220
8.38M
                }
221
8.46M
            }
222
98.8M
        }
223
49.7M
        m_root->color = Color::Black; // the root should always be black
224
49.7M
    }
AK::BaseRedBlackTree<unsigned int>::insert_fixups(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
185
8.58M
    {
186
8.58M
        VERIFY(node && node->color == Color::Red);
187
25.1M
        while (node->parent && node->parent->color == Color::Red) {
188
16.5M
            auto* grand_parent = node->parent->parent;
189
16.5M
            if (grand_parent->right_child == node->parent) {
190
15.8M
                auto* uncle = grand_parent->left_child;
191
15.8M
                if (uncle && uncle->color == Color::Red) {
192
8.12M
                    node->parent->color = Color::Black;
193
8.12M
                    uncle->color = Color::Black;
194
8.12M
                    grand_parent->color = Color::Red;
195
8.12M
                    node = grand_parent;
196
8.12M
                } else {
197
7.69M
                    if (node->parent->left_child == node) {
198
17.6k
                        node = node->parent;
199
17.6k
                        rotate_right(node);
200
17.6k
                    }
201
7.69M
                    node->parent->color = Color::Black;
202
7.69M
                    grand_parent->color = Color::Red;
203
7.69M
                    rotate_left(grand_parent);
204
7.69M
                }
205
15.8M
            } else {
206
726k
                auto* uncle = grand_parent->right_child;
207
726k
                if (uncle && uncle->color == Color::Red) {
208
9.46k
                    node->parent->color = Color::Black;
209
9.46k
                    uncle->color = Color::Black;
210
9.46k
                    grand_parent->color = Color::Red;
211
9.46k
                    node = grand_parent;
212
717k
                } else {
213
717k
                    if (node->parent->right_child == node) {
214
451k
                        node = node->parent;
215
451k
                        rotate_left(node);
216
451k
                    }
217
717k
                    node->parent->color = Color::Black;
218
717k
                    grand_parent->color = Color::Red;
219
717k
                    rotate_right(grand_parent);
220
717k
                }
221
726k
            }
222
16.5M
        }
223
8.58M
        m_root->color = Color::Black; // the root should always be black
224
8.58M
    }
225
226
    void remove(Node* node)
227
0
    {
228
0
        VERIFY(node);
229
230
        // special case: deleting the only node
231
0
        if (m_size == 1) {
232
0
            m_root = nullptr;
233
0
            m_minimum = nullptr;
234
0
            m_size = 0;
235
0
            return;
236
0
        }
237
238
0
        if (m_minimum == node)
239
0
            m_minimum = successor(node);
240
241
        // removal assumes the node has 0 or 1 child, so if we have 2, relink with the successor first (by definition the successor has no left child)
242
        // FIXME: since we dont know how a value is represented in the node, we can't simply swap the values and keys, and instead we relink the nodes
243
        //  in place, this is quite a bit more expensive, as well as much less readable, is there a better way?
244
0
        if (node->left_child && node->right_child) {
245
0
            auto* successor_node = successor(node); // this is always non-null as all nodes besides the maximum node have a successor, and the maximum node has no right child
246
0
            auto neighbor_swap = successor_node->parent == node;
247
0
            node->left_child->parent = successor_node;
248
0
            if (!neighbor_swap)
249
0
                node->right_child->parent = successor_node;
250
0
            if (node->parent) {
251
0
                if (node->parent->left_child == node) {
252
0
                    node->parent->left_child = successor_node;
253
0
                } else {
254
0
                    node->parent->right_child = successor_node;
255
0
                }
256
0
            } else {
257
0
                m_root = successor_node;
258
0
            }
259
0
            if (successor_node->right_child)
260
0
                successor_node->right_child->parent = node;
261
0
            if (neighbor_swap) {
262
0
                successor_node->parent = node->parent;
263
0
                node->parent = successor_node;
264
0
            } else {
265
0
                if (successor_node->parent) {
266
0
                    if (successor_node->parent->left_child == successor_node) {
267
0
                        successor_node->parent->left_child = node;
268
0
                    } else {
269
0
                        successor_node->parent->right_child = node;
270
0
                    }
271
0
                } else {
272
0
                    m_root = node;
273
0
                }
274
0
                swap(node->parent, successor_node->parent);
275
0
            }
276
0
            swap(node->left_child, successor_node->left_child);
277
0
            if (neighbor_swap) {
278
0
                node->right_child = successor_node->right_child;
279
0
                successor_node->right_child = node;
280
0
            } else {
281
0
                swap(node->right_child, successor_node->right_child);
282
0
            }
283
0
            swap(node->color, successor_node->color);
284
0
        }
285
286
0
        auto* child = node->left_child ?: node->right_child;
287
288
0
        if (child)
289
0
            child->parent = node->parent;
290
0
        if (node->parent) {
291
0
            if (node->parent->left_child == node)
292
0
                node->parent->left_child = child;
293
0
            else
294
0
                node->parent->right_child = child;
295
0
        } else {
296
0
            m_root = child;
297
0
        }
298
299
        // if the node is red then child must be black, and just replacing the node with its child should result in a valid tree (no change to black height)
300
0
        if (node->color != Color::Red)
301
0
            remove_fixups(child, node->parent);
302
303
0
        m_size--;
304
0
    }
Unexecuted instantiation: AK::BaseRedBlackTree<unsigned long>::remove(AK::BaseRedBlackTree<unsigned long>::Node*)
Unexecuted instantiation: AK::BaseRedBlackTree<unsigned int>::remove(AK::BaseRedBlackTree<unsigned int>::Node*)
305
306
    // We maintain parent as a separate argument since node might be null
307
    void remove_fixups(Node* node, Node* parent)
308
0
    {
309
0
        while (node != m_root && (!node || node->color == Color::Black)) {
310
0
            if (parent->left_child == node) {
311
0
                auto* sibling = parent->right_child;
312
0
                if (sibling->color == Color::Red) {
313
0
                    sibling->color = Color::Black;
314
0
                    parent->color = Color::Red;
315
0
                    rotate_left(parent);
316
0
                    sibling = parent->right_child;
317
0
                }
318
0
                if ((!sibling->left_child || sibling->left_child->color == Color::Black) && (!sibling->right_child || sibling->right_child->color == Color::Black)) {
319
0
                    sibling->color = Color::Red;
320
0
                    node = parent;
321
0
                } else {
322
0
                    if (!sibling->right_child || sibling->right_child->color == Color::Black) {
323
0
                        sibling->left_child->color = Color::Black; // null check?
324
0
                        sibling->color = Color::Red;
325
0
                        rotate_right(sibling);
326
0
                        sibling = parent->right_child;
327
0
                    }
328
0
                    sibling->color = parent->color;
329
0
                    parent->color = Color::Black;
330
0
                    sibling->right_child->color = Color::Black; // null check?
331
0
                    rotate_left(parent);
332
0
                    node = m_root; // fixed
333
0
                }
334
0
            } else {
335
0
                auto* sibling = parent->left_child;
336
0
                if (sibling->color == Color::Red) {
337
0
                    sibling->color = Color::Black;
338
0
                    parent->color = Color::Red;
339
0
                    rotate_right(parent);
340
0
                    sibling = parent->left_child;
341
0
                }
342
0
                if ((!sibling->left_child || sibling->left_child->color == Color::Black) && (!sibling->right_child || sibling->right_child->color == Color::Black)) {
343
0
                    sibling->color = Color::Red;
344
0
                    node = parent;
345
0
                } else {
346
0
                    if (!sibling->left_child || sibling->left_child->color == Color::Black) {
347
0
                        sibling->right_child->color = Color::Black; // null check?
348
0
                        sibling->color = Color::Red;
349
0
                        rotate_left(sibling);
350
0
                        sibling = parent->left_child;
351
0
                    }
352
0
                    sibling->color = parent->color;
353
0
                    parent->color = Color::Black;
354
0
                    sibling->left_child->color = Color::Black; // null check?
355
0
                    rotate_right(parent);
356
0
                    node = m_root; // fixed
357
0
                }
358
0
            }
359
0
            parent = node->parent;
360
0
        }
361
0
        node->color = Color::Black; // by this point node can't be null
362
0
    }
Unexecuted instantiation: AK::BaseRedBlackTree<unsigned long>::remove_fixups(AK::BaseRedBlackTree<unsigned long>::Node*, AK::BaseRedBlackTree<unsigned long>::Node*)
Unexecuted instantiation: AK::BaseRedBlackTree<unsigned int>::remove_fixups(AK::BaseRedBlackTree<unsigned int>::Node*, AK::BaseRedBlackTree<unsigned int>::Node*)
363
364
    static Node* successor(Node* node)
365
49.6M
    {
366
49.6M
        VERIFY(node);
367
49.6M
        if (node->right_child) {
368
24.1M
            node = node->right_child;
369
46.9M
            while (node->left_child)
370
22.7M
                node = node->left_child;
371
24.1M
            return node;
372
24.1M
        }
373
25.5M
        auto temp = node->parent;
374
48.3M
        while (temp && node == temp->right_child) {
375
22.8M
            node = temp;
376
22.8M
            temp = temp->parent;
377
22.8M
        }
378
25.5M
        return temp;
379
49.6M
    }
AK::BaseRedBlackTree<unsigned long>::successor(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
365
40.6M
    {
366
40.6M
        VERIFY(node);
367
40.6M
        if (node->right_child) {
368
20.3M
            node = node->right_child;
369
40.5M
            while (node->left_child)
370
20.2M
                node = node->left_child;
371
20.3M
            return node;
372
20.3M
        }
373
20.3M
        auto temp = node->parent;
374
40.6M
        while (temp && node == temp->right_child) {
375
20.3M
            node = temp;
376
20.3M
            temp = temp->parent;
377
20.3M
        }
378
20.3M
        return temp;
379
40.6M
    }
AK::BaseRedBlackTree<unsigned int>::successor(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
365
9.02M
    {
366
9.02M
        VERIFY(node);
367
9.02M
        if (node->right_child) {
368
3.80M
            node = node->right_child;
369
6.34M
            while (node->left_child)
370
2.53M
                node = node->left_child;
371
3.80M
            return node;
372
3.80M
        }
373
5.22M
        auto temp = node->parent;
374
7.75M
        while (temp && node == temp->right_child) {
375
2.53M
            node = temp;
376
2.53M
            temp = temp->parent;
377
2.53M
        }
378
5.22M
        return temp;
379
9.02M
    }
380
381
    static Node* predecessor(Node* node)
382
40.5M
    {
383
40.5M
        VERIFY(node);
384
40.5M
        if (node->left_child) {
385
13.6M
            node = node->left_child;
386
14.1M
            while (node->right_child)
387
478k
                node = node->right_child;
388
13.6M
            return node;
389
13.6M
        }
390
26.9M
        auto temp = node->parent;
391
27.8M
        while (temp && node == temp->left_child) {
392
914k
            node = temp;
393
914k
            temp = temp->parent;
394
914k
        }
395
26.9M
        return temp;
396
40.5M
    }
AK::BaseRedBlackTree<unsigned long>::predecessor(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
382
40.5M
    {
383
40.5M
        VERIFY(node);
384
40.5M
        if (node->left_child) {
385
13.6M
            node = node->left_child;
386
14.1M
            while (node->right_child)
387
478k
                node = node->right_child;
388
13.6M
            return node;
389
13.6M
        }
390
26.9M
        auto temp = node->parent;
391
27.8M
        while (temp && node == temp->left_child) {
392
914k
            node = temp;
393
914k
            temp = temp->parent;
394
914k
        }
395
26.9M
        return temp;
396
40.5M
    }
Unexecuted instantiation: AK::BaseRedBlackTree<unsigned int>::predecessor(AK::BaseRedBlackTree<unsigned int>::Node*)
397
398
    Node* m_root { nullptr };
399
    size_t m_size { 0 };
400
    Node* m_minimum { nullptr }; // maintained for O(1) begin()
401
};
402
403
template<typename TreeType, typename ElementType>
404
class RedBlackTreeIterator {
405
public:
406
10.4M
    RedBlackTreeIterator() = default;
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, unsigned long> const, unsigned long const>::RedBlackTreeIterator()
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value> const, JS::Value const>::RedBlackTreeIterator()
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, regex::CharRange>, regex::CharRange>::RedBlackTreeIterator()
Line
Count
Source
406
18.6k
    RedBlackTreeIterator() = default;
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::RedBlackTreeIterator()
Line
Count
Source
406
10.4M
    RedBlackTreeIterator() = default;
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> > const, AK::Optional<Line::Style::Mask> const>::RedBlackTreeIterator()
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame> const, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame const>::RedBlackTreeIterator()
407
51.1M
    bool operator!=(RedBlackTreeIterator const& other) const { return m_node != other.m_node; }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, regex::CharRange>, regex::CharRange>::operator!=(AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, regex::CharRange>, regex::CharRange> const&) const
Line
Count
Source
407
40.6M
    bool operator!=(RedBlackTreeIterator const& other) const { return m_node != other.m_node; }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::operator!=(AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int> const&) const
Line
Count
Source
407
10.4M
    bool operator!=(RedBlackTreeIterator const& other) const { return m_node != other.m_node; }
408
    RedBlackTreeIterator& operator++()
409
49.6M
    {
410
49.6M
        if (!m_node)
411
0
            return *this;
412
49.6M
        m_prev = m_node;
413
        // the complexity is O(logn) for each successor call, but the total complexity for all elements comes out to O(n), meaning the amortized cost for a single call is O(1)
414
49.6M
        m_node = static_cast<typename TreeType::Node*>(TreeType::successor(m_node));
415
49.6M
        return *this;
416
49.6M
    }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value>, JS::Value>::operator++()
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, regex::CharRange>, regex::CharRange>::operator++()
Line
Count
Source
409
40.6M
    {
410
40.6M
        if (!m_node)
411
0
            return *this;
412
40.6M
        m_prev = m_node;
413
        // the complexity is O(logn) for each successor call, but the total complexity for all elements comes out to O(n), meaning the amortized cost for a single call is O(1)
414
40.6M
        m_node = static_cast<typename TreeType::Node*>(TreeType::successor(m_node));
415
40.6M
        return *this;
416
40.6M
    }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::operator++()
Line
Count
Source
409
9.02M
    {
410
9.02M
        if (!m_node)
411
0
            return *this;
412
9.02M
        m_prev = m_node;
413
        // the complexity is O(logn) for each successor call, but the total complexity for all elements comes out to O(n), meaning the amortized cost for a single call is O(1)
414
9.02M
        m_node = static_cast<typename TreeType::Node*>(TreeType::successor(m_node));
415
9.02M
        return *this;
416
9.02M
    }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> > const, AK::Optional<Line::Style::Mask> const>::operator++()
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame> const, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame const>::operator++()
417
    RedBlackTreeIterator& operator--()
418
    {
419
        if (!m_prev)
420
            return *this;
421
        m_node = m_prev;
422
        m_prev = static_cast<typename TreeType::Node*>(TreeType::predecessor(m_prev));
423
        return *this;
424
    }
425
91.6M
    ElementType& operator*() { return m_node->value; }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, unsigned long> const, unsigned long const>::operator*()
Line
Count
Source
425
40.5M
    ElementType& operator*() { return m_node->value; }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value> const, JS::Value const>::operator*()
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value>, JS::Value>::operator*()
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, regex::CharRange>, regex::CharRange>::operator*()
Line
Count
Source
425
40.6M
    ElementType& operator*() { return m_node->value; }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::operator*()
Line
Count
Source
425
10.4M
    ElementType& operator*() { return m_node->value; }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> > const, AK::Optional<Line::Style::Mask> const>::operator*()
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame> const, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame const>::operator*()
426
0
    ElementType* operator->() { return &m_node->value; }
427
0
    [[nodiscard]] bool is_end() const { return !m_node; }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value> const, JS::Value const>::is_end() const
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value>, JS::Value>::is_end() const
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, unsigned long> const, unsigned long const>::is_end() const
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> > const, AK::Optional<Line::Style::Mask> const>::is_end() const
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame> const, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame const>::is_end() const
428
    [[nodiscard]] bool is_begin() const { return !m_prev; }
429
430
51.0M
    [[nodiscard]] auto key() const { return m_node->key; }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, unsigned long> const, unsigned long const>::key() const
Line
Count
Source
430
40.5M
    [[nodiscard]] auto key() const { return m_node->key; }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value> const, JS::Value const>::key() const
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value>, JS::Value>::key() const
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::key() const
Line
Count
Source
430
10.4M
    [[nodiscard]] auto key() const { return m_node->key; }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> > const, AK::Optional<Line::Style::Mask> const>::key() const
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame> const, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame const>::key() const
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::key() const
431
432
private:
433
    friend TreeType;
434
    explicit RedBlackTreeIterator(typename TreeType::Node* node, typename TreeType::Node* prev = nullptr)
435
42.0M
        : m_node(node)
436
42.0M
        , m_prev(prev)
437
42.0M
    {
438
42.0M
    }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, unsigned long> const, unsigned long const>::RedBlackTreeIterator(AK::RedBlackTree<unsigned long, unsigned long>::Node*, AK::RedBlackTree<unsigned long, unsigned long>::Node*)
Line
Count
Source
435
40.5M
        : m_node(node)
436
40.5M
        , m_prev(prev)
437
40.5M
    {
438
40.5M
    }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value> const, JS::Value const>::RedBlackTreeIterator(AK::RedBlackTree<unsigned long, JS::Value>::Node*, AK::RedBlackTree<unsigned long, JS::Value>::Node*)
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, JS::Value>, JS::Value>::RedBlackTreeIterator(AK::RedBlackTree<unsigned long, JS::Value>::Node*, AK::RedBlackTree<unsigned long, JS::Value>::Node*)
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, regex::CharRange>, regex::CharRange>::RedBlackTreeIterator(AK::RedBlackTree<unsigned long, regex::CharRange>::Node*, AK::RedBlackTree<unsigned long, regex::CharRange>::Node*)
Line
Count
Source
435
18.6k
        : m_node(node)
436
18.6k
        , m_prev(prev)
437
18.6k
    {
438
18.6k
    }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::RedBlackTreeIterator(AK::RedBlackTree<unsigned int, unsigned int>::Node*, AK::RedBlackTree<unsigned int, unsigned int>::Node*)
Line
Count
Source
435
1.43M
        : m_node(node)
436
1.43M
        , m_prev(prev)
437
1.43M
    {
438
1.43M
    }
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> > const, AK::Optional<Line::Style::Mask> const>::RedBlackTreeIterator(AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::Node*, AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::Node*)
Unexecuted instantiation: AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame> const, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame const>::RedBlackTreeIterator(AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::Node*, AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::Node*)
439
    typename TreeType::Node* m_node { nullptr };
440
    typename TreeType::Node* m_prev { nullptr };
441
};
442
443
template<Integral K, typename V>
444
class RedBlackTree final : public BaseRedBlackTree<K> {
445
public:
446
9.13M
    RedBlackTree() = default;
AK::RedBlackTree<unsigned long, unsigned long>::RedBlackTree()
Line
Count
Source
446
3.95M
    RedBlackTree() = default;
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::RedBlackTree()
AK::RedBlackTree<unsigned long, regex::CharRange>::RedBlackTree()
Line
Count
Source
446
92.1k
    RedBlackTree() = default;
AK::RedBlackTree<unsigned int, unsigned int>::RedBlackTree()
Line
Count
Source
446
5.08M
    RedBlackTree() = default;
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::RedBlackTree()
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::RedBlackTree()
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::RedBlackTree()
447
    virtual ~RedBlackTree() override
448
9.13M
    {
449
9.13M
        clear();
450
9.13M
    }
AK::RedBlackTree<unsigned long, unsigned long>::~RedBlackTree()
Line
Count
Source
448
3.95M
    {
449
3.95M
        clear();
450
3.95M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::~RedBlackTree()
AK::RedBlackTree<unsigned long, regex::CharRange>::~RedBlackTree()
Line
Count
Source
448
92.1k
    {
449
92.1k
        clear();
450
92.1k
    }
AK::RedBlackTree<unsigned int, unsigned int>::~RedBlackTree()
Line
Count
Source
448
5.08M
    {
449
5.08M
        clear();
450
5.08M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::~RedBlackTree()
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::~RedBlackTree()
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::~RedBlackTree()
451
452
    using BaseTree = BaseRedBlackTree<K>;
453
454
    [[nodiscard]] V* find(K key)
455
16.4k
    {
456
16.4k
        auto* node = static_cast<Node*>(BaseTree::find(this->m_root, key));
457
16.4k
        if (!node)
458
0
            return nullptr;
459
16.4k
        return &node->value;
460
16.4k
    }
AK::RedBlackTree<unsigned long, unsigned long>::find(unsigned long)
Line
Count
Source
455
16.4k
    {
456
16.4k
        auto* node = static_cast<Node*>(BaseTree::find(this->m_root, key));
457
16.4k
        if (!node)
458
0
            return nullptr;
459
16.4k
        return &node->value;
460
16.4k
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::find(unsigned long)
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::find(unsigned long)
461
462
    [[nodiscard]] V* find_largest_not_above(K key)
463
    {
464
        auto* node = static_cast<Node*>(BaseTree::find_largest_not_above(this->m_root, key));
465
        if (!node)
466
            return nullptr;
467
        return &node->value;
468
    }
469
470
    [[nodiscard]] V* find_smallest_not_below(K key)
471
6.67M
    {
472
6.67M
        auto* node = static_cast<Node*>(BaseTree::find_smallest_not_below(this->m_root, key));
473
6.67M
        if (!node)
474
1.11M
            return nullptr;
475
5.55M
        return &node->value;
476
6.67M
    }
477
478
    ErrorOr<void> try_insert(K key, V const& value)
479
13.2M
    {
480
13.2M
        return try_insert(key, V(value));
481
13.2M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::try_insert(unsigned long, JS::Value const&)
AK::RedBlackTree<unsigned long, regex::CharRange>::try_insert(unsigned long, regex::CharRange const&)
Line
Count
Source
479
4.63M
    {
480
4.63M
        return try_insert(key, V(value));
481
4.63M
    }
AK::RedBlackTree<unsigned long, unsigned long>::try_insert(unsigned long, unsigned long const&)
Line
Count
Source
479
4.34M
    {
480
4.34M
        return try_insert(key, V(value));
481
4.34M
    }
AK::RedBlackTree<unsigned int, unsigned int>::try_insert(unsigned int, unsigned int const&)
Line
Count
Source
479
4.31M
    {
480
4.31M
        return try_insert(key, V(value));
481
4.31M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::try_insert(unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame const&)
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::try_insert(unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> const&)
482
483
    void insert(K key, V const& value)
484
13.2M
    {
485
13.2M
        MUST(try_insert(key, value));
486
13.2M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::insert(unsigned long, JS::Value const&)
AK::RedBlackTree<unsigned long, regex::CharRange>::insert(unsigned long, regex::CharRange const&)
Line
Count
Source
484
4.63M
    {
485
4.63M
        MUST(try_insert(key, value));
486
4.63M
    }
AK::RedBlackTree<unsigned long, unsigned long>::insert(unsigned long, unsigned long const&)
Line
Count
Source
484
4.34M
    {
485
4.34M
        MUST(try_insert(key, value));
486
4.34M
    }
AK::RedBlackTree<unsigned int, unsigned int>::insert(unsigned int, unsigned int const&)
Line
Count
Source
484
4.31M
    {
485
4.31M
        MUST(try_insert(key, value));
486
4.31M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::insert(unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame const&)
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::insert(unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> const&)
487
488
    ErrorOr<void> try_insert(K key, V&& value)
489
65.4M
    {
490
65.4M
        auto* node = new (nothrow) Node(key, move(value));
491
65.4M
        if (!node)
492
0
            return Error::from_errno(ENOMEM);
493
65.4M
        BaseTree::insert(node);
494
65.4M
        return {};
495
65.4M
    }
AK::RedBlackTree<unsigned long, unsigned long>::try_insert(unsigned long, unsigned long&&)
Line
Count
Source
489
13.3M
    {
490
13.3M
        auto* node = new (nothrow) Node(key, move(value));
491
13.3M
        if (!node)
492
0
            return Error::from_errno(ENOMEM);
493
13.3M
        BaseTree::insert(node);
494
13.3M
        return {};
495
13.3M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::try_insert(unsigned long, JS::Value&&)
AK::RedBlackTree<unsigned long, regex::CharRange>::try_insert(unsigned long, regex::CharRange&&)
Line
Count
Source
489
40.6M
    {
490
40.6M
        auto* node = new (nothrow) Node(key, move(value));
491
40.6M
        if (!node)
492
0
            return Error::from_errno(ENOMEM);
493
40.6M
        BaseTree::insert(node);
494
40.6M
        return {};
495
40.6M
    }
AK::RedBlackTree<unsigned int, unsigned int>::try_insert(unsigned int, unsigned int&&)
Line
Count
Source
489
11.4M
    {
490
11.4M
        auto* node = new (nothrow) Node(key, move(value));
491
11.4M
        if (!node)
492
0
            return Error::from_errno(ENOMEM);
493
11.4M
        BaseTree::insert(node);
494
11.4M
        return {};
495
11.4M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::try_insert(unsigned int, AK::Optional<Line::Style::Mask>&&)
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::try_insert(unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame&&)
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::try_insert(unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool>&&)
496
497
    void insert(K key, V&& value)
498
52.1M
    {
499
52.1M
        MUST(try_insert(key, move(value)));
500
52.1M
    }
AK::RedBlackTree<unsigned long, unsigned long>::insert(unsigned long, unsigned long&&)
Line
Count
Source
498
9.02M
    {
499
9.02M
        MUST(try_insert(key, move(value)));
500
9.02M
    }
AK::RedBlackTree<unsigned long, regex::CharRange>::insert(unsigned long, regex::CharRange&&)
Line
Count
Source
498
35.9M
    {
499
35.9M
        MUST(try_insert(key, move(value)));
500
35.9M
    }
AK::RedBlackTree<unsigned int, unsigned int>::insert(unsigned int, unsigned int&&)
Line
Count
Source
498
7.09M
    {
499
7.09M
        MUST(try_insert(key, move(value)));
500
7.09M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::insert(unsigned int, AK::Optional<Line::Style::Mask>&&)
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::insert(unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame&&)
501
502
    using Iterator = RedBlackTreeIterator<RedBlackTree, V>;
503
    friend Iterator;
504
1.45M
    Iterator begin() { return Iterator(static_cast<Node*>(this->m_minimum)); }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::begin()
AK::RedBlackTree<unsigned long, regex::CharRange>::begin()
Line
Count
Source
504
18.6k
    Iterator begin() { return Iterator(static_cast<Node*>(this->m_minimum)); }
AK::RedBlackTree<unsigned int, unsigned int>::begin()
Line
Count
Source
504
1.43M
    Iterator begin() { return Iterator(static_cast<Node*>(this->m_minimum)); }
505
10.4M
    Iterator end() { return {}; }
AK::RedBlackTree<unsigned long, regex::CharRange>::end()
Line
Count
Source
505
18.6k
    Iterator end() { return {}; }
AK::RedBlackTree<unsigned int, unsigned int>::end()
Line
Count
Source
505
10.4M
    Iterator end() { return {}; }
506
0
    Iterator begin_from(K key) { return Iterator(static_cast<Node*>(BaseTree::find(this->m_root, key))); }
507
508
    using ConstIterator = RedBlackTreeIterator<RedBlackTree const, V const>;
509
    friend ConstIterator;
510
0
    ConstIterator begin() const { return ConstIterator(static_cast<Node*>(this->m_minimum)); }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::begin() const
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::begin() const
511
0
    ConstIterator end() const { return {}; }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, unsigned long>::end() const
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::end() const
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::end() const
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::end() const
512
0
    ConstIterator begin_from(K key) const { return ConstIterator(static_cast<Node*>(BaseTree::find(this->m_root, key))); }
513
514
    ConstIterator find_largest_not_above_iterator(K key) const
515
40.5M
    {
516
40.5M
        auto node = static_cast<Node*>(BaseTree::find_largest_not_above(this->m_root, key));
517
40.5M
        if (!node)
518
0
            return end();
519
40.5M
        return ConstIterator(node, static_cast<Node*>(BaseTree::predecessor(node)));
520
40.5M
    }
AK::RedBlackTree<unsigned long, unsigned long>::find_largest_not_above_iterator(unsigned long) const
Line
Count
Source
515
40.5M
    {
516
40.5M
        auto node = static_cast<Node*>(BaseTree::find_largest_not_above(this->m_root, key));
517
40.5M
        if (!node)
518
0
            return end();
519
40.5M
        return ConstIterator(node, static_cast<Node*>(BaseTree::predecessor(node)));
520
40.5M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::find_largest_not_above_iterator(unsigned int) const
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::find_largest_not_above_iterator(unsigned long) const
521
522
    ConstIterator find_smallest_not_below_iterator(K key) const
523
0
    {
524
0
        auto node = static_cast<Node*>(BaseTree::find_smallest_not_below(this->m_root, key));
525
0
        if (!node)
526
0
            return end();
527
0
        return ConstIterator(node, static_cast<Node*>(BaseTree::predecessor(node)));
528
0
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::find_smallest_not_below_iterator(unsigned long) const
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::find_smallest_not_below_iterator(unsigned int) const
529
530
    V unsafe_remove(K key)
531
    {
532
        auto* node = BaseTree::find(this->m_root, key);
533
        VERIFY(node);
534
535
        BaseTree::remove(node);
536
537
        V temp = move(static_cast<Node*>(node)->value);
538
539
        node->right_child = nullptr;
540
        node->left_child = nullptr;
541
        delete node;
542
543
        return temp;
544
    }
545
546
    bool remove(K key)
547
0
    {
548
0
        auto* node = BaseTree::find(this->m_root, key);
549
0
        if (!node)
550
0
            return false;
551
552
0
        BaseTree::remove(node);
553
554
0
        node->right_child = nullptr;
555
0
        node->left_child = nullptr;
556
0
        delete node;
557
558
0
        return true;
559
0
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::remove(unsigned long)
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::remove(unsigned int)
560
561
    void clear()
562
9.28M
    {
563
9.28M
        delete this->m_root;
564
9.28M
        this->m_root = nullptr;
565
9.28M
        this->m_minimum = nullptr;
566
9.28M
        this->m_size = 0;
567
9.28M
    }
AK::RedBlackTree<unsigned long, unsigned long>::clear()
Line
Count
Source
562
3.95M
    {
563
3.95M
        delete this->m_root;
564
3.95M
        this->m_root = nullptr;
565
3.95M
        this->m_minimum = nullptr;
566
3.95M
        this->m_size = 0;
567
3.95M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::clear()
AK::RedBlackTree<unsigned long, regex::CharRange>::clear()
Line
Count
Source
562
241k
    {
563
241k
        delete this->m_root;
564
241k
        this->m_root = nullptr;
565
241k
        this->m_minimum = nullptr;
566
241k
        this->m_size = 0;
567
241k
    }
AK::RedBlackTree<unsigned int, unsigned int>::clear()
Line
Count
Source
562
5.08M
    {
563
5.08M
        delete this->m_root;
564
5.08M
        this->m_root = nullptr;
565
5.08M
        this->m_minimum = nullptr;
566
5.08M
        this->m_size = 0;
567
5.08M
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::clear()
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::clear()
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::clear()
568
569
private:
570
    struct Node : BaseRedBlackTree<K>::Node {
571
572
        V value;
573
574
        Node(K key, V value)
575
65.4M
            : BaseRedBlackTree<K>::Node(key)
576
40.6M
            , value(move(value))
577
65.4M
        {
578
65.4M
        }
AK::RedBlackTree<unsigned long, unsigned long>::Node::Node(unsigned long, unsigned long)
Line
Count
Source
575
13.3M
            : BaseRedBlackTree<K>::Node(key)
576
13.3M
            , value(move(value))
577
13.3M
        {
578
13.3M
        }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::Node::Node(unsigned long, JS::Value)
AK::RedBlackTree<unsigned long, regex::CharRange>::Node::Node(unsigned long, regex::CharRange)
Line
Count
Source
575
40.6M
            : BaseRedBlackTree<K>::Node(key)
576
40.6M
            , value(move(value))
577
40.6M
        {
578
40.6M
        }
AK::RedBlackTree<unsigned int, unsigned int>::Node::Node(unsigned int, unsigned int)
Line
Count
Source
575
11.4M
            : BaseRedBlackTree<K>::Node(key)
576
11.4M
            , value(move(value))
577
11.4M
        {
578
11.4M
        }
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::Node::Node(unsigned int, AK::Optional<Line::Style::Mask>)
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::Node::Node(unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame)
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::Node::Node(unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool>)
579
580
        ~Node()
581
65.4M
        {
582
65.4M
            delete this->left_child;
583
65.4M
            delete this->right_child;
584
65.4M
        }
AK::RedBlackTree<unsigned long, unsigned long>::Node::~Node()
Line
Count
Source
581
13.3M
        {
582
13.3M
            delete this->left_child;
583
13.3M
            delete this->right_child;
584
13.3M
        }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::Node::~Node()
AK::RedBlackTree<unsigned long, regex::CharRange>::Node::~Node()
Line
Count
Source
581
40.6M
        {
582
40.6M
            delete this->left_child;
583
40.6M
            delete this->right_child;
584
40.6M
        }
AK::RedBlackTree<unsigned int, unsigned int>::Node::~Node()
Line
Count
Source
581
11.4M
        {
582
11.4M
            delete this->left_child;
583
11.4M
            delete this->right_child;
584
11.4M
        }
Unexecuted instantiation: AK::RedBlackTree<unsigned int, AK::Optional<Line::Style::Mask> >::Node::~Node()
Unexecuted instantiation: AK::RedBlackTree<unsigned long, Web::Animations::KeyframeEffect::KeyFrameSet::ResolvedKeyFrame>::Node::~Node()
Unexecuted instantiation: AK::RedBlackTree<unsigned long, AK::DistinctNumeric<unsigned long, Wasm::__FunctionIndex_tag, AK::DistinctNumericFeature::Comparison, AK::DistinctNumericFeature::CastToBool> >::Node::~Node()
585
    };
586
};
587
588
}
589
590
#if USING_AK_GLOBALLY
591
using AK::RedBlackTree;
592
#endif