• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-
2  *******************************************************************************
3  *
4  * cpp macro implementation of left-leaning 2-3 red-black trees.  Parent
5  * pointers are not used, and color bits are stored in the least significant
6  * bit of right-child pointers (if RB_COMPACT is defined), thus making node
7  * linkage as compact as is possible for red-black trees.
8  *
9  * Usage:
10  *
11  *   #include <stdint.h>
12  *   #include <stdbool.h>
13  *   #define NDEBUG // (Optional, see assert(3).)
14  *   #include <assert.h>
15  *   #define RB_COMPACT // (Optional, embed color bits in right-child pointers.)
16  *   #include <rb.h>
17  *   ...
18  *
19  *******************************************************************************
20  */
21 
22 #ifndef RB_H_
23 #define	RB_H_
24 
25 #ifdef RB_COMPACT
26 /* Node structure. */
27 #define	rb_node(a_type)							\
28 struct {								\
29     a_type *rbn_left;							\
30     a_type *rbn_right_red;						\
31 }
32 #else
33 #define	rb_node(a_type)							\
34 struct {								\
35     a_type *rbn_left;							\
36     a_type *rbn_right;							\
37     bool rbn_red;							\
38 }
39 #endif
40 
41 /* Root structure. */
42 #define	rb_tree(a_type)							\
43 struct {								\
44     a_type *rbt_root;							\
45 }
46 
47 /* Left accessors. */
48 #define	rbtn_left_get(a_type, a_field, a_node)				\
49     ((a_node)->a_field.rbn_left)
50 #define	rbtn_left_set(a_type, a_field, a_node, a_left) do {		\
51     (a_node)->a_field.rbn_left = a_left;				\
52 } while (0)
53 
54 #ifdef RB_COMPACT
55 /* Right accessors. */
56 #define	rbtn_right_get(a_type, a_field, a_node)				\
57     ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red)		\
58       & ((ssize_t)-2)))
59 #define	rbtn_right_set(a_type, a_field, a_node, a_right) do {		\
60     (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right)	\
61       | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1)));	\
62 } while (0)
63 
64 /* Color accessors. */
65 #define	rbtn_red_get(a_type, a_field, a_node)				\
66     ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red)		\
67       & ((size_t)1)))
68 #define	rbtn_color_set(a_type, a_field, a_node, a_red) do {		\
69     (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t)		\
70       (a_node)->a_field.rbn_right_red) & ((ssize_t)-2))			\
71       | ((ssize_t)a_red));						\
72 } while (0)
73 #define	rbtn_red_set(a_type, a_field, a_node) do {			\
74     (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t)		\
75       (a_node)->a_field.rbn_right_red) | ((size_t)1));			\
76 } while (0)
77 #define	rbtn_black_set(a_type, a_field, a_node) do {			\
78     (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t)		\
79       (a_node)->a_field.rbn_right_red) & ((ssize_t)-2));		\
80 } while (0)
81 
82 /* Node initializer. */
83 #define	rbt_node_new(a_type, a_field, a_rbt, a_node) do {		\
84     /* Bookkeeping bit cannot be used by node pointer. */		\
85     assert(((uintptr_t)(a_node) & 0x1) == 0);				\
86     rbtn_left_set(a_type, a_field, (a_node), NULL);	\
87     rbtn_right_set(a_type, a_field, (a_node), NULL);	\
88     rbtn_red_set(a_type, a_field, (a_node));				\
89 } while (0)
90 #else
91 /* Right accessors. */
92 #define	rbtn_right_get(a_type, a_field, a_node)				\
93     ((a_node)->a_field.rbn_right)
94 #define	rbtn_right_set(a_type, a_field, a_node, a_right) do {		\
95     (a_node)->a_field.rbn_right = a_right;				\
96 } while (0)
97 
98 /* Color accessors. */
99 #define	rbtn_red_get(a_type, a_field, a_node)				\
100     ((a_node)->a_field.rbn_red)
101 #define	rbtn_color_set(a_type, a_field, a_node, a_red) do {		\
102     (a_node)->a_field.rbn_red = (a_red);				\
103 } while (0)
104 #define	rbtn_red_set(a_type, a_field, a_node) do {			\
105     (a_node)->a_field.rbn_red = true;					\
106 } while (0)
107 #define	rbtn_black_set(a_type, a_field, a_node) do {			\
108     (a_node)->a_field.rbn_red = false;					\
109 } while (0)
110 
111 /* Node initializer. */
112 #define	rbt_node_new(a_type, a_field, a_rbt, a_node) do {		\
113     rbtn_left_set(a_type, a_field, (a_node), NULL);	\
114     rbtn_right_set(a_type, a_field, (a_node), NULL);	\
115     rbtn_red_set(a_type, a_field, (a_node));				\
116 } while (0)
117 #endif
118 
119 /* Tree initializer. */
120 #define	rb_new(a_type, a_field, a_rbt) do {				\
121     (a_rbt)->rbt_root = NULL;						\
122 } while (0)
123 
124 /* Internal utility macros. */
125 #define	rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do {		\
126     (r_node) = (a_root);						\
127     if ((r_node) != NULL) {						\
128 	for (;								\
129 	  rbtn_left_get(a_type, a_field, (r_node)) != NULL;		\
130 	  (r_node) = rbtn_left_get(a_type, a_field, (r_node))) {	\
131 	}								\
132     }									\
133 } while (0)
134 
135 #define	rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do {		\
136     (r_node) = (a_root);						\
137     if ((r_node) != NULL) {						\
138 	for (; rbtn_right_get(a_type, a_field, (r_node)) != NULL;	\
139 	  (r_node) = rbtn_right_get(a_type, a_field, (r_node))) {	\
140 	}								\
141     }									\
142 } while (0)
143 
144 #define	rbtn_rotate_left(a_type, a_field, a_node, r_node) do {		\
145     (r_node) = rbtn_right_get(a_type, a_field, (a_node));		\
146     rbtn_right_set(a_type, a_field, (a_node),				\
147       rbtn_left_get(a_type, a_field, (r_node)));			\
148     rbtn_left_set(a_type, a_field, (r_node), (a_node));			\
149 } while (0)
150 
151 #define	rbtn_rotate_right(a_type, a_field, a_node, r_node) do {		\
152     (r_node) = rbtn_left_get(a_type, a_field, (a_node));		\
153     rbtn_left_set(a_type, a_field, (a_node),				\
154       rbtn_right_get(a_type, a_field, (r_node)));			\
155     rbtn_right_set(a_type, a_field, (r_node), (a_node));		\
156 } while (0)
157 
158 /*
159  * The rb_proto() macro generates function prototypes that correspond to the
160  * functions generated by an equivalently parameterized call to rb_gen().
161  */
162 
163 #define	rb_proto(a_attr, a_prefix, a_rbt_type, a_type)			\
164 a_attr void								\
165 a_prefix##new(a_rbt_type *rbtree);					\
166 a_attr bool								\
167 a_prefix##empty(a_rbt_type *rbtree);					\
168 a_attr a_type *								\
169 a_prefix##first(a_rbt_type *rbtree);					\
170 a_attr a_type *								\
171 a_prefix##last(a_rbt_type *rbtree);					\
172 a_attr a_type *								\
173 a_prefix##next(a_rbt_type *rbtree, a_type *node);			\
174 a_attr a_type *								\
175 a_prefix##prev(a_rbt_type *rbtree, a_type *node);			\
176 a_attr a_type *								\
177 a_prefix##search(a_rbt_type *rbtree, const a_type *key);		\
178 a_attr a_type *								\
179 a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key);		\
180 a_attr a_type *								\
181 a_prefix##psearch(a_rbt_type *rbtree, const a_type *key);		\
182 a_attr void								\
183 a_prefix##insert(a_rbt_type *rbtree, a_type *node);			\
184 a_attr void								\
185 a_prefix##remove(a_rbt_type *rbtree, a_type *node);			\
186 a_attr a_type *								\
187 a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(	\
188   a_rbt_type *, a_type *, void *), void *arg);				\
189 a_attr a_type *								\
190 a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,		\
191   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg);		\
192 a_attr void								\
193 a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *),	\
194   void *arg);
195 
196 /*
197  * The rb_gen() macro generates a type-specific red-black tree implementation,
198  * based on the above cpp macros.
199  *
200  * Arguments:
201  *
202  *   a_attr    : Function attribute for generated functions (ex: static).
203  *   a_prefix  : Prefix for generated functions (ex: ex_).
204  *   a_rb_type : Type for red-black tree data structure (ex: ex_t).
205  *   a_type    : Type for red-black tree node data structure (ex: ex_node_t).
206  *   a_field   : Name of red-black tree node linkage (ex: ex_link).
207  *   a_cmp     : Node comparison function name, with the following prototype:
208  *                 int (a_cmp *)(a_type *a_node, a_type *a_other);
209  *                                       ^^^^^^
210  *                                    or a_key
211  *               Interpretation of comparison function return values:
212  *                 -1 : a_node <  a_other
213  *                  0 : a_node == a_other
214  *                  1 : a_node >  a_other
215  *               In all cases, the a_node or a_key macro argument is the first
216  *               argument to the comparison function, which makes it possible
217  *               to write comparison functions that treat the first argument
218  *               specially.
219  *
220  * Assuming the following setup:
221  *
222  *   typedef struct ex_node_s ex_node_t;
223  *   struct ex_node_s {
224  *       rb_node(ex_node_t) ex_link;
225  *   };
226  *   typedef rb_tree(ex_node_t) ex_t;
227  *   rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp)
228  *
229  * The following API is generated:
230  *
231  *   static void
232  *   ex_new(ex_t *tree);
233  *       Description: Initialize a red-black tree structure.
234  *       Args:
235  *         tree: Pointer to an uninitialized red-black tree object.
236  *
237  *   static bool
238  *   ex_empty(ex_t *tree);
239  *       Description: Determine whether tree is empty.
240  *       Args:
241  *         tree: Pointer to an initialized red-black tree object.
242  *       Ret: True if tree is empty, false otherwise.
243  *
244  *   static ex_node_t *
245  *   ex_first(ex_t *tree);
246  *   static ex_node_t *
247  *   ex_last(ex_t *tree);
248  *       Description: Get the first/last node in tree.
249  *       Args:
250  *         tree: Pointer to an initialized red-black tree object.
251  *       Ret: First/last node in tree, or NULL if tree is empty.
252  *
253  *   static ex_node_t *
254  *   ex_next(ex_t *tree, ex_node_t *node);
255  *   static ex_node_t *
256  *   ex_prev(ex_t *tree, ex_node_t *node);
257  *       Description: Get node's successor/predecessor.
258  *       Args:
259  *         tree: Pointer to an initialized red-black tree object.
260  *         node: A node in tree.
261  *       Ret: node's successor/predecessor in tree, or NULL if node is
262  *            last/first.
263  *
264  *   static ex_node_t *
265  *   ex_search(ex_t *tree, const ex_node_t *key);
266  *       Description: Search for node that matches key.
267  *       Args:
268  *         tree: Pointer to an initialized red-black tree object.
269  *         key : Search key.
270  *       Ret: Node in tree that matches key, or NULL if no match.
271  *
272  *   static ex_node_t *
273  *   ex_nsearch(ex_t *tree, const ex_node_t *key);
274  *   static ex_node_t *
275  *   ex_psearch(ex_t *tree, const ex_node_t *key);
276  *       Description: Search for node that matches key.  If no match is found,
277  *                    return what would be key's successor/predecessor, were
278  *                    key in tree.
279  *       Args:
280  *         tree: Pointer to an initialized red-black tree object.
281  *         key : Search key.
282  *       Ret: Node in tree that matches key, or if no match, hypothetical node's
283  *            successor/predecessor (NULL if no successor/predecessor).
284  *
285  *   static void
286  *   ex_insert(ex_t *tree, ex_node_t *node);
287  *       Description: Insert node into tree.
288  *       Args:
289  *         tree: Pointer to an initialized red-black tree object.
290  *         node: Node to be inserted into tree.
291  *
292  *   static void
293  *   ex_remove(ex_t *tree, ex_node_t *node);
294  *       Description: Remove node from tree.
295  *       Args:
296  *         tree: Pointer to an initialized red-black tree object.
297  *         node: Node in tree to be removed.
298  *
299  *   static ex_node_t *
300  *   ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,
301  *     ex_node_t *, void *), void *arg);
302  *   static ex_node_t *
303  *   ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,
304  *     ex_node_t *, void *), void *arg);
305  *       Description: Iterate forward/backward over tree, starting at node.  If
306  *                    tree is modified, iteration must be immediately
307  *                    terminated by the callback function that causes the
308  *                    modification.
309  *       Args:
310  *         tree : Pointer to an initialized red-black tree object.
311  *         start: Node at which to start iteration, or NULL to start at
312  *                first/last node.
313  *         cb   : Callback function, which is called for each node during
314  *                iteration.  Under normal circumstances the callback function
315  *                should return NULL, which causes iteration to continue.  If a
316  *                callback function returns non-NULL, iteration is immediately
317  *                terminated and the non-NULL return value is returned by the
318  *                iterator.  This is useful for re-starting iteration after
319  *                modifying tree.
320  *         arg  : Opaque pointer passed to cb().
321  *       Ret: NULL if iteration completed, or the non-NULL callback return value
322  *            that caused termination of the iteration.
323  *
324  *   static void
325  *   ex_destroy(ex_t *tree, void (*cb)(ex_node_t *, void *), void *arg);
326  *       Description: Iterate over the tree with post-order traversal, remove
327  *                    each node, and run the callback if non-null.  This is
328  *                    used for destroying a tree without paying the cost to
329  *                    rebalance it.  The tree must not be otherwise altered
330  *                    during traversal.
331  *       Args:
332  *         tree: Pointer to an initialized red-black tree object.
333  *         cb  : Callback function, which, if non-null, is called for each node
334  *               during iteration.  There is no way to stop iteration once it
335  *               has begun.
336  *         arg : Opaque pointer passed to cb().
337  */
338 #define	rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp)	\
339 a_attr void								\
340 a_prefix##new(a_rbt_type *rbtree) {					\
341     rb_new(a_type, a_field, rbtree);					\
342 }									\
343 a_attr bool								\
344 a_prefix##empty(a_rbt_type *rbtree) {					\
345     return (rbtree->rbt_root == NULL);					\
346 }									\
347 a_attr a_type *								\
348 a_prefix##first(a_rbt_type *rbtree) {					\
349     a_type *ret;							\
350     rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret);		\
351     return (ret);							\
352 }									\
353 a_attr a_type *								\
354 a_prefix##last(a_rbt_type *rbtree) {					\
355     a_type *ret;							\
356     rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret);		\
357     return (ret);							\
358 }									\
359 a_attr a_type *								\
360 a_prefix##next(a_rbt_type *rbtree, a_type *node) {			\
361     a_type *ret;							\
362     if (rbtn_right_get(a_type, a_field, node) != NULL) {		\
363 	rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type,	\
364 	  a_field, node), ret);						\
365     } else {								\
366 	a_type *tnode = rbtree->rbt_root;				\
367 	assert(tnode != NULL);						\
368 	ret = NULL;							\
369 	while (true) {							\
370 	    int cmp = (a_cmp)(node, tnode);				\
371 	    if (cmp < 0) {						\
372 		ret = tnode;						\
373 		tnode = rbtn_left_get(a_type, a_field, tnode);		\
374 	    } else if (cmp > 0) {					\
375 		tnode = rbtn_right_get(a_type, a_field, tnode);		\
376 	    } else {							\
377 		break;							\
378 	    }								\
379 	    assert(tnode != NULL);					\
380 	}								\
381     }									\
382     return (ret);							\
383 }									\
384 a_attr a_type *								\
385 a_prefix##prev(a_rbt_type *rbtree, a_type *node) {			\
386     a_type *ret;							\
387     if (rbtn_left_get(a_type, a_field, node) != NULL) {			\
388 	rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type,	\
389 	  a_field, node), ret);						\
390     } else {								\
391 	a_type *tnode = rbtree->rbt_root;				\
392 	assert(tnode != NULL);						\
393 	ret = NULL;							\
394 	while (true) {							\
395 	    int cmp = (a_cmp)(node, tnode);				\
396 	    if (cmp < 0) {						\
397 		tnode = rbtn_left_get(a_type, a_field, tnode);		\
398 	    } else if (cmp > 0) {					\
399 		ret = tnode;						\
400 		tnode = rbtn_right_get(a_type, a_field, tnode);		\
401 	    } else {							\
402 		break;							\
403 	    }								\
404 	    assert(tnode != NULL);					\
405 	}								\
406     }									\
407     return (ret);							\
408 }									\
409 a_attr a_type *								\
410 a_prefix##search(a_rbt_type *rbtree, const a_type *key) {		\
411     a_type *ret;							\
412     int cmp;								\
413     ret = rbtree->rbt_root;						\
414     while (ret != NULL							\
415       && (cmp = (a_cmp)(key, ret)) != 0) {				\
416 	if (cmp < 0) {							\
417 	    ret = rbtn_left_get(a_type, a_field, ret);			\
418 	} else {							\
419 	    ret = rbtn_right_get(a_type, a_field, ret);			\
420 	}								\
421     }									\
422     return (ret);							\
423 }									\
424 a_attr a_type *								\
425 a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) {		\
426     a_type *ret;							\
427     a_type *tnode = rbtree->rbt_root;					\
428     ret = NULL;								\
429     while (tnode != NULL) {						\
430 	int cmp = (a_cmp)(key, tnode);					\
431 	if (cmp < 0) {							\
432 	    ret = tnode;						\
433 	    tnode = rbtn_left_get(a_type, a_field, tnode);		\
434 	} else if (cmp > 0) {						\
435 	    tnode = rbtn_right_get(a_type, a_field, tnode);		\
436 	} else {							\
437 	    ret = tnode;						\
438 	    break;							\
439 	}								\
440     }									\
441     return (ret);							\
442 }									\
443 a_attr a_type *								\
444 a_prefix##psearch(a_rbt_type *rbtree, const a_type *key) {		\
445     a_type *ret;							\
446     a_type *tnode = rbtree->rbt_root;					\
447     ret = NULL;								\
448     while (tnode != NULL) {						\
449 	int cmp = (a_cmp)(key, tnode);					\
450 	if (cmp < 0) {							\
451 	    tnode = rbtn_left_get(a_type, a_field, tnode);		\
452 	} else if (cmp > 0) {						\
453 	    ret = tnode;						\
454 	    tnode = rbtn_right_get(a_type, a_field, tnode);		\
455 	} else {							\
456 	    ret = tnode;						\
457 	    break;							\
458 	}								\
459     }									\
460     return (ret);							\
461 }									\
462 a_attr void								\
463 a_prefix##insert(a_rbt_type *rbtree, a_type *node) {			\
464     struct {								\
465 	a_type *node;							\
466 	int cmp;							\
467     } path[sizeof(void *) << 4], *pathp;				\
468     rbt_node_new(a_type, a_field, rbtree, node);			\
469     /* Wind. */								\
470     path->node = rbtree->rbt_root;					\
471     for (pathp = path; pathp->node != NULL; pathp++) {			\
472 	int cmp = pathp->cmp = a_cmp(node, pathp->node);		\
473 	assert(cmp != 0);						\
474 	if (cmp < 0) {							\
475 	    pathp[1].node = rbtn_left_get(a_type, a_field,		\
476 	      pathp->node);						\
477 	} else {							\
478 	    pathp[1].node = rbtn_right_get(a_type, a_field,		\
479 	      pathp->node);						\
480 	}								\
481     }									\
482     pathp->node = node;							\
483     /* Unwind. */							\
484     for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {	\
485 	a_type *cnode = pathp->node;					\
486 	if (pathp->cmp < 0) {						\
487 	    a_type *left = pathp[1].node;				\
488 	    rbtn_left_set(a_type, a_field, cnode, left);		\
489 	    if (rbtn_red_get(a_type, a_field, left)) {			\
490 		a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
491 		if (leftleft != NULL && rbtn_red_get(a_type, a_field,	\
492 		  leftleft)) {						\
493 		    /* Fix up 4-node. */				\
494 		    a_type *tnode;					\
495 		    rbtn_black_set(a_type, a_field, leftleft);		\
496 		    rbtn_rotate_right(a_type, a_field, cnode, tnode);	\
497 		    cnode = tnode;					\
498 		}							\
499 	    } else {							\
500 		return;							\
501 	    }								\
502 	} else {							\
503 	    a_type *right = pathp[1].node;				\
504 	    rbtn_right_set(a_type, a_field, cnode, right);		\
505 	    if (rbtn_red_get(a_type, a_field, right)) {			\
506 		a_type *left = rbtn_left_get(a_type, a_field, cnode);	\
507 		if (left != NULL && rbtn_red_get(a_type, a_field,	\
508 		  left)) {						\
509 		    /* Split 4-node. */					\
510 		    rbtn_black_set(a_type, a_field, left);		\
511 		    rbtn_black_set(a_type, a_field, right);		\
512 		    rbtn_red_set(a_type, a_field, cnode);		\
513 		} else {						\
514 		    /* Lean left. */					\
515 		    a_type *tnode;					\
516 		    bool tred = rbtn_red_get(a_type, a_field, cnode);	\
517 		    rbtn_rotate_left(a_type, a_field, cnode, tnode);	\
518 		    rbtn_color_set(a_type, a_field, tnode, tred);	\
519 		    rbtn_red_set(a_type, a_field, cnode);		\
520 		    cnode = tnode;					\
521 		}							\
522 	    } else {							\
523 		return;							\
524 	    }								\
525 	}								\
526 	pathp->node = cnode;						\
527     }									\
528     /* Set root, and make it black. */					\
529     rbtree->rbt_root = path->node;					\
530     rbtn_black_set(a_type, a_field, rbtree->rbt_root);			\
531 }									\
532 a_attr void								\
533 a_prefix##remove(a_rbt_type *rbtree, a_type *node) {			\
534     struct {								\
535 	a_type *node;							\
536 	int cmp;							\
537     } *pathp, *nodep, path[sizeof(void *) << 4];			\
538     /* Wind. */								\
539     nodep = NULL; /* Silence compiler warning. */			\
540     path->node = rbtree->rbt_root;					\
541     for (pathp = path; pathp->node != NULL; pathp++) {			\
542 	int cmp = pathp->cmp = a_cmp(node, pathp->node);		\
543 	if (cmp < 0) {							\
544 	    pathp[1].node = rbtn_left_get(a_type, a_field,		\
545 	      pathp->node);						\
546 	} else {							\
547 	    pathp[1].node = rbtn_right_get(a_type, a_field,		\
548 	      pathp->node);						\
549 	    if (cmp == 0) {						\
550 	        /* Find node's successor, in preparation for swap. */	\
551 		pathp->cmp = 1;						\
552 		nodep = pathp;						\
553 		for (pathp++; pathp->node != NULL;			\
554 		  pathp++) {						\
555 		    pathp->cmp = -1;					\
556 		    pathp[1].node = rbtn_left_get(a_type, a_field,	\
557 		      pathp->node);					\
558 		}							\
559 		break;							\
560 	    }								\
561 	}								\
562     }									\
563     assert(nodep->node == node);					\
564     pathp--;								\
565     if (pathp->node != node) {						\
566 	/* Swap node with its successor. */				\
567 	bool tred = rbtn_red_get(a_type, a_field, pathp->node);		\
568 	rbtn_color_set(a_type, a_field, pathp->node,			\
569 	  rbtn_red_get(a_type, a_field, node));				\
570 	rbtn_left_set(a_type, a_field, pathp->node,			\
571 	  rbtn_left_get(a_type, a_field, node));			\
572 	/* If node's successor is its right child, the following code */\
573 	/* will do the wrong thing for the right child pointer.       */\
574 	/* However, it doesn't matter, because the pointer will be    */\
575 	/* properly set when the successor is pruned.                 */\
576 	rbtn_right_set(a_type, a_field, pathp->node,			\
577 	  rbtn_right_get(a_type, a_field, node));			\
578 	rbtn_color_set(a_type, a_field, node, tred);			\
579 	/* The pruned leaf node's child pointers are never accessed   */\
580 	/* again, so don't bother setting them to nil.                */\
581 	nodep->node = pathp->node;					\
582 	pathp->node = node;						\
583 	if (nodep == path) {						\
584 	    rbtree->rbt_root = nodep->node;				\
585 	} else {							\
586 	    if (nodep[-1].cmp < 0) {					\
587 		rbtn_left_set(a_type, a_field, nodep[-1].node,		\
588 		  nodep->node);						\
589 	    } else {							\
590 		rbtn_right_set(a_type, a_field, nodep[-1].node,		\
591 		  nodep->node);						\
592 	    }								\
593 	}								\
594     } else {								\
595 	a_type *left = rbtn_left_get(a_type, a_field, node);		\
596 	if (left != NULL) {						\
597 	    /* node has no successor, but it has a left child.        */\
598 	    /* Splice node out, without losing the left child.        */\
599 	    assert(!rbtn_red_get(a_type, a_field, node));		\
600 	    assert(rbtn_red_get(a_type, a_field, left));		\
601 	    rbtn_black_set(a_type, a_field, left);			\
602 	    if (pathp == path) {					\
603 		rbtree->rbt_root = left;				\
604 	    } else {							\
605 		if (pathp[-1].cmp < 0) {				\
606 		    rbtn_left_set(a_type, a_field, pathp[-1].node,	\
607 		      left);						\
608 		} else {						\
609 		    rbtn_right_set(a_type, a_field, pathp[-1].node,	\
610 		      left);						\
611 		}							\
612 	    }								\
613 	    return;							\
614 	} else if (pathp == path) {					\
615 	    /* The tree only contained one node. */			\
616 	    rbtree->rbt_root = NULL;					\
617 	    return;							\
618 	}								\
619     }									\
620     if (rbtn_red_get(a_type, a_field, pathp->node)) {			\
621 	/* Prune red node, which requires no fixup. */			\
622 	assert(pathp[-1].cmp < 0);					\
623 	rbtn_left_set(a_type, a_field, pathp[-1].node, NULL);		\
624 	return;								\
625     }									\
626     /* The node to be pruned is black, so unwind until balance is     */\
627     /* restored.                                                      */\
628     pathp->node = NULL;							\
629     for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) {	\
630 	assert(pathp->cmp != 0);					\
631 	if (pathp->cmp < 0) {						\
632 	    rbtn_left_set(a_type, a_field, pathp->node,			\
633 	      pathp[1].node);						\
634 	    if (rbtn_red_get(a_type, a_field, pathp->node)) {		\
635 		a_type *right = rbtn_right_get(a_type, a_field,		\
636 		  pathp->node);						\
637 		a_type *rightleft = rbtn_left_get(a_type, a_field,	\
638 		  right);						\
639 		a_type *tnode;						\
640 		if (rightleft != NULL && rbtn_red_get(a_type, a_field,	\
641 		  rightleft)) {						\
642 		    /* In the following diagrams, ||, //, and \\      */\
643 		    /* indicate the path to the removed node.         */\
644 		    /*                                                */\
645 		    /*      ||                                        */\
646 		    /*    pathp(r)                                    */\
647 		    /*  //        \                                   */\
648 		    /* (b)        (b)                                 */\
649 		    /*           /                                    */\
650 		    /*          (r)                                   */\
651 		    /*                                                */\
652 		    rbtn_black_set(a_type, a_field, pathp->node);	\
653 		    rbtn_rotate_right(a_type, a_field, right, tnode);	\
654 		    rbtn_right_set(a_type, a_field, pathp->node, tnode);\
655 		    rbtn_rotate_left(a_type, a_field, pathp->node,	\
656 		      tnode);						\
657 		} else {						\
658 		    /*      ||                                        */\
659 		    /*    pathp(r)                                    */\
660 		    /*  //        \                                   */\
661 		    /* (b)        (b)                                 */\
662 		    /*           /                                    */\
663 		    /*          (b)                                   */\
664 		    /*                                                */\
665 		    rbtn_rotate_left(a_type, a_field, pathp->node,	\
666 		      tnode);						\
667 		}							\
668 		/* Balance restored, but rotation modified subtree    */\
669 		/* root.                                              */\
670 		assert((uintptr_t)pathp > (uintptr_t)path);		\
671 		if (pathp[-1].cmp < 0) {				\
672 		    rbtn_left_set(a_type, a_field, pathp[-1].node,	\
673 		      tnode);						\
674 		} else {						\
675 		    rbtn_right_set(a_type, a_field, pathp[-1].node,	\
676 		      tnode);						\
677 		}							\
678 		return;							\
679 	    } else {							\
680 		a_type *right = rbtn_right_get(a_type, a_field,		\
681 		  pathp->node);						\
682 		a_type *rightleft = rbtn_left_get(a_type, a_field,	\
683 		  right);						\
684 		if (rightleft != NULL && rbtn_red_get(a_type, a_field,	\
685 		  rightleft)) {						\
686 		    /*      ||                                        */\
687 		    /*    pathp(b)                                    */\
688 		    /*  //        \                                   */\
689 		    /* (b)        (b)                                 */\
690 		    /*           /                                    */\
691 		    /*          (r)                                   */\
692 		    a_type *tnode;					\
693 		    rbtn_black_set(a_type, a_field, rightleft);		\
694 		    rbtn_rotate_right(a_type, a_field, right, tnode);	\
695 		    rbtn_right_set(a_type, a_field, pathp->node, tnode);\
696 		    rbtn_rotate_left(a_type, a_field, pathp->node,	\
697 		      tnode);						\
698 		    /* Balance restored, but rotation modified        */\
699 		    /* subtree root, which may actually be the tree   */\
700 		    /* root.                                          */\
701 		    if (pathp == path) {				\
702 			/* Set root. */					\
703 			rbtree->rbt_root = tnode;			\
704 		    } else {						\
705 			if (pathp[-1].cmp < 0) {			\
706 			    rbtn_left_set(a_type, a_field,		\
707 			      pathp[-1].node, tnode);			\
708 			} else {					\
709 			    rbtn_right_set(a_type, a_field,		\
710 			      pathp[-1].node, tnode);			\
711 			}						\
712 		    }							\
713 		    return;						\
714 		} else {						\
715 		    /*      ||                                        */\
716 		    /*    pathp(b)                                    */\
717 		    /*  //        \                                   */\
718 		    /* (b)        (b)                                 */\
719 		    /*           /                                    */\
720 		    /*          (b)                                   */\
721 		    a_type *tnode;					\
722 		    rbtn_red_set(a_type, a_field, pathp->node);		\
723 		    rbtn_rotate_left(a_type, a_field, pathp->node,	\
724 		      tnode);						\
725 		    pathp->node = tnode;				\
726 		}							\
727 	    }								\
728 	} else {							\
729 	    a_type *left;						\
730 	    rbtn_right_set(a_type, a_field, pathp->node,		\
731 	      pathp[1].node);						\
732 	    left = rbtn_left_get(a_type, a_field, pathp->node);		\
733 	    if (rbtn_red_get(a_type, a_field, left)) {			\
734 		a_type *tnode;						\
735 		a_type *leftright = rbtn_right_get(a_type, a_field,	\
736 		  left);						\
737 		a_type *leftrightleft = rbtn_left_get(a_type, a_field,	\
738 		  leftright);						\
739 		if (leftrightleft != NULL && rbtn_red_get(a_type,	\
740 		  a_field, leftrightleft)) {				\
741 		    /*      ||                                        */\
742 		    /*    pathp(b)                                    */\
743 		    /*   /        \\                                  */\
744 		    /* (r)        (b)                                 */\
745 		    /*   \                                            */\
746 		    /*   (b)                                          */\
747 		    /*   /                                            */\
748 		    /* (r)                                            */\
749 		    a_type *unode;					\
750 		    rbtn_black_set(a_type, a_field, leftrightleft);	\
751 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
752 		      unode);						\
753 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
754 		      tnode);						\
755 		    rbtn_right_set(a_type, a_field, unode, tnode);	\
756 		    rbtn_rotate_left(a_type, a_field, unode, tnode);	\
757 		} else {						\
758 		    /*      ||                                        */\
759 		    /*    pathp(b)                                    */\
760 		    /*   /        \\                                  */\
761 		    /* (r)        (b)                                 */\
762 		    /*   \                                            */\
763 		    /*   (b)                                          */\
764 		    /*   /                                            */\
765 		    /* (b)                                            */\
766 		    assert(leftright != NULL);				\
767 		    rbtn_red_set(a_type, a_field, leftright);		\
768 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
769 		      tnode);						\
770 		    rbtn_black_set(a_type, a_field, tnode);		\
771 		}							\
772 		/* Balance restored, but rotation modified subtree    */\
773 		/* root, which may actually be the tree root.         */\
774 		if (pathp == path) {					\
775 		    /* Set root. */					\
776 		    rbtree->rbt_root = tnode;				\
777 		} else {						\
778 		    if (pathp[-1].cmp < 0) {				\
779 			rbtn_left_set(a_type, a_field, pathp[-1].node,	\
780 			  tnode);					\
781 		    } else {						\
782 			rbtn_right_set(a_type, a_field, pathp[-1].node,	\
783 			  tnode);					\
784 		    }							\
785 		}							\
786 		return;							\
787 	    } else if (rbtn_red_get(a_type, a_field, pathp->node)) {	\
788 		a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
789 		if (leftleft != NULL && rbtn_red_get(a_type, a_field,	\
790 		  leftleft)) {						\
791 		    /*        ||                                      */\
792 		    /*      pathp(r)                                  */\
793 		    /*     /        \\                                */\
794 		    /*   (b)        (b)                               */\
795 		    /*   /                                            */\
796 		    /* (r)                                            */\
797 		    a_type *tnode;					\
798 		    rbtn_black_set(a_type, a_field, pathp->node);	\
799 		    rbtn_red_set(a_type, a_field, left);		\
800 		    rbtn_black_set(a_type, a_field, leftleft);		\
801 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
802 		      tnode);						\
803 		    /* Balance restored, but rotation modified        */\
804 		    /* subtree root.                                  */\
805 		    assert((uintptr_t)pathp > (uintptr_t)path);		\
806 		    if (pathp[-1].cmp < 0) {				\
807 			rbtn_left_set(a_type, a_field, pathp[-1].node,	\
808 			  tnode);					\
809 		    } else {						\
810 			rbtn_right_set(a_type, a_field, pathp[-1].node,	\
811 			  tnode);					\
812 		    }							\
813 		    return;						\
814 		} else {						\
815 		    /*        ||                                      */\
816 		    /*      pathp(r)                                  */\
817 		    /*     /        \\                                */\
818 		    /*   (b)        (b)                               */\
819 		    /*   /                                            */\
820 		    /* (b)                                            */\
821 		    rbtn_red_set(a_type, a_field, left);		\
822 		    rbtn_black_set(a_type, a_field, pathp->node);	\
823 		    /* Balance restored. */				\
824 		    return;						\
825 		}							\
826 	    } else {							\
827 		a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
828 		if (leftleft != NULL && rbtn_red_get(a_type, a_field,	\
829 		  leftleft)) {						\
830 		    /*               ||                               */\
831 		    /*             pathp(b)                           */\
832 		    /*            /        \\                         */\
833 		    /*          (b)        (b)                        */\
834 		    /*          /                                     */\
835 		    /*        (r)                                     */\
836 		    a_type *tnode;					\
837 		    rbtn_black_set(a_type, a_field, leftleft);		\
838 		    rbtn_rotate_right(a_type, a_field, pathp->node,	\
839 		      tnode);						\
840 		    /* Balance restored, but rotation modified        */\
841 		    /* subtree root, which may actually be the tree   */\
842 		    /* root.                                          */\
843 		    if (pathp == path) {				\
844 			/* Set root. */					\
845 			rbtree->rbt_root = tnode;			\
846 		    } else {						\
847 			if (pathp[-1].cmp < 0) {			\
848 			    rbtn_left_set(a_type, a_field,		\
849 			      pathp[-1].node, tnode);			\
850 			} else {					\
851 			    rbtn_right_set(a_type, a_field,		\
852 			      pathp[-1].node, tnode);			\
853 			}						\
854 		    }							\
855 		    return;						\
856 		} else {						\
857 		    /*               ||                               */\
858 		    /*             pathp(b)                           */\
859 		    /*            /        \\                         */\
860 		    /*          (b)        (b)                        */\
861 		    /*          /                                     */\
862 		    /*        (b)                                     */\
863 		    rbtn_red_set(a_type, a_field, left);		\
864 		}							\
865 	    }								\
866 	}								\
867     }									\
868     /* Set root. */							\
869     rbtree->rbt_root = path->node;					\
870     assert(!rbtn_red_get(a_type, a_field, rbtree->rbt_root));		\
871 }									\
872 a_attr a_type *								\
873 a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node,		\
874   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {		\
875     if (node == NULL) {							\
876 	return (NULL);							\
877     } else {								\
878 	a_type *ret;							\
879 	if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type,	\
880 	  a_field, node), cb, arg)) != NULL || (ret = cb(rbtree, node,	\
881 	  arg)) != NULL) {						\
882 	    return (ret);						\
883 	}								\
884 	return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,	\
885 	  a_field, node), cb, arg));					\
886     }									\
887 }									\
888 a_attr a_type *								\
889 a_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node,	\
890   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {		\
891     int cmp = a_cmp(start, node);					\
892     if (cmp < 0) {							\
893 	a_type *ret;							\
894 	if ((ret = a_prefix##iter_start(rbtree, start,			\
895 	  rbtn_left_get(a_type, a_field, node), cb, arg)) != NULL ||	\
896 	  (ret = cb(rbtree, node, arg)) != NULL) {			\
897 	    return (ret);						\
898 	}								\
899 	return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,	\
900 	  a_field, node), cb, arg));					\
901     } else if (cmp > 0) {						\
902 	return (a_prefix##iter_start(rbtree, start,			\
903 	  rbtn_right_get(a_type, a_field, node), cb, arg));		\
904     } else {								\
905 	a_type *ret;							\
906 	if ((ret = cb(rbtree, node, arg)) != NULL) {			\
907 	    return (ret);						\
908 	}								\
909 	return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type,	\
910 	  a_field, node), cb, arg));					\
911     }									\
912 }									\
913 a_attr a_type *								\
914 a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)(	\
915   a_rbt_type *, a_type *, void *), void *arg) {				\
916     a_type *ret;							\
917     if (start != NULL) {						\
918 	ret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root,	\
919 	  cb, arg);							\
920     } else {								\
921 	ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\
922     }									\
923     return (ret);							\
924 }									\
925 a_attr a_type *								\
926 a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node,	\
927   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {		\
928     if (node == NULL) {							\
929 	return (NULL);							\
930     } else {								\
931 	a_type *ret;							\
932 	if ((ret = a_prefix##reverse_iter_recurse(rbtree,		\
933 	  rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL ||	\
934 	  (ret = cb(rbtree, node, arg)) != NULL) {			\
935 	    return (ret);						\
936 	}								\
937 	return (a_prefix##reverse_iter_recurse(rbtree,			\
938 	  rbtn_left_get(a_type, a_field, node), cb, arg));		\
939     }									\
940 }									\
941 a_attr a_type *								\
942 a_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start,		\
943   a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *),		\
944   void *arg) {								\
945     int cmp = a_cmp(start, node);					\
946     if (cmp > 0) {							\
947 	a_type *ret;							\
948 	if ((ret = a_prefix##reverse_iter_start(rbtree, start,		\
949 	  rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL ||	\
950 	  (ret = cb(rbtree, node, arg)) != NULL) {			\
951 	    return (ret);						\
952 	}								\
953 	return (a_prefix##reverse_iter_recurse(rbtree,			\
954 	  rbtn_left_get(a_type, a_field, node), cb, arg));		\
955     } else if (cmp < 0) {						\
956 	return (a_prefix##reverse_iter_start(rbtree, start,		\
957 	  rbtn_left_get(a_type, a_field, node), cb, arg));		\
958     } else {								\
959 	a_type *ret;							\
960 	if ((ret = cb(rbtree, node, arg)) != NULL) {			\
961 	    return (ret);						\
962 	}								\
963 	return (a_prefix##reverse_iter_recurse(rbtree,			\
964 	  rbtn_left_get(a_type, a_field, node), cb, arg));		\
965     }									\
966 }									\
967 a_attr a_type *								\
968 a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start,		\
969   a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) {		\
970     a_type *ret;							\
971     if (start != NULL) {						\
972 	ret = a_prefix##reverse_iter_start(rbtree, start,		\
973 	  rbtree->rbt_root, cb, arg);					\
974     } else {								\
975 	ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root,	\
976 	  cb, arg);							\
977     }									\
978     return (ret);							\
979 }									\
980 a_attr void								\
981 a_prefix##destroy_recurse(a_rbt_type *rbtree, a_type *node, void (*cb)(	\
982   a_type *, void *), void *arg) {					\
983     if (node == NULL) {							\
984 	return;								\
985     }									\
986     a_prefix##destroy_recurse(rbtree, rbtn_left_get(a_type, a_field,	\
987       node), cb, arg);							\
988     rbtn_left_set(a_type, a_field, (node), NULL);			\
989     a_prefix##destroy_recurse(rbtree, rbtn_right_get(a_type, a_field,	\
990       node), cb, arg);							\
991     rbtn_right_set(a_type, a_field, (node), NULL);			\
992     if (cb) {								\
993 	cb(node, arg);							\
994     }									\
995 }									\
996 a_attr void								\
997 a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *),	\
998   void *arg) {								\
999     a_prefix##destroy_recurse(rbtree, rbtree->rbt_root, cb, arg);	\
1000     rbtree->rbt_root = NULL;						\
1001 }
1002 
1003 #endif /* RB_H_ */
1004