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/** A red-black tree node
32 *
33 * This struct represents a node in the red-black tree.  This struct should
34 * be embedded as a member in whatever structure you wish to put in the
35 * tree.
36 */
37struct rb_node {
38    /** Parent and color of this node
39     *
40     * The least significant bit represents the color and is est to 1 for
41     * black and 0 for red.  The other bits are the pointer to the parent
42     * and that pointer can be retrieved by masking off the bottom bit and
43     * casting to a pointer.
44     */
45    uintptr_t parent;
46
47    /** Left child of this node, null for a leaf */
48    struct rb_node *left;
49
50    /** Right child of this node, null for a leaf */
51    struct rb_node *right;
52};
53
54/** Return the parent node of the given node or NULL if it is the root */
55static inline struct rb_node *
56rb_node_parent(struct rb_node *n)
57{
58    return (struct rb_node *)(n->parent & ~(uintptr_t)1);
59}
60
61/** A red-black tree
62 *
63 * This struct represents the red-black tree itself.  It is just a pointer
64 * to the root node with no other metadata.
65 */
66struct rb_tree {
67    struct rb_node *root;
68};
69
70/** Initialize a red-black tree */
71void rb_tree_init(struct rb_tree *T);
72
73/** Returns true if the red-black tree is empty */
74static inline bool
75rb_tree_is_empty(const struct rb_tree *T)
76{
77    return T->root == NULL;
78}
79
80/** Retrieve the data structure containing a node
81 *
82 * \param   type    The type of the containing data structure
83 *
84 * \param   node    A pointer to a rb_node
85 *
86 * \param   field   The rb_node field in the containing data structure
87 */
88#define rb_node_data(type, node, field) \
89    ((type *)(((char *)(node)) - offsetof(type, field)))
90
91/** Insert a node into a tree at a particular location
92 *
93 * This function should probably not be used directly as it relies on the
94 * caller to ensure that the parent node is correct.  Use rb_tree_insert
95 * instead.
96 *
97 * \param   T           The red-black tree into which to insert the new node
98 *
99 * \param   parent      The node in the tree that will be the parent of the
100 *                      newly inserted node
101 *
102 * \param   node        The node to insert
103 *
104 * \param   insert_left If true, the new node will be the left child of
105 *                      \p parent, otherwise it will be the right child
106 */
107void rb_tree_insert_at(struct rb_tree *T, struct rb_node *parent,
108                       struct rb_node *node, bool insert_left);
109
110/** Insert a node into a tree
111 *
112 * \param   T       The red-black tree into which to insert the new node
113 *
114 * \param   node    The node to insert
115 *
116 * \param   cmp     A comparison function to use to order the nodes.
117 */
118static inline void
119rb_tree_insert(struct rb_tree *T, struct rb_node *node,
120               int (*cmp)(const struct rb_node *, const struct rb_node *))
121{
122    /* This function is declared inline in the hopes that the compiler can
123     * optimize away the comparison function pointer call.
124     */
125    struct rb_node *y = NULL;
126    struct rb_node *x = T->root;
127    bool left = false;
128    while (x != NULL) {
129        y = x;
130        left = cmp(x, node) < 0;
131        if (left)
132            x = x->left;
133        else
134            x = x->right;
135    }
136
137    rb_tree_insert_at(T, y, node, left);
138}
139
140/** Remove a node from a tree
141 *
142 * \param   T       The red-black tree from which to remove the node
143 *
144 * \param   node    The node to remove
145 */
146void rb_tree_remove(struct rb_tree *T, struct rb_node *z);
147
148/** Search the tree for a node
149 *
150 * If a node with a matching key exists, the first matching node found will
151 * be returned.  If no matching node exists, NULL is returned.
152 *
153 * \param   T       The red-black tree to search
154 *
155 * \param   key     The key to search for
156 *
157 * \param   cmp     A comparison function to use to order the nodes
158 */
159static inline struct rb_node *
160rb_tree_search(struct rb_tree *T, const void *key,
161               int (*cmp)(const struct rb_node *, const void *))
162{
163    /* This function is declared inline in the hopes that the compiler can
164     * optimize away the comparison function pointer call.
165     */
166    struct rb_node *x = T->root;
167    while (x != NULL) {
168        int c = cmp(x, key);
169        if (c < 0)
170            x = x->left;
171        else if (c > 0)
172            x = x->right;
173        else
174            return x;
175    }
176
177    return x;
178}
179
180/** Sloppily search the tree for a node
181 *
182 * This function searches the tree for a given node.  If a node with a
183 * matching key exists, that first matching node found will be returned.
184 * If no node with an exactly matching key exists, the node returned will
185 * be either the right-most node comparing less than \p key or the
186 * right-most node comparing greater than \p key.  If the tree is empty,
187 * NULL is returned.
188 *
189 * \param   T       The red-black tree to search
190 *
191 * \param   key     The key to search for
192 *
193 * \param   cmp     A comparison function to use to order the nodes
194 */
195static inline struct rb_node *
196rb_tree_search_sloppy(struct rb_tree *T, const void *key,
197                      int (*cmp)(const struct rb_node *, const void *))
198{
199    /* This function is declared inline in the hopes that the compiler can
200     * optimize away the comparison function pointer call.
201     */
202    struct rb_node *y = NULL;
203    struct rb_node *x = T->root;
204    while (x != NULL) {
205        y = x;
206        int c = cmp(x, key);
207        if (c < 0)
208            x = x->left;
209        else if (c > 0)
210            x = x->right;
211        else
212            return x;
213    }
214
215    return y;
216}
217
218/** Get the first (left-most) node in the tree or NULL */
219struct rb_node *rb_tree_first(struct rb_tree *T);
220
221/** Get the last (right-most) node in the tree or NULL */
222struct rb_node *rb_tree_last(struct rb_tree *T);
223
224/** Get the next node (to the right) in the tree or NULL */
225struct rb_node *rb_node_next(struct rb_node *node);
226
227/** Get the next previous (to the left) in the tree or NULL */
228struct rb_node *rb_node_prev(struct rb_node *node);
229
230#define rb_node_next_or_null(n) ((n) == NULL ? NULL : rb_node_next(n))
231#define rb_node_prev_or_null(n) ((n) == NULL ? NULL : rb_node_prev(n))
232
233/** Iterate over the nodes in the tree
234 *
235 * \param   type    The type of the containing data structure
236 *
237 * \param   node    The variable name for current node in the iteration;
238 *                  this will be declared as a pointer to \p type
239 *
240 * \param   T       The red-black tree
241 *
242 * \param   field   The rb_node field in containing data structure
243 */
244#define rb_tree_foreach(type, iter, T, field) \
245   for (type *iter, *__node = (type *)rb_tree_first(T); \
246        __node != NULL && \
247        (iter = rb_node_data(type, (struct rb_node *)__node, field), true); \
248        __node = (type *)rb_node_next((struct rb_node *)__node))
249
250/** Iterate over the nodes in the tree, allowing the current node to be freed
251 *
252 * \param   type    The type of the containing data structure
253 *
254 * \param   node    The variable name for current node in the iteration;
255 *                  this will be declared as a pointer to \p type
256 *
257 * \param   T       The red-black tree
258 *
259 * \param   field   The rb_node field in containing data structure
260 */
261#define rb_tree_foreach_safe(type, iter, T, field) \
262   for (type *iter, \
263             *__node = (type *)rb_tree_first(T), \
264             *__next = (type *)rb_node_next_or_null((struct rb_node *)__node); \
265        __node != NULL && \
266        (iter = rb_node_data(type, (struct rb_node *)__node, field), true); \
267        __node = __next, \
268        __next = (type *)rb_node_next_or_null((struct rb_node *)__node))
269
270/** Iterate over the nodes in the tree in reverse
271 *
272 * \param   type    The type of the containing data structure
273 *
274 * \param   node    The variable name for current node in the iteration;
275 *                  this will be declared as a pointer to \p type
276 *
277 * \param   T       The red-black tree
278 *
279 * \param   field   The rb_node field in containing data structure
280 */
281#define rb_tree_foreach_rev(type, iter, T, field) \
282   for (type *iter, *__node = (type *)rb_tree_last(T); \
283        __node != NULL && \
284        (iter = rb_node_data(type, (struct rb_node *)__node, field), true); \
285        __node = (type *)rb_node_prev((struct rb_node *)__node))
286
287/** Iterate over the nodes in the tree in reverse, allowing the current node to be freed
288 *
289 * \param   type    The type of the containing data structure
290 *
291 * \param   node    The variable name for current node in the iteration;
292 *                  this will be declared as a pointer to \p type
293 *
294 * \param   T       The red-black tree
295 *
296 * \param   field   The rb_node field in containing data structure
297 */
298#define rb_tree_foreach_rev_safe(type, iter, T, field) \
299   for (type *iter, \
300             *__node = (type *)rb_tree_last(T), \
301             *__prev = (type *)rb_node_prev_or_null((struct rb_node *)__node); \
302        __node != NULL && \
303        (iter = rb_node_data(type, (struct rb_node *)__node, field), true); \
304        __node = __prev, \
305        __prev = (type *)rb_node_prev_or_null((struct rb_node *)__node))
306
307/** Validate a red-black tree
308 *
309 * This function walks the tree and validates that this is a valid red-
310 * black tree.  If anything is wrong, it will assert-fail.
311 */
312void rb_tree_validate(struct rb_tree *T);
313
314#endif /* RB_TREE_H */
315