xref: /third_party/mesa3d/src/util/rb_tree.h (revision bf215546)
1/*
2 * Copyright © 2017 Jason Ekstrand
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#ifndef RB_TREE_H
24#define RB_TREE_H
25
26#include <stdbool.h>
27#include <stddef.h>
28#include <stdint.h>
29#include <stdlib.h>
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35/** A red-black tree node
36 *
37 * This struct represents a node in the red-black tree.  This struct should
38 * be embedded as a member in whatever structure you wish to put in the
39 * tree.
40 */
41struct rb_node {
42    /** Parent and color of this node
43     *
44     * The least significant bit represents the color and is est to 1 for
45     * black and 0 for red.  The other bits are the pointer to the parent
46     * and that pointer can be retrieved by masking off the bottom bit and
47     * casting to a pointer.
48     */
49    uintptr_t parent;
50
51    /** Left child of this node, null for a leaf */
52    struct rb_node *left;
53
54    /** Right child of this node, null for a leaf */
55    struct rb_node *right;
56};
57
58/** Return the parent node of the given node or NULL if it is the root */
59static inline struct rb_node *
60rb_node_parent(struct rb_node *n)
61{
62    return (struct rb_node *)(n->parent & ~(uintptr_t)1);
63}
64
65/** A red-black tree
66 *
67 * This struct represents the red-black tree itself.  It is just a pointer
68 * to the root node with no other metadata.
69 */
70struct rb_tree {
71    struct rb_node *root;
72};
73
74/** Initialize a red-black tree */
75void rb_tree_init(struct rb_tree *T);
76
77/** Returns true if the red-black tree is empty */
78static inline bool
79rb_tree_is_empty(const struct rb_tree *T)
80{
81    return T->root == NULL;
82}
83
84/** Retrieve the data structure containing a node
85 *
86 * \param   type    The type of the containing data structure
87 *
88 * \param   node    A pointer to a rb_node
89 *
90 * \param   field   The rb_node field in the containing data structure
91 */
92#define rb_node_data(type, node, field) \
93    ((type *)(((char *)(node)) - offsetof(type, field)))
94
95/** Insert a node into a tree at a particular location
96 *
97 * This function should probably not be used directly as it relies on the
98 * caller to ensure that the parent node is correct.  Use rb_tree_insert
99 * instead.
100 *
101 * \param   T           The red-black tree into which to insert the new node
102 *
103 * \param   parent      The node in the tree that will be the parent of the
104 *                      newly inserted node
105 *
106 * \param   node        The node to insert
107 *
108 * \param   insert_left If true, the new node will be the left child of
109 *                      \p parent, otherwise it will be the right child
110 */
111void rb_tree_insert_at(struct rb_tree *T, struct rb_node *parent,
112                       struct rb_node *node, bool insert_left);
113
114/** Insert a node into a tree
115 *
116 * \param   T       The red-black tree into which to insert the new node
117 *
118 * \param   node    The node to insert
119 *
120 * \param   cmp     A comparison function to use to order the nodes.
121 */
122static inline void
123rb_tree_insert(struct rb_tree *T, struct rb_node *node,
124               int (*cmp)(const struct rb_node *, const struct rb_node *))
125{
126    /* This function is declared inline in the hopes that the compiler can
127     * optimize away the comparison function pointer call.
128     */
129    struct rb_node *y = NULL;
130    struct rb_node *x = T->root;
131    bool left = false;
132    while (x != NULL) {
133        y = x;
134        left = cmp(x, node) < 0;
135        if (left)
136            x = x->left;
137        else
138            x = x->right;
139    }
140
141    rb_tree_insert_at(T, y, node, left);
142}
143
144/** Remove a node from a tree
145 *
146 * \param   T       The red-black tree from which to remove the node
147 *
148 * \param   node    The node to remove
149 */
150void rb_tree_remove(struct rb_tree *T, struct rb_node *z);
151
152/** Search the tree for a node
153 *
154 * If a node with a matching key exists, the first matching node found will
155 * be returned.  If no matching node exists, NULL is returned.
156 *
157 * \param   T       The red-black tree to search
158 *
159 * \param   key     The key to search for
160 *
161 * \param   cmp     A comparison function to use to order the nodes
162 */
163static inline struct rb_node *
164rb_tree_search(struct rb_tree *T, const void *key,
165               int (*cmp)(const struct rb_node *, const void *))
166{
167    /* This function is declared inline in the hopes that the compiler can
168     * optimize away the comparison function pointer call.
169     */
170    struct rb_node *x = T->root;
171    while (x != NULL) {
172        int c = cmp(x, key);
173        if (c < 0)
174            x = x->left;
175        else if (c > 0)
176            x = x->right;
177        else
178            return x;
179    }
180
181    return x;
182}
183
184/** Sloppily search the tree for a node
185 *
186 * This function searches the tree for a given node.  If a node with a
187 * matching key exists, that first matching node found will be returned.
188 * If no node with an exactly matching key exists, the node returned will
189 * be either the right-most node comparing less than \p key or the
190 * right-most node comparing greater than \p key.  If the tree is empty,
191 * NULL is returned.
192 *
193 * \param   T       The red-black tree to search
194 *
195 * \param   key     The key to search for
196 *
197 * \param   cmp     A comparison function to use to order the nodes
198 */
199static inline struct rb_node *
200rb_tree_search_sloppy(struct rb_tree *T, const void *key,
201                      int (*cmp)(const struct rb_node *, const void *))
202{
203    /* This function is declared inline in the hopes that the compiler can
204     * optimize away the comparison function pointer call.
205     */
206    struct rb_node *y = NULL;
207    struct rb_node *x = T->root;
208    while (x != NULL) {
209        y = x;
210        int c = cmp(x, key);
211        if (c < 0)
212            x = x->left;
213        else if (c > 0)
214            x = x->right;
215        else
216            return x;
217    }
218
219    return y;
220}
221
222/** Get the first (left-most) node in the tree or NULL */
223struct rb_node *rb_tree_first(struct rb_tree *T);
224
225/** Get the last (right-most) node in the tree or NULL */
226struct rb_node *rb_tree_last(struct rb_tree *T);
227
228/** Get the next node (to the right) in the tree or NULL */
229struct rb_node *rb_node_next(struct rb_node *node);
230
231/** Get the next previous (to the left) in the tree or NULL */
232struct rb_node *rb_node_prev(struct rb_node *node);
233
234#define rb_node_next_or_null(n) ((n) == NULL ? NULL : rb_node_next(n))
235#define rb_node_prev_or_null(n) ((n) == NULL ? NULL : rb_node_prev(n))
236
237/** Iterate over the nodes in the tree
238 *
239 * \param   type    The type of the containing data structure
240 *
241 * \param   node    The variable name for current node in the iteration;
242 *                  this will be declared as a pointer to \p type
243 *
244 * \param   T       The red-black tree
245 *
246 * \param   field   The rb_node field in containing data structure
247 */
248#define rb_tree_foreach(type, iter, T, field) \
249   for (type *iter, *__node = (type *)rb_tree_first(T); \
250        __node != NULL && \
251        (iter = rb_node_data(type, (struct rb_node *)__node, field), true); \
252        __node = (type *)rb_node_next((struct rb_node *)__node))
253
254/** Iterate over the nodes in the tree, allowing the current node to be freed
255 *
256 * \param   type    The type of the containing data structure
257 *
258 * \param   node    The variable name for current node in the iteration;
259 *                  this will be declared as a pointer to \p type
260 *
261 * \param   T       The red-black tree
262 *
263 * \param   field   The rb_node field in containing data structure
264 */
265#define rb_tree_foreach_safe(type, iter, T, field) \
266   for (type *iter, \
267             *__node = (type *)rb_tree_first(T), \
268             *__next = (type *)rb_node_next_or_null((struct rb_node *)__node); \
269        __node != NULL && \
270        (iter = rb_node_data(type, (struct rb_node *)__node, field), true); \
271        __node = __next, \
272        __next = (type *)rb_node_next_or_null((struct rb_node *)__node))
273
274/** Iterate over the nodes in the tree in reverse
275 *
276 * \param   type    The type of the containing data structure
277 *
278 * \param   node    The variable name for current node in the iteration;
279 *                  this will be declared as a pointer to \p type
280 *
281 * \param   T       The red-black tree
282 *
283 * \param   field   The rb_node field in containing data structure
284 */
285#define rb_tree_foreach_rev(type, iter, T, field) \
286   for (type *iter, *__node = (type *)rb_tree_last(T); \
287        __node != NULL && \
288        (iter = rb_node_data(type, (struct rb_node *)__node, field), true); \
289        __node = (type *)rb_node_prev((struct rb_node *)__node))
290
291/** Iterate over the nodes in the tree in reverse, allowing the current node to be freed
292 *
293 * \param   type    The type of the containing data structure
294 *
295 * \param   node    The variable name for current node in the iteration;
296 *                  this will be declared as a pointer to \p type
297 *
298 * \param   T       The red-black tree
299 *
300 * \param   field   The rb_node field in containing data structure
301 */
302#define rb_tree_foreach_rev_safe(type, iter, T, field) \
303   for (type *iter, \
304             *__node = (type *)rb_tree_last(T), \
305             *__prev = (type *)rb_node_prev_or_null((struct rb_node *)__node); \
306        __node != NULL && \
307        (iter = rb_node_data(type, (struct rb_node *)__node, field), true); \
308        __node = __prev, \
309        __prev = (type *)rb_node_prev_or_null((struct rb_node *)__node))
310
311/** Validate a red-black tree
312 *
313 * This function walks the tree and validates that this is a valid red-
314 * black tree.  If anything is wrong, it will assert-fail.
315 */
316void rb_tree_validate(struct rb_tree *T);
317
318#ifdef __cplusplus
319} /* extern C */
320#endif
321
322#endif /* RB_TREE_H */
323