1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2017 Jason Ekstrand
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci * all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include "rb_tree.h"
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci/** \file rb_tree.c
26bf215546Sopenharmony_ci *
27bf215546Sopenharmony_ci * An implementation of a red-black tree
28bf215546Sopenharmony_ci *
29bf215546Sopenharmony_ci * This file implements the guts of a red-black tree.  The implementation
30bf215546Sopenharmony_ci * is mostly based on the one in "Introduction to Algorithms", third
31bf215546Sopenharmony_ci * edition, by Cormen, Leiserson, Rivest, and Stein.  The primary
32bf215546Sopenharmony_ci * divergence in our algorithms from those presented in CLRS is that we use
33bf215546Sopenharmony_ci * NULL for the leaves instead of a sentinel.  This means we have to do a
34bf215546Sopenharmony_ci * tiny bit more tracking in our implementation of delete but it makes the
35bf215546Sopenharmony_ci * algorithms far more explicit than stashing stuff in the sentinel.
36bf215546Sopenharmony_ci */
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include <stdlib.h>
39bf215546Sopenharmony_ci#include <string.h>
40bf215546Sopenharmony_ci#include <assert.h>
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistatic bool
43bf215546Sopenharmony_cirb_node_is_black(struct rb_node *n)
44bf215546Sopenharmony_ci{
45bf215546Sopenharmony_ci    /* NULL nodes are leaves and therefore black */
46bf215546Sopenharmony_ci    return (n == NULL) || (n->parent & 1);
47bf215546Sopenharmony_ci}
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_cistatic bool
50bf215546Sopenharmony_cirb_node_is_red(struct rb_node *n)
51bf215546Sopenharmony_ci{
52bf215546Sopenharmony_ci    return !rb_node_is_black(n);
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cistatic void
56bf215546Sopenharmony_cirb_node_set_black(struct rb_node *n)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci    n->parent |= 1;
59bf215546Sopenharmony_ci}
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_cistatic void
62bf215546Sopenharmony_cirb_node_set_red(struct rb_node *n)
63bf215546Sopenharmony_ci{
64bf215546Sopenharmony_ci    n->parent &= ~1ull;
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_cistatic void
68bf215546Sopenharmony_cirb_node_copy_color(struct rb_node *dst, struct rb_node *src)
69bf215546Sopenharmony_ci{
70bf215546Sopenharmony_ci    dst->parent = (dst->parent & ~1ull) | (src->parent & 1);
71bf215546Sopenharmony_ci}
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_cistatic void
74bf215546Sopenharmony_cirb_node_set_parent(struct rb_node *n, struct rb_node *p)
75bf215546Sopenharmony_ci{
76bf215546Sopenharmony_ci    n->parent = (n->parent & 1) | (uintptr_t)p;
77bf215546Sopenharmony_ci}
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_cistatic struct rb_node *
80bf215546Sopenharmony_cirb_node_minimum(struct rb_node *node)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci    while (node->left)
83bf215546Sopenharmony_ci        node = node->left;
84bf215546Sopenharmony_ci    return node;
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_cistatic struct rb_node *
88bf215546Sopenharmony_cirb_node_maximum(struct rb_node *node)
89bf215546Sopenharmony_ci{
90bf215546Sopenharmony_ci    while (node->right)
91bf215546Sopenharmony_ci        node = node->right;
92bf215546Sopenharmony_ci    return node;
93bf215546Sopenharmony_ci}
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_civoid
96bf215546Sopenharmony_cirb_tree_init(struct rb_tree *T)
97bf215546Sopenharmony_ci{
98bf215546Sopenharmony_ci    T->root = NULL;
99bf215546Sopenharmony_ci}
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci/**
102bf215546Sopenharmony_ci * Replace the subtree of T rooted at u with the subtree rooted at v
103bf215546Sopenharmony_ci *
104bf215546Sopenharmony_ci * This is called RB-transplant in CLRS.
105bf215546Sopenharmony_ci *
106bf215546Sopenharmony_ci * The node to be replaced is assumed to be a non-leaf.
107bf215546Sopenharmony_ci */
108bf215546Sopenharmony_cistatic void
109bf215546Sopenharmony_cirb_tree_splice(struct rb_tree *T, struct rb_node *u, struct rb_node *v)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci    assert(u);
112bf215546Sopenharmony_ci    struct rb_node *p = rb_node_parent(u);
113bf215546Sopenharmony_ci    if (p == NULL) {
114bf215546Sopenharmony_ci        assert(T->root == u);
115bf215546Sopenharmony_ci        T->root = v;
116bf215546Sopenharmony_ci    } else if (u == p->left) {
117bf215546Sopenharmony_ci        p->left = v;
118bf215546Sopenharmony_ci    } else {
119bf215546Sopenharmony_ci        assert(u == p->right);
120bf215546Sopenharmony_ci        p->right = v;
121bf215546Sopenharmony_ci    }
122bf215546Sopenharmony_ci    if (v)
123bf215546Sopenharmony_ci        rb_node_set_parent(v, p);
124bf215546Sopenharmony_ci}
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_cistatic void
127bf215546Sopenharmony_cirb_tree_rotate_left(struct rb_tree *T, struct rb_node *x)
128bf215546Sopenharmony_ci{
129bf215546Sopenharmony_ci    assert(x && x->right);
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci    struct rb_node *y = x->right;
132bf215546Sopenharmony_ci    x->right = y->left;
133bf215546Sopenharmony_ci    if (y->left)
134bf215546Sopenharmony_ci        rb_node_set_parent(y->left, x);
135bf215546Sopenharmony_ci    rb_tree_splice(T, x, y);
136bf215546Sopenharmony_ci    y->left = x;
137bf215546Sopenharmony_ci    rb_node_set_parent(x, y);
138bf215546Sopenharmony_ci}
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_cistatic void
141bf215546Sopenharmony_cirb_tree_rotate_right(struct rb_tree *T, struct rb_node *y)
142bf215546Sopenharmony_ci{
143bf215546Sopenharmony_ci    assert(y && y->left);
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci    struct rb_node *x = y->left;
146bf215546Sopenharmony_ci    y->left = x->right;
147bf215546Sopenharmony_ci    if (x->right)
148bf215546Sopenharmony_ci        rb_node_set_parent(x->right, y);
149bf215546Sopenharmony_ci    rb_tree_splice(T, y, x);
150bf215546Sopenharmony_ci    x->right = y;
151bf215546Sopenharmony_ci    rb_node_set_parent(y, x);
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_civoid
155bf215546Sopenharmony_cirb_tree_insert_at(struct rb_tree *T, struct rb_node *parent,
156bf215546Sopenharmony_ci                  struct rb_node *node, bool insert_left)
157bf215546Sopenharmony_ci{
158bf215546Sopenharmony_ci    /* This sets null children, parent, and a color of red */
159bf215546Sopenharmony_ci    memset(node, 0, sizeof(*node));
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci    if (parent == NULL) {
162bf215546Sopenharmony_ci        assert(T->root == NULL);
163bf215546Sopenharmony_ci        T->root = node;
164bf215546Sopenharmony_ci        rb_node_set_black(node);
165bf215546Sopenharmony_ci        return;
166bf215546Sopenharmony_ci    }
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci    if (insert_left) {
169bf215546Sopenharmony_ci        assert(parent->left == NULL);
170bf215546Sopenharmony_ci        parent->left = node;
171bf215546Sopenharmony_ci    } else {
172bf215546Sopenharmony_ci        assert(parent->right == NULL);
173bf215546Sopenharmony_ci        parent->right = node;
174bf215546Sopenharmony_ci    }
175bf215546Sopenharmony_ci    rb_node_set_parent(node, parent);
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci    /* Now we do the insertion fixup */
178bf215546Sopenharmony_ci    struct rb_node *z = node;
179bf215546Sopenharmony_ci    while (rb_node_is_red(rb_node_parent(z))) {
180bf215546Sopenharmony_ci        struct rb_node *z_p = rb_node_parent(z);
181bf215546Sopenharmony_ci        assert(z == z_p->left || z == z_p->right);
182bf215546Sopenharmony_ci        struct rb_node *z_p_p = rb_node_parent(z_p);
183bf215546Sopenharmony_ci        assert(z_p_p != NULL);
184bf215546Sopenharmony_ci        if (z_p == z_p_p->left) {
185bf215546Sopenharmony_ci            struct rb_node *y = z_p_p->right;
186bf215546Sopenharmony_ci            if (rb_node_is_red(y)) {
187bf215546Sopenharmony_ci                rb_node_set_black(z_p);
188bf215546Sopenharmony_ci                rb_node_set_black(y);
189bf215546Sopenharmony_ci                rb_node_set_red(z_p_p);
190bf215546Sopenharmony_ci                z = z_p_p;
191bf215546Sopenharmony_ci            } else {
192bf215546Sopenharmony_ci                if (z == z_p->right) {
193bf215546Sopenharmony_ci                    z = z_p;
194bf215546Sopenharmony_ci                    rb_tree_rotate_left(T, z);
195bf215546Sopenharmony_ci                    /* We changed z */
196bf215546Sopenharmony_ci                    z_p = rb_node_parent(z);
197bf215546Sopenharmony_ci                    assert(z == z_p->left || z == z_p->right);
198bf215546Sopenharmony_ci                    z_p_p = rb_node_parent(z_p);
199bf215546Sopenharmony_ci                }
200bf215546Sopenharmony_ci                rb_node_set_black(z_p);
201bf215546Sopenharmony_ci                rb_node_set_red(z_p_p);
202bf215546Sopenharmony_ci                rb_tree_rotate_right(T, z_p_p);
203bf215546Sopenharmony_ci            }
204bf215546Sopenharmony_ci        } else {
205bf215546Sopenharmony_ci            struct rb_node *y = z_p_p->left;
206bf215546Sopenharmony_ci            if (rb_node_is_red(y)) {
207bf215546Sopenharmony_ci                rb_node_set_black(z_p);
208bf215546Sopenharmony_ci                rb_node_set_black(y);
209bf215546Sopenharmony_ci                rb_node_set_red(z_p_p);
210bf215546Sopenharmony_ci                z = z_p_p;
211bf215546Sopenharmony_ci            } else {
212bf215546Sopenharmony_ci                if (z == z_p->left) {
213bf215546Sopenharmony_ci                    z = z_p;
214bf215546Sopenharmony_ci                    rb_tree_rotate_right(T, z);
215bf215546Sopenharmony_ci                    /* We changed z */
216bf215546Sopenharmony_ci                    z_p = rb_node_parent(z);
217bf215546Sopenharmony_ci                    assert(z == z_p->left || z == z_p->right);
218bf215546Sopenharmony_ci                    z_p_p = rb_node_parent(z_p);
219bf215546Sopenharmony_ci                }
220bf215546Sopenharmony_ci                rb_node_set_black(z_p);
221bf215546Sopenharmony_ci                rb_node_set_red(z_p_p);
222bf215546Sopenharmony_ci                rb_tree_rotate_left(T, z_p_p);
223bf215546Sopenharmony_ci            }
224bf215546Sopenharmony_ci        }
225bf215546Sopenharmony_ci    }
226bf215546Sopenharmony_ci    rb_node_set_black(T->root);
227bf215546Sopenharmony_ci}
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_civoid
230bf215546Sopenharmony_cirb_tree_remove(struct rb_tree *T, struct rb_node *z)
231bf215546Sopenharmony_ci{
232bf215546Sopenharmony_ci    /* x_p is always the parent node of X.  We have to track this
233bf215546Sopenharmony_ci     * separately because x may be NULL.
234bf215546Sopenharmony_ci     */
235bf215546Sopenharmony_ci    struct rb_node *x, *x_p;
236bf215546Sopenharmony_ci    struct rb_node *y = z;
237bf215546Sopenharmony_ci    bool y_was_black = rb_node_is_black(y);
238bf215546Sopenharmony_ci    if (z->left == NULL) {
239bf215546Sopenharmony_ci        x = z->right;
240bf215546Sopenharmony_ci        x_p = rb_node_parent(z);
241bf215546Sopenharmony_ci        rb_tree_splice(T, z, x);
242bf215546Sopenharmony_ci    } else if (z->right == NULL) {
243bf215546Sopenharmony_ci        x = z->left;
244bf215546Sopenharmony_ci        x_p = rb_node_parent(z);
245bf215546Sopenharmony_ci        rb_tree_splice(T, z, x);
246bf215546Sopenharmony_ci    } else {
247bf215546Sopenharmony_ci        /* Find the minimum sub-node of z->right */
248bf215546Sopenharmony_ci        y = rb_node_minimum(z->right);
249bf215546Sopenharmony_ci        y_was_black = rb_node_is_black(y);
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci        x = y->right;
252bf215546Sopenharmony_ci        if (rb_node_parent(y) == z) {
253bf215546Sopenharmony_ci            x_p = y;
254bf215546Sopenharmony_ci        } else {
255bf215546Sopenharmony_ci            x_p = rb_node_parent(y);
256bf215546Sopenharmony_ci            rb_tree_splice(T, y, x);
257bf215546Sopenharmony_ci            y->right = z->right;
258bf215546Sopenharmony_ci            rb_node_set_parent(y->right, y);
259bf215546Sopenharmony_ci        }
260bf215546Sopenharmony_ci        assert(y->left == NULL);
261bf215546Sopenharmony_ci        rb_tree_splice(T, z, y);
262bf215546Sopenharmony_ci        y->left = z->left;
263bf215546Sopenharmony_ci        rb_node_set_parent(y->left, y);
264bf215546Sopenharmony_ci        rb_node_copy_color(y, z);
265bf215546Sopenharmony_ci    }
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci    assert(x_p == NULL || x == x_p->left || x == x_p->right);
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci    if (!y_was_black)
270bf215546Sopenharmony_ci        return;
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci    /* Fixup RB tree after the delete */
273bf215546Sopenharmony_ci    while (x != T->root && rb_node_is_black(x)) {
274bf215546Sopenharmony_ci        if (x == x_p->left) {
275bf215546Sopenharmony_ci            struct rb_node *w = x_p->right;
276bf215546Sopenharmony_ci            if (rb_node_is_red(w)) {
277bf215546Sopenharmony_ci                rb_node_set_black(w);
278bf215546Sopenharmony_ci                rb_node_set_red(x_p);
279bf215546Sopenharmony_ci                rb_tree_rotate_left(T, x_p);
280bf215546Sopenharmony_ci                assert(x == x_p->left);
281bf215546Sopenharmony_ci                w = x_p->right;
282bf215546Sopenharmony_ci            }
283bf215546Sopenharmony_ci            if (rb_node_is_black(w->left) && rb_node_is_black(w->right)) {
284bf215546Sopenharmony_ci                rb_node_set_red(w);
285bf215546Sopenharmony_ci                x = x_p;
286bf215546Sopenharmony_ci            } else {
287bf215546Sopenharmony_ci                if (rb_node_is_black(w->right)) {
288bf215546Sopenharmony_ci                    rb_node_set_black(w->left);
289bf215546Sopenharmony_ci                    rb_node_set_red(w);
290bf215546Sopenharmony_ci                    rb_tree_rotate_right(T, w);
291bf215546Sopenharmony_ci                    w = x_p->right;
292bf215546Sopenharmony_ci                }
293bf215546Sopenharmony_ci                rb_node_copy_color(w, x_p);
294bf215546Sopenharmony_ci                rb_node_set_black(x_p);
295bf215546Sopenharmony_ci                rb_node_set_black(w->right);
296bf215546Sopenharmony_ci                rb_tree_rotate_left(T, x_p);
297bf215546Sopenharmony_ci                x = T->root;
298bf215546Sopenharmony_ci            }
299bf215546Sopenharmony_ci        } else {
300bf215546Sopenharmony_ci            struct rb_node *w = x_p->left;
301bf215546Sopenharmony_ci            if (rb_node_is_red(w)) {
302bf215546Sopenharmony_ci                rb_node_set_black(w);
303bf215546Sopenharmony_ci                rb_node_set_red(x_p);
304bf215546Sopenharmony_ci                rb_tree_rotate_right(T, x_p);
305bf215546Sopenharmony_ci                assert(x == x_p->right);
306bf215546Sopenharmony_ci                w = x_p->left;
307bf215546Sopenharmony_ci            }
308bf215546Sopenharmony_ci            if (rb_node_is_black(w->right) && rb_node_is_black(w->left)) {
309bf215546Sopenharmony_ci                rb_node_set_red(w);
310bf215546Sopenharmony_ci                x = x_p;
311bf215546Sopenharmony_ci            } else {
312bf215546Sopenharmony_ci                if (rb_node_is_black(w->left)) {
313bf215546Sopenharmony_ci                    rb_node_set_black(w->right);
314bf215546Sopenharmony_ci                    rb_node_set_red(w);
315bf215546Sopenharmony_ci                    rb_tree_rotate_left(T, w);
316bf215546Sopenharmony_ci                    w = x_p->left;
317bf215546Sopenharmony_ci                }
318bf215546Sopenharmony_ci                rb_node_copy_color(w, x_p);
319bf215546Sopenharmony_ci                rb_node_set_black(x_p);
320bf215546Sopenharmony_ci                rb_node_set_black(w->left);
321bf215546Sopenharmony_ci                rb_tree_rotate_right(T, x_p);
322bf215546Sopenharmony_ci                x = T->root;
323bf215546Sopenharmony_ci            }
324bf215546Sopenharmony_ci        }
325bf215546Sopenharmony_ci        x_p = rb_node_parent(x);
326bf215546Sopenharmony_ci    }
327bf215546Sopenharmony_ci    if (x)
328bf215546Sopenharmony_ci        rb_node_set_black(x);
329bf215546Sopenharmony_ci}
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_cistruct rb_node *
332bf215546Sopenharmony_cirb_tree_first(struct rb_tree *T)
333bf215546Sopenharmony_ci{
334bf215546Sopenharmony_ci    return T->root ? rb_node_minimum(T->root) : NULL;
335bf215546Sopenharmony_ci}
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_cistruct rb_node *
338bf215546Sopenharmony_cirb_tree_last(struct rb_tree *T)
339bf215546Sopenharmony_ci{
340bf215546Sopenharmony_ci    return T->root ? rb_node_maximum(T->root) : NULL;
341bf215546Sopenharmony_ci}
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_cistruct rb_node *
344bf215546Sopenharmony_cirb_node_next(struct rb_node *node)
345bf215546Sopenharmony_ci{
346bf215546Sopenharmony_ci    if (node->right) {
347bf215546Sopenharmony_ci        /* If we have a right child, then the next thing (compared to this
348bf215546Sopenharmony_ci         * node) is the left-most child of our right child.
349bf215546Sopenharmony_ci         */
350bf215546Sopenharmony_ci        return rb_node_minimum(node->right);
351bf215546Sopenharmony_ci    } else {
352bf215546Sopenharmony_ci        /* If node doesn't have a right child, crawl back up the to the
353bf215546Sopenharmony_ci         * left until we hit a parent to the right.
354bf215546Sopenharmony_ci         */
355bf215546Sopenharmony_ci        struct rb_node *p = rb_node_parent(node);
356bf215546Sopenharmony_ci        while (p && node == p->right) {
357bf215546Sopenharmony_ci            node = p;
358bf215546Sopenharmony_ci            p = rb_node_parent(node);
359bf215546Sopenharmony_ci        }
360bf215546Sopenharmony_ci        assert(p == NULL || node == p->left);
361bf215546Sopenharmony_ci        return p;
362bf215546Sopenharmony_ci    }
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_cistruct rb_node *
366bf215546Sopenharmony_cirb_node_prev(struct rb_node *node)
367bf215546Sopenharmony_ci{
368bf215546Sopenharmony_ci    if (node->left) {
369bf215546Sopenharmony_ci        /* If we have a left child, then the previous thing (compared to
370bf215546Sopenharmony_ci         * this node) is the right-most child of our left child.
371bf215546Sopenharmony_ci         */
372bf215546Sopenharmony_ci        return rb_node_maximum(node->left);
373bf215546Sopenharmony_ci    } else {
374bf215546Sopenharmony_ci        /* If node doesn't have a left child, crawl back up the to the
375bf215546Sopenharmony_ci         * right until we hit a parent to the left.
376bf215546Sopenharmony_ci         */
377bf215546Sopenharmony_ci        struct rb_node *p = rb_node_parent(node);
378bf215546Sopenharmony_ci        while (p && node == p->left) {
379bf215546Sopenharmony_ci            node = p;
380bf215546Sopenharmony_ci            p = rb_node_parent(node);
381bf215546Sopenharmony_ci        }
382bf215546Sopenharmony_ci        assert(p == NULL || node == p->right);
383bf215546Sopenharmony_ci        return p;
384bf215546Sopenharmony_ci    }
385bf215546Sopenharmony_ci}
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_cistatic void
388bf215546Sopenharmony_civalidate_rb_node(struct rb_node *n, int black_depth)
389bf215546Sopenharmony_ci{
390bf215546Sopenharmony_ci    if (n == NULL) {
391bf215546Sopenharmony_ci        assert(black_depth == 0);
392bf215546Sopenharmony_ci        return;
393bf215546Sopenharmony_ci    }
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci    if (rb_node_is_black(n)) {
396bf215546Sopenharmony_ci        black_depth--;
397bf215546Sopenharmony_ci    } else {
398bf215546Sopenharmony_ci        assert(rb_node_is_black(n->left));
399bf215546Sopenharmony_ci        assert(rb_node_is_black(n->right));
400bf215546Sopenharmony_ci    }
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci    validate_rb_node(n->left, black_depth);
403bf215546Sopenharmony_ci    validate_rb_node(n->right, black_depth);
404bf215546Sopenharmony_ci}
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_civoid
407bf215546Sopenharmony_cirb_tree_validate(struct rb_tree *T)
408bf215546Sopenharmony_ci{
409bf215546Sopenharmony_ci    if (T->root == NULL)
410bf215546Sopenharmony_ci        return;
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci    assert(rb_node_is_black(T->root));
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci    unsigned black_depth = 0;
415bf215546Sopenharmony_ci    for (struct rb_node *n = T->root; n; n = n->left) {
416bf215546Sopenharmony_ci        if (rb_node_is_black(n))
417bf215546Sopenharmony_ci            black_depth++;
418bf215546Sopenharmony_ci    }
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci    validate_rb_node(T->root, black_depth);
421bf215546Sopenharmony_ci}
422