Coverage Report

Created: 2026-07-25 07:46

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.49M
    [[nodiscard]] size_t size() const { return m_size; }
23
51.4k
    [[nodiscard]] bool is_empty() const { return m_size == 0; }
AK::BaseRedBlackTree<unsigned long>::is_empty() const
Line
Count
Source
23
40.6k
    [[nodiscard]] bool is_empty() const { return m_size == 0; }
AK::BaseRedBlackTree<unsigned int>::is_empty() const
Line
Count
Source
23
10.8k
    [[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
68.1M
            : key(key)
40
68.1M
        {
41
68.1M
        }
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
14.2M
            : key(key)
40
14.2M
        {
41
14.2M
        }
42
        Node()
43
        {
44
        }
45
68.1M
        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
14.2M
        virtual ~Node() = default;
46
    };
47
48
protected:
49
4.73M
    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
757k
    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
3.97M
    BaseRedBlackTree() = default; // These are protected to ensure no one instantiates the leaky base red black tree directly
50
4.73M
    virtual ~BaseRedBlackTree() = default;
AK::BaseRedBlackTree<unsigned long>::~BaseRedBlackTree()
Line
Count
Source
50
757k
    virtual ~BaseRedBlackTree() = default;
AK::BaseRedBlackTree<unsigned int>::~BaseRedBlackTree()
Line
Count
Source
50
3.97M
    virtual ~BaseRedBlackTree() = default;
51
52
    void rotate_left(Node* subtree_root)
53
63.8M
    {
54
63.8M
        VERIFY(subtree_root);
55
63.8M
        auto* pivot = subtree_root->right_child;
56
63.8M
        VERIFY(pivot);
57
63.8M
        auto* parent = subtree_root->parent;
58
59
        // stage 1 - subtree_root's right child is now pivot's left child
60
63.8M
        subtree_root->right_child = pivot->left_child;
61
63.8M
        if (subtree_root->right_child)
62
31.6M
            subtree_root->right_child->parent = subtree_root;
63
64
        // stage 2 - pivot's left child is now subtree_root
65
63.8M
        pivot->left_child = subtree_root;
66
63.8M
        subtree_root->parent = pivot;
67
68
        // stage 3 - update pivot's parent
69
63.8M
        pivot->parent = parent;
70
63.8M
        if (!parent) { // new root
71
268k
            m_root = pivot;
72
63.5M
        } else if (parent->left_child == subtree_root) { // we are the left child
73
13.3M
            parent->left_child = pivot;
74
50.2M
        } else { // we are the right child
75
50.2M
            parent->right_child = pivot;
76
50.2M
        }
77
63.8M
    }
AK::BaseRedBlackTree<unsigned long>::rotate_left(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
53
52.4M
    {
54
52.4M
        VERIFY(subtree_root);
55
52.4M
        auto* pivot = subtree_root->right_child;
56
52.4M
        VERIFY(pivot);
57
52.4M
        auto* parent = subtree_root->parent;
58
59
        // stage 1 - subtree_root's right child is now pivot's left child
60
52.4M
        subtree_root->right_child = pivot->left_child;
61
52.4M
        if (subtree_root->right_child)
62
26.0M
            subtree_root->right_child->parent = subtree_root;
63
64
        // stage 2 - pivot's left child is now subtree_root
65
52.4M
        pivot->left_child = subtree_root;
66
52.4M
        subtree_root->parent = pivot;
67
68
        // stage 3 - update pivot's parent
69
52.4M
        pivot->parent = parent;
70
52.4M
        if (!parent) { // new root
71
145k
            m_root = pivot;
72
52.3M
        } else if (parent->left_child == subtree_root) { // we are the left child
73
11.7M
            parent->left_child = pivot;
74
40.5M
        } else { // we are the right child
75
40.5M
            parent->right_child = pivot;
76
40.5M
        }
77
52.4M
    }
AK::BaseRedBlackTree<unsigned int>::rotate_left(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
53
11.3M
    {
54
11.3M
        VERIFY(subtree_root);
55
11.3M
        auto* pivot = subtree_root->right_child;
56
11.3M
        VERIFY(pivot);
57
11.3M
        auto* parent = subtree_root->parent;
58
59
        // stage 1 - subtree_root's right child is now pivot's left child
60
11.3M
        subtree_root->right_child = pivot->left_child;
61
11.3M
        if (subtree_root->right_child)
62
5.56M
            subtree_root->right_child->parent = subtree_root;
63
64
        // stage 2 - pivot's left child is now subtree_root
65
11.3M
        pivot->left_child = subtree_root;
66
11.3M
        subtree_root->parent = pivot;
67
68
        // stage 3 - update pivot's parent
69
11.3M
        pivot->parent = parent;
70
11.3M
        if (!parent) { // new root
71
122k
            m_root = pivot;
72
11.2M
        } else if (parent->left_child == subtree_root) { // we are the left child
73
1.52M
            parent->left_child = pivot;
74
9.70M
        } else { // we are the right child
75
9.70M
            parent->right_child = pivot;
76
9.70M
        }
77
11.3M
    }
78
79
    void rotate_right(Node* subtree_root)
80
10.2M
    {
81
10.2M
        VERIFY(subtree_root);
82
10.2M
        auto* pivot = subtree_root->left_child;
83
10.2M
        VERIFY(pivot);
84
10.2M
        auto* parent = subtree_root->parent;
85
86
        // stage 1 - subtree_root's left child is now pivot's right child
87
10.2M
        subtree_root->left_child = pivot->right_child;
88
10.2M
        if (subtree_root->left_child)
89
4.60M
            subtree_root->left_child->parent = subtree_root;
90
91
        // stage 2 - pivot's right child is now subtree_root
92
10.2M
        pivot->right_child = subtree_root;
93
10.2M
        subtree_root->parent = pivot;
94
95
        // stage 3 - update pivot's parent
96
10.2M
        pivot->parent = parent;
97
10.2M
        if (!parent) { // new root
98
295k
            m_root = pivot;
99
9.95M
        } else if (parent->left_child == subtree_root) { // we are the left child
100
1.24M
            parent->left_child = pivot;
101
8.71M
        } else { // we are the right child
102
8.71M
            parent->right_child = pivot;
103
8.71M
        }
104
10.2M
    }
AK::BaseRedBlackTree<unsigned long>::rotate_right(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
80
9.00M
    {
81
9.00M
        VERIFY(subtree_root);
82
9.00M
        auto* pivot = subtree_root->left_child;
83
9.00M
        VERIFY(pivot);
84
9.00M
        auto* parent = subtree_root->parent;
85
86
        // stage 1 - subtree_root's left child is now pivot's right child
87
9.00M
        subtree_root->left_child = pivot->right_child;
88
9.00M
        if (subtree_root->left_child)
89
3.98M
            subtree_root->left_child->parent = subtree_root;
90
91
        // stage 2 - pivot's right child is now subtree_root
92
9.00M
        pivot->right_child = subtree_root;
93
9.00M
        subtree_root->parent = pivot;
94
95
        // stage 3 - update pivot's parent
96
9.00M
        pivot->parent = parent;
97
9.00M
        if (!parent) { // new root
98
2.81k
            m_root = pivot;
99
8.99M
        } else if (parent->left_child == subtree_root) { // we are the left child
100
1.20M
            parent->left_child = pivot;
101
7.79M
        } else { // we are the right child
102
7.79M
            parent->right_child = pivot;
103
7.79M
        }
104
9.00M
    }
AK::BaseRedBlackTree<unsigned int>::rotate_right(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
80
1.25M
    {
81
1.25M
        VERIFY(subtree_root);
82
1.25M
        auto* pivot = subtree_root->left_child;
83
1.25M
        VERIFY(pivot);
84
1.25M
        auto* parent = subtree_root->parent;
85
86
        // stage 1 - subtree_root's left child is now pivot's right child
87
1.25M
        subtree_root->left_child = pivot->right_child;
88
1.25M
        if (subtree_root->left_child)
89
620k
            subtree_root->left_child->parent = subtree_root;
90
91
        // stage 2 - pivot's right child is now subtree_root
92
1.25M
        pivot->right_child = subtree_root;
93
1.25M
        subtree_root->parent = pivot;
94
95
        // stage 3 - update pivot's parent
96
1.25M
        pivot->parent = parent;
97
1.25M
        if (!parent) { // new root
98
292k
            m_root = pivot;
99
959k
        } else if (parent->left_child == subtree_root) { // we are the left child
100
36.7k
            parent->left_child = pivot;
101
922k
        } else { // we are the right child
102
922k
            parent->right_child = pivot;
103
922k
        }
104
1.25M
    }
105
106
    static Node* find(Node* node, K key)
107
23.7k
    {
108
83.2k
        while (node && node->key != key) {
109
59.4k
            if (key < node->key) {
110
11.4k
                node = node->left_child;
111
47.9k
            } else {
112
47.9k
                node = node->right_child;
113
47.9k
            }
114
59.4k
        }
115
23.7k
        return node;
116
23.7k
    }
AK::BaseRedBlackTree<unsigned long>::find(AK::BaseRedBlackTree<unsigned long>::Node*, unsigned long)
Line
Count
Source
107
23.7k
    {
108
83.2k
        while (node && node->key != key) {
109
59.4k
            if (key < node->key) {
110
11.4k
                node = node->left_child;
111
47.9k
            } else {
112
47.9k
                node = node->right_child;
113
47.9k
            }
114
59.4k
        }
115
23.7k
        return node;
116
23.7k
    }
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
76.0M
    {
120
76.0M
        Node* candidate = nullptr;
121
262M
        while (node) {
122
192M
            if (key == node->key)
123
5.76M
                return node;
124
186M
            if (key < node->key) {
125
73.2M
                node = node->left_child;
126
113M
            } else {
127
113M
                candidate = node;
128
113M
                node = node->right_child;
129
113M
            }
130
186M
        }
131
70.3M
        return candidate;
132
76.0M
    }
AK::BaseRedBlackTree<unsigned long>::find_largest_not_above(AK::BaseRedBlackTree<unsigned long>::Node*, unsigned long)
Line
Count
Source
119
76.0M
    {
120
76.0M
        Node* candidate = nullptr;
121
262M
        while (node) {
122
192M
            if (key == node->key)
123
5.76M
                return node;
124
186M
            if (key < node->key) {
125
73.2M
                node = node->left_child;
126
113M
            } else {
127
113M
                candidate = node;
128
113M
                node = node->right_child;
129
113M
            }
130
186M
        }
131
70.3M
        return candidate;
132
76.0M
    }
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
5.94M
    {
136
5.94M
        Node* candidate = nullptr;
137
14.8M
        while (node) {
138
9.43M
            if (node->key == key)
139
520k
                return node;
140
141
8.91M
            if (node->key <= key) {
142
913k
                node = node->right_child;
143
8.00M
            } else {
144
8.00M
                candidate = node;
145
8.00M
                node = node->left_child;
146
8.00M
            }
147
8.91M
        }
148
5.42M
        return candidate;
149
5.94M
    }
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
5.94M
    {
136
5.94M
        Node* candidate = nullptr;
137
14.8M
        while (node) {
138
9.43M
            if (node->key == key)
139
520k
                return node;
140
141
8.91M
            if (node->key <= key) {
142
913k
                node = node->right_child;
143
8.00M
            } else {
144
8.00M
                candidate = node;
145
8.00M
                node = node->left_child;
146
8.00M
            }
147
8.91M
        }
148
5.42M
        return candidate;
149
5.94M
    }
150
151
    void insert(Node* node)
152
68.1M
    {
153
68.1M
        VERIFY(node);
154
68.1M
        Node* parent = nullptr;
155
68.1M
        Node* temp = m_root;
156
1.87G
        while (temp) {
157
1.81G
            parent = temp;
158
1.81G
            if (node->key < temp->key)
159
121M
                temp = temp->left_child;
160
1.68G
            else
161
1.68G
                temp = temp->right_child;
162
1.81G
        }
163
68.1M
        if (!parent) { // new root
164
2.72M
            node->color = Color::Black;
165
2.72M
            m_root = node;
166
2.72M
            m_size = 1;
167
2.72M
            m_minimum = node;
168
2.72M
            return;
169
2.72M
        }
170
65.4M
        if (node->key < parent->key) // we are the left child
171
6.01M
            parent->left_child = node;
172
59.4M
        else // we are the right child
173
59.4M
            parent->right_child = node;
174
65.4M
        node->parent = parent;
175
176
65.4M
        if (node->parent->parent) // no fixups to be done for a height <= 2 tree
177
64.7M
            insert_fixups(node);
178
179
65.4M
        m_size++;
180
65.4M
        if (m_minimum->left_child == node)
181
611k
            m_minimum = node;
182
65.4M
    }
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.60G
        while (temp) {
157
1.55G
            parent = temp;
158
1.55G
            if (node->key < temp->key)
159
115M
                temp = temp->left_child;
160
1.43G
            else
161
1.43G
                temp = temp->right_child;
162
1.55G
        }
163
53.9M
        if (!parent) { // new root
164
737k
            node->color = Color::Black;
165
737k
            m_root = node;
166
737k
            m_size = 1;
167
737k
            m_minimum = node;
168
737k
            return;
169
737k
        }
170
53.2M
        if (node->key < parent->key) // we are the left child
171
5.06M
            parent->left_child = node;
172
48.1M
        else // we are the right child
173
48.1M
            parent->right_child = node;
174
53.2M
        node->parent = parent;
175
176
53.2M
        if (node->parent->parent) // no fixups to be done for a height <= 2 tree
177
52.8M
            insert_fixups(node);
178
179
53.2M
        m_size++;
180
53.2M
        if (m_minimum->left_child == node)
181
11.0k
            m_minimum = node;
182
53.2M
    }
AK::BaseRedBlackTree<unsigned int>::insert(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
152
14.2M
    {
153
14.2M
        VERIFY(node);
154
14.2M
        Node* parent = nullptr;
155
14.2M
        Node* temp = m_root;
156
269M
        while (temp) {
157
255M
            parent = temp;
158
255M
            if (node->key < temp->key)
159
6.23M
                temp = temp->left_child;
160
249M
            else
161
249M
                temp = temp->right_child;
162
255M
        }
163
14.2M
        if (!parent) { // new root
164
1.98M
            node->color = Color::Black;
165
1.98M
            m_root = node;
166
1.98M
            m_size = 1;
167
1.98M
            m_minimum = node;
168
1.98M
            return;
169
1.98M
        }
170
12.2M
        if (node->key < parent->key) // we are the left child
171
955k
            parent->left_child = node;
172
11.2M
        else // we are the right child
173
11.2M
            parent->right_child = node;
174
12.2M
        node->parent = parent;
175
176
12.2M
        if (node->parent->parent) // no fixups to be done for a height <= 2 tree
177
11.9M
            insert_fixups(node);
178
179
12.2M
        m_size++;
180
12.2M
        if (m_minimum->left_child == node)
181
600k
            m_minimum = node;
182
12.2M
    }
183
184
    void insert_fixups(Node* node)
185
64.7M
    {
186
64.7M
        VERIFY(node && node->color == Color::Red);
187
192M
        while (node->parent && node->parent->color == Color::Red) {
188
127M
            auto* grand_parent = node->parent->parent;
189
127M
            if (grand_parent->right_child == node->parent) {
190
117M
                auto* uncle = grand_parent->left_child;
191
117M
                if (uncle && uncle->color == Color::Red) {
192
63.6M
                    node->parent->color = Color::Black;
193
63.6M
                    uncle->color = Color::Black;
194
63.6M
                    grand_parent->color = Color::Red;
195
63.6M
                    node = grand_parent;
196
63.6M
                } else {
197
53.9M
                    if (node->parent->left_child == node) {
198
63.6k
                        node = node->parent;
199
63.6k
                        rotate_right(node);
200
63.6k
                    }
201
53.9M
                    node->parent->color = Color::Black;
202
53.9M
                    grand_parent->color = Color::Red;
203
53.9M
                    rotate_left(grand_parent);
204
53.9M
                }
205
117M
            } else {
206
10.2M
                auto* uncle = grand_parent->right_child;
207
10.2M
                if (uncle && uncle->color == Color::Red) {
208
93.7k
                    node->parent->color = Color::Black;
209
93.7k
                    uncle->color = Color::Black;
210
93.7k
                    grand_parent->color = Color::Red;
211
93.7k
                    node = grand_parent;
212
10.1M
                } else {
213
10.1M
                    if (node->parent->right_child == node) {
214
9.88M
                        node = node->parent;
215
9.88M
                        rotate_left(node);
216
9.88M
                    }
217
10.1M
                    node->parent->color = Color::Black;
218
10.1M
                    grand_parent->color = Color::Red;
219
10.1M
                    rotate_right(grand_parent);
220
10.1M
                }
221
10.2M
            }
222
127M
        }
223
64.7M
        m_root->color = Color::Black; // the root should always be black
224
64.7M
    }
AK::BaseRedBlackTree<unsigned long>::insert_fixups(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
185
52.8M
    {
186
52.8M
        VERIFY(node && node->color == Color::Red);
187
157M
        while (node->parent && node->parent->color == Color::Red) {
188
104M
            auto* grand_parent = node->parent->parent;
189
104M
            if (grand_parent->right_child == node->parent) {
190
95.8M
                auto* uncle = grand_parent->left_child;
191
95.8M
                if (uncle && uncle->color == Color::Red) {
192
52.3M
                    node->parent->color = Color::Black;
193
52.3M
                    uncle->color = Color::Black;
194
52.3M
                    grand_parent->color = Color::Red;
195
52.3M
                    node = grand_parent;
196
52.3M
                } else {
197
43.5M
                    if (node->parent->left_child == node) {
198
32.1k
                        node = node->parent;
199
32.1k
                        rotate_right(node);
200
32.1k
                    }
201
43.5M
                    node->parent->color = Color::Black;
202
43.5M
                    grand_parent->color = Color::Red;
203
43.5M
                    rotate_left(grand_parent);
204
43.5M
                }
205
95.8M
            } else {
206
9.04M
                auto* uncle = grand_parent->right_child;
207
9.04M
                if (uncle && uncle->color == Color::Red) {
208
77.2k
                    node->parent->color = Color::Black;
209
77.2k
                    uncle->color = Color::Black;
210
77.2k
                    grand_parent->color = Color::Red;
211
77.2k
                    node = grand_parent;
212
8.96M
                } else {
213
8.96M
                    if (node->parent->right_child == node) {
214
8.95M
                        node = node->parent;
215
8.95M
                        rotate_left(node);
216
8.95M
                    }
217
8.96M
                    node->parent->color = Color::Black;
218
8.96M
                    grand_parent->color = Color::Red;
219
8.96M
                    rotate_right(grand_parent);
220
8.96M
                }
221
9.04M
            }
222
104M
        }
223
52.8M
        m_root->color = Color::Black; // the root should always be black
224
52.8M
    }
AK::BaseRedBlackTree<unsigned int>::insert_fixups(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
185
11.9M
    {
186
11.9M
        VERIFY(node && node->color == Color::Red);
187
34.8M
        while (node->parent && node->parent->color == Color::Red) {
188
22.9M
            auto* grand_parent = node->parent->parent;
189
22.9M
            if (grand_parent->right_child == node->parent) {
190
21.7M
                auto* uncle = grand_parent->left_child;
191
21.7M
                if (uncle && uncle->color == Color::Red) {
192
11.3M
                    node->parent->color = Color::Black;
193
11.3M
                    uncle->color = Color::Black;
194
11.3M
                    grand_parent->color = Color::Red;
195
11.3M
                    node = grand_parent;
196
11.3M
                } else {
197
10.4M
                    if (node->parent->left_child == node) {
198
31.4k
                        node = node->parent;
199
31.4k
                        rotate_right(node);
200
31.4k
                    }
201
10.4M
                    node->parent->color = Color::Black;
202
10.4M
                    grand_parent->color = Color::Red;
203
10.4M
                    rotate_left(grand_parent);
204
10.4M
                }
205
21.7M
            } else {
206
1.23M
                auto* uncle = grand_parent->right_child;
207
1.23M
                if (uncle && uncle->color == Color::Red) {
208
16.4k
                    node->parent->color = Color::Black;
209
16.4k
                    uncle->color = Color::Black;
210
16.4k
                    grand_parent->color = Color::Red;
211
16.4k
                    node = grand_parent;
212
1.22M
                } else {
213
1.22M
                    if (node->parent->right_child == node) {
214
927k
                        node = node->parent;
215
927k
                        rotate_left(node);
216
927k
                    }
217
1.22M
                    node->parent->color = Color::Black;
218
1.22M
                    grand_parent->color = Color::Red;
219
1.22M
                    rotate_right(grand_parent);
220
1.22M
                }
221
1.23M
            }
222
22.9M
        }
223
11.9M
        m_root->color = Color::Black; // the root should always be black
224
11.9M
    }
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
43.9M
    {
366
43.9M
        VERIFY(node);
367
43.9M
        if (node->right_child) {
368
21.9M
            node = node->right_child;
369
43.9M
            while (node->left_child)
370
21.9M
                node = node->left_child;
371
21.9M
            return node;
372
21.9M
        }
373
21.9M
        auto temp = node->parent;
374
43.9M
        while (temp && node == temp->right_child) {
375
21.9M
            node = temp;
376
21.9M
            temp = temp->parent;
377
21.9M
        }
378
21.9M
        return temp;
379
43.9M
    }
AK::BaseRedBlackTree<unsigned long>::successor(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
365
43.9M
    {
366
43.9M
        VERIFY(node);
367
43.9M
        if (node->right_child) {
368
21.9M
            node = node->right_child;
369
43.9M
            while (node->left_child)
370
21.9M
                node = node->left_child;
371
21.9M
            return node;
372
21.9M
        }
373
21.9M
        auto temp = node->parent;
374
43.9M
        while (temp && node == temp->right_child) {
375
21.9M
            node = temp;
376
21.9M
            temp = temp->parent;
377
21.9M
        }
378
21.9M
        return temp;
379
43.9M
    }
AK::BaseRedBlackTree<unsigned int>::successor(AK::BaseRedBlackTree<unsigned int>::Node*)
Line
Count
Source
365
14.4k
    {
366
14.4k
        VERIFY(node);
367
14.4k
        if (node->right_child) {
368
5.94k
            node = node->right_child;
369
10.1k
            while (node->left_child)
370
4.15k
                node = node->left_child;
371
5.94k
            return node;
372
5.94k
        }
373
8.49k
        auto temp = node->parent;
374
13.3k
        while (temp && node == temp->right_child) {
375
4.84k
            node = temp;
376
4.84k
            temp = temp->parent;
377
4.84k
        }
378
8.49k
        return temp;
379
14.4k
    }
380
381
    static Node* predecessor(Node* node)
382
76.0M
    {
383
76.0M
        VERIFY(node);
384
76.0M
        if (node->left_child) {
385
15.7M
            node = node->left_child;
386
15.9M
            while (node->right_child)
387
265k
                node = node->right_child;
388
15.7M
            return node;
389
15.7M
        }
390
60.3M
        auto temp = node->parent;
391
60.9M
        while (temp && node == temp->left_child) {
392
539k
            node = temp;
393
539k
            temp = temp->parent;
394
539k
        }
395
60.3M
        return temp;
396
76.0M
    }
AK::BaseRedBlackTree<unsigned long>::predecessor(AK::BaseRedBlackTree<unsigned long>::Node*)
Line
Count
Source
382
76.0M
    {
383
76.0M
        VERIFY(node);
384
76.0M
        if (node->left_child) {
385
15.7M
            node = node->left_child;
386
15.9M
            while (node->right_child)
387
265k
                node = node->right_child;
388
15.7M
            return node;
389
15.7M
        }
390
60.3M
        auto temp = node->parent;
391
60.9M
        while (temp && node == temp->left_child) {
392
539k
            node = temp;
393
539k
            temp = temp->parent;
394
539k
        }
395
60.3M
        return temp;
396
76.0M
    }
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
41.8k
    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
17.0k
    RedBlackTreeIterator() = default;
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::RedBlackTreeIterator()
Line
Count
Source
406
24.8k
    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
44.0M
    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
43.9M
    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
24.8k
    bool operator!=(RedBlackTreeIterator const& other) const { return m_node != other.m_node; }
408
    RedBlackTreeIterator& operator++()
409
43.9M
    {
410
43.9M
        if (!m_node)
411
0
            return *this;
412
43.9M
        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
43.9M
        m_node = static_cast<typename TreeType::Node*>(TreeType::successor(m_node));
415
43.9M
        return *this;
416
43.9M
    }
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
43.9M
    {
410
43.9M
        if (!m_node)
411
0
            return *this;
412
43.9M
        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
43.9M
        m_node = static_cast<typename TreeType::Node*>(TreeType::successor(m_node));
415
43.9M
        return *this;
416
43.9M
    }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::operator++()
Line
Count
Source
409
14.4k
    {
410
14.4k
        if (!m_node)
411
0
            return *this;
412
14.4k
        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
14.4k
        m_node = static_cast<typename TreeType::Node*>(TreeType::successor(m_node));
415
14.4k
        return *this;
416
14.4k
    }
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
120M
    ElementType& operator*() { return m_node->value; }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned long, unsigned long> const, unsigned long const>::operator*()
Line
Count
Source
425
76.0M
    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
43.9M
    ElementType& operator*() { return m_node->value; }
AK::RedBlackTreeIterator<AK::RedBlackTree<unsigned int, unsigned int>, unsigned int>::operator*()
Line
Count
Source
425
23.1k
    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
76.1M
    [[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
76.0M
    [[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
23.1k
    [[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
76.1M
        : m_node(node)
436
76.1M
        , m_prev(prev)
437
76.1M
    {
438
76.1M
    }
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
76.0M
        : m_node(node)
436
76.0M
        , m_prev(prev)
437
76.0M
    {
438
76.0M
    }
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
17.0k
        : m_node(node)
436
17.0k
        , m_prev(prev)
437
17.0k
    {
438
17.0k
    }
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
10.3k
        : m_node(node)
436
10.3k
        , m_prev(prev)
437
10.3k
    {
438
10.3k
    }
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
4.73M
    RedBlackTree() = default;
AK::RedBlackTree<unsigned long, unsigned long>::RedBlackTree()
Line
Count
Source
446
722k
    RedBlackTree() = default;
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::RedBlackTree()
AK::RedBlackTree<unsigned long, regex::CharRange>::RedBlackTree()
Line
Count
Source
446
35.2k
    RedBlackTree() = default;
AK::RedBlackTree<unsigned int, unsigned int>::RedBlackTree()
Line
Count
Source
446
3.97M
    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
4.73M
    {
449
4.73M
        clear();
450
4.73M
    }
AK::RedBlackTree<unsigned long, unsigned long>::~RedBlackTree()
Line
Count
Source
448
722k
    {
449
722k
        clear();
450
722k
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::~RedBlackTree()
AK::RedBlackTree<unsigned long, regex::CharRange>::~RedBlackTree()
Line
Count
Source
448
35.2k
    {
449
35.2k
        clear();
450
35.2k
    }
AK::RedBlackTree<unsigned int, unsigned int>::~RedBlackTree()
Line
Count
Source
448
3.97M
    {
449
3.97M
        clear();
450
3.97M
    }
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
23.7k
    {
456
23.7k
        auto* node = static_cast<Node*>(BaseTree::find(this->m_root, key));
457
23.7k
        if (!node)
458
0
            return nullptr;
459
23.7k
        return &node->value;
460
23.7k
    }
AK::RedBlackTree<unsigned long, unsigned long>::find(unsigned long)
Line
Count
Source
455
23.7k
    {
456
23.7k
        auto* node = static_cast<Node*>(BaseTree::find(this->m_root, key));
457
23.7k
        if (!node)
458
0
            return nullptr;
459
23.7k
        return &node->value;
460
23.7k
    }
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
5.94M
    {
472
5.94M
        auto* node = static_cast<Node*>(BaseTree::find_smallest_not_below(this->m_root, key));
473
5.94M
        if (!node)
474
731k
            return nullptr;
475
5.21M
        return &node->value;
476
5.94M
    }
477
478
    ErrorOr<void> try_insert(K key, V const& value)
479
12.1M
    {
480
12.1M
        return try_insert(key, V(value));
481
12.1M
    }
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
5.76M
    {
480
5.76M
        return try_insert(key, V(value));
481
5.76M
    }
AK::RedBlackTree<unsigned long, unsigned long>::try_insert(unsigned long, unsigned long const&)
Line
Count
Source
479
1.03M
    {
480
1.03M
        return try_insert(key, V(value));
481
1.03M
    }
AK::RedBlackTree<unsigned int, unsigned int>::try_insert(unsigned int, unsigned int const&)
Line
Count
Source
479
5.31M
    {
480
5.31M
        return try_insert(key, V(value));
481
5.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
12.1M
    {
485
12.1M
        MUST(try_insert(key, value));
486
12.1M
    }
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
5.76M
    {
485
5.76M
        MUST(try_insert(key, value));
486
5.76M
    }
AK::RedBlackTree<unsigned long, unsigned long>::insert(unsigned long, unsigned long const&)
Line
Count
Source
484
1.03M
    {
485
1.03M
        MUST(try_insert(key, value));
486
1.03M
    }
AK::RedBlackTree<unsigned int, unsigned int>::insert(unsigned int, unsigned int const&)
Line
Count
Source
484
5.31M
    {
485
5.31M
        MUST(try_insert(key, value));
486
5.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
68.1M
    {
490
68.1M
        auto* node = new (nothrow) Node(key, move(value));
491
68.1M
        if (!node)
492
0
            return Error::from_errno(ENOMEM);
493
68.1M
        BaseTree::insert(node);
494
68.1M
        return {};
495
68.1M
    }
AK::RedBlackTree<unsigned long, unsigned long>::try_insert(unsigned long, unsigned long&&)
Line
Count
Source
489
10.0M
    {
490
10.0M
        auto* node = new (nothrow) Node(key, move(value));
491
10.0M
        if (!node)
492
0
            return Error::from_errno(ENOMEM);
493
10.0M
        BaseTree::insert(node);
494
10.0M
        return {};
495
10.0M
    }
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
43.9M
    {
490
43.9M
        auto* node = new (nothrow) Node(key, move(value));
491
43.9M
        if (!node)
492
0
            return Error::from_errno(ENOMEM);
493
43.9M
        BaseTree::insert(node);
494
43.9M
        return {};
495
43.9M
    }
AK::RedBlackTree<unsigned int, unsigned int>::try_insert(unsigned int, unsigned int&&)
Line
Count
Source
489
14.2M
    {
490
14.2M
        auto* node = new (nothrow) Node(key, move(value));
491
14.2M
        if (!node)
492
0
            return Error::from_errno(ENOMEM);
493
14.2M
        BaseTree::insert(node);
494
14.2M
        return {};
495
14.2M
    }
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
56.0M
    {
499
56.0M
        MUST(try_insert(key, move(value)));
500
56.0M
    }
AK::RedBlackTree<unsigned long, unsigned long>::insert(unsigned long, unsigned long&&)
Line
Count
Source
498
8.96M
    {
499
8.96M
        MUST(try_insert(key, move(value)));
500
8.96M
    }
AK::RedBlackTree<unsigned long, regex::CharRange>::insert(unsigned long, regex::CharRange&&)
Line
Count
Source
498
38.1M
    {
499
38.1M
        MUST(try_insert(key, move(value)));
500
38.1M
    }
AK::RedBlackTree<unsigned int, unsigned int>::insert(unsigned int, unsigned int&&)
Line
Count
Source
498
8.90M
    {
499
8.90M
        MUST(try_insert(key, move(value)));
500
8.90M
    }
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
27.4k
    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
17.0k
    Iterator begin() { return Iterator(static_cast<Node*>(this->m_minimum)); }
AK::RedBlackTree<unsigned int, unsigned int>::begin()
Line
Count
Source
504
10.3k
    Iterator begin() { return Iterator(static_cast<Node*>(this->m_minimum)); }
505
41.8k
    Iterator end() { return {}; }
AK::RedBlackTree<unsigned long, regex::CharRange>::end()
Line
Count
Source
505
17.0k
    Iterator end() { return {}; }
AK::RedBlackTree<unsigned int, unsigned int>::end()
Line
Count
Source
505
24.8k
    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
76.0M
    {
516
76.0M
        auto node = static_cast<Node*>(BaseTree::find_largest_not_above(this->m_root, key));
517
76.0M
        if (!node)
518
0
            return end();
519
76.0M
        return ConstIterator(node, static_cast<Node*>(BaseTree::predecessor(node)));
520
76.0M
    }
AK::RedBlackTree<unsigned long, unsigned long>::find_largest_not_above_iterator(unsigned long) const
Line
Count
Source
515
76.0M
    {
516
76.0M
        auto node = static_cast<Node*>(BaseTree::find_largest_not_above(this->m_root, key));
517
76.0M
        if (!node)
518
0
            return end();
519
76.0M
        return ConstIterator(node, static_cast<Node*>(BaseTree::predecessor(node)));
520
76.0M
    }
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
4.76M
    {
563
4.76M
        delete this->m_root;
564
4.76M
        this->m_root = nullptr;
565
4.76M
        this->m_minimum = nullptr;
566
4.76M
        this->m_size = 0;
567
4.76M
    }
AK::RedBlackTree<unsigned long, unsigned long>::clear()
Line
Count
Source
562
722k
    {
563
722k
        delete this->m_root;
564
722k
        this->m_root = nullptr;
565
722k
        this->m_minimum = nullptr;
566
722k
        this->m_size = 0;
567
722k
    }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::clear()
AK::RedBlackTree<unsigned long, regex::CharRange>::clear()
Line
Count
Source
562
73.8k
    {
563
73.8k
        delete this->m_root;
564
73.8k
        this->m_root = nullptr;
565
73.8k
        this->m_minimum = nullptr;
566
73.8k
        this->m_size = 0;
567
73.8k
    }
AK::RedBlackTree<unsigned int, unsigned int>::clear()
Line
Count
Source
562
3.97M
    {
563
3.97M
        delete this->m_root;
564
3.97M
        this->m_root = nullptr;
565
3.97M
        this->m_minimum = nullptr;
566
3.97M
        this->m_size = 0;
567
3.97M
    }
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
68.1M
            : BaseRedBlackTree<K>::Node(key)
576
43.9M
            , value(move(value))
577
68.1M
        {
578
68.1M
        }
AK::RedBlackTree<unsigned long, unsigned long>::Node::Node(unsigned long, unsigned long)
Line
Count
Source
575
10.0M
            : BaseRedBlackTree<K>::Node(key)
576
10.0M
            , value(move(value))
577
10.0M
        {
578
10.0M
        }
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
43.9M
            : BaseRedBlackTree<K>::Node(key)
576
43.9M
            , value(move(value))
577
43.9M
        {
578
43.9M
        }
AK::RedBlackTree<unsigned int, unsigned int>::Node::Node(unsigned int, unsigned int)
Line
Count
Source
575
14.2M
            : BaseRedBlackTree<K>::Node(key)
576
14.2M
            , value(move(value))
577
14.2M
        {
578
14.2M
        }
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
68.1M
        {
582
68.1M
            delete this->left_child;
583
68.1M
            delete this->right_child;
584
68.1M
        }
AK::RedBlackTree<unsigned long, unsigned long>::Node::~Node()
Line
Count
Source
581
10.0M
        {
582
10.0M
            delete this->left_child;
583
10.0M
            delete this->right_child;
584
10.0M
        }
Unexecuted instantiation: AK::RedBlackTree<unsigned long, JS::Value>::Node::~Node()
AK::RedBlackTree<unsigned long, regex::CharRange>::Node::~Node()
Line
Count
Source
581
43.9M
        {
582
43.9M
            delete this->left_child;
583
43.9M
            delete this->right_child;
584
43.9M
        }
AK::RedBlackTree<unsigned int, unsigned int>::Node::~Node()
Line
Count
Source
581
14.2M
        {
582
14.2M
            delete this->left_child;
583
14.2M
            delete this->right_child;
584
14.2M
        }
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