2 *******************************************************************************
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.
12 * #include <stdbool.h>
13 * #define NDEBUG // (Optional, see assert(3).)
15 * #define RB_COMPACT // (Optional, embed color bits in right-child pointers.)
19 *******************************************************************************
31 #define rb_node(a_type) \
34 a_type *rbn_right_red; \
37 #define rb_node(a_type) \
46 #define rb_tree(a_type) \
52 #define rbtn_left_get(a_type, a_field, a_node) \
53 ((a_node)->a_field.rbn_left)
54 #define rbtn_left_set(a_type, a_field, a_node, a_left) do { \
55 (a_node)->a_field.rbn_left = a_left; \
59 /* Right accessors. */
60 #define rbtn_right_get(a_type, a_field, a_node) \
61 ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red) \
63 #define rbtn_right_set(a_type, a_field, a_node, a_right) do { \
64 (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right) \
65 | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1))); \
68 /* Color accessors. */
69 #define rbtn_red_get(a_type, a_field, a_node) \
70 ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red) \
72 #define rbtn_color_set(a_type, a_field, a_node, a_red) do { \
73 (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t) \
74 (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)) \
75 | ((ssize_t)a_red)); \
77 #define rbtn_red_set(a_type, a_field, a_node) do { \
78 (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) \
79 (a_node)->a_field.rbn_right_red) | ((size_t)1)); \
81 #define rbtn_black_set(a_type, a_field, a_node) do { \
82 (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t) \
83 (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)); \
86 /* Node initializer. */
87 #define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
88 /* Bookkeeping bit cannot be used by node pointer. */ \
89 assert(((uintptr_t)(a_node) & 0x1) == 0); \
90 rbtn_left_set(a_type, a_field, (a_node), NULL); \
91 rbtn_right_set(a_type, a_field, (a_node), NULL); \
92 rbtn_red_set(a_type, a_field, (a_node)); \
95 /* Right accessors. */
96 #define rbtn_right_get(a_type, a_field, a_node) \
97 ((a_node)->a_field.rbn_right)
98 #define rbtn_right_set(a_type, a_field, a_node, a_right) do { \
99 (a_node)->a_field.rbn_right = a_right; \
102 /* Color accessors. */
103 #define rbtn_red_get(a_type, a_field, a_node) \
104 ((a_node)->a_field.rbn_red)
105 #define rbtn_color_set(a_type, a_field, a_node, a_red) do { \
106 (a_node)->a_field.rbn_red = (a_red); \
108 #define rbtn_red_set(a_type, a_field, a_node) do { \
109 (a_node)->a_field.rbn_red = true; \
111 #define rbtn_black_set(a_type, a_field, a_node) do { \
112 (a_node)->a_field.rbn_red = false; \
115 /* Node initializer. */
116 #define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
117 rbtn_left_set(a_type, a_field, (a_node), NULL); \
118 rbtn_right_set(a_type, a_field, (a_node), NULL); \
119 rbtn_red_set(a_type, a_field, (a_node)); \
123 /* Tree initializer. */
124 #define rb_new(a_type, a_field, a_rbt) do { \
125 (a_rbt)->rbt_root = NULL; \
128 /* Internal utility macros. */
129 #define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do { \
130 (r_node) = (a_root); \
131 if ((r_node) != NULL) { \
133 rbtn_left_get(a_type, a_field, (r_node)) != NULL; \
134 (r_node) = rbtn_left_get(a_type, a_field, (r_node))) { \
139 #define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do { \
140 (r_node) = (a_root); \
141 if ((r_node) != NULL) { \
142 for (; rbtn_right_get(a_type, a_field, (r_node)) != NULL; \
143 (r_node) = rbtn_right_get(a_type, a_field, (r_node))) { \
148 #define rbtn_rotate_left(a_type, a_field, a_node, r_node) do { \
149 (r_node) = rbtn_right_get(a_type, a_field, (a_node)); \
150 rbtn_right_set(a_type, a_field, (a_node), \
151 rbtn_left_get(a_type, a_field, (r_node))); \
152 rbtn_left_set(a_type, a_field, (r_node), (a_node)); \
155 #define rbtn_rotate_right(a_type, a_field, a_node, r_node) do { \
156 (r_node) = rbtn_left_get(a_type, a_field, (a_node)); \
157 rbtn_left_set(a_type, a_field, (a_node), \
158 rbtn_right_get(a_type, a_field, (r_node))); \
159 rbtn_right_set(a_type, a_field, (r_node), (a_node)); \
163 * The rb_proto() macro generates function prototypes that correspond to the
164 * functions generated by an equivalently parameterized call to rb_gen().
167 #define rb_proto(a_attr, a_prefix, a_rbt_type, a_type) \
169 a_prefix##new(a_rbt_type *rbtree); \
171 a_prefix##empty(a_rbt_type *rbtree); \
173 a_prefix##first(a_rbt_type *rbtree); \
175 a_prefix##last(a_rbt_type *rbtree); \
177 a_prefix##next(a_rbt_type *rbtree, a_type *node); \
179 a_prefix##prev(a_rbt_type *rbtree, a_type *node); \
181 a_prefix##search(a_rbt_type *rbtree, const a_type *key); \
183 a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key); \
185 a_prefix##psearch(a_rbt_type *rbtree, const a_type *key); \
187 a_prefix##insert(a_rbt_type *rbtree, a_type *node); \
189 a_prefix##remove(a_rbt_type *rbtree, a_type *node); \
191 a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \
192 a_rbt_type *, a_type *, void *), void *arg); \
194 a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \
195 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg); \
197 a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \
201 * The rb_gen() macro generates a type-specific red-black tree implementation,
202 * based on the above cpp macros.
206 * a_attr : Function attribute for generated functions (ex: static).
207 * a_prefix : Prefix for generated functions (ex: ex_).
208 * a_rb_type : Type for red-black tree data structure (ex: ex_t).
209 * a_type : Type for red-black tree node data structure (ex: ex_node_t).
210 * a_field : Name of red-black tree node linkage (ex: ex_link).
211 * a_cmp : Node comparison function name, with the following prototype:
212 * int (a_cmp *)(a_type *a_node, a_type *a_other);
215 * Interpretation of comparison function return values:
216 * -1 : a_node < a_other
217 * 0 : a_node == a_other
218 * 1 : a_node > a_other
219 * In all cases, the a_node or a_key macro argument is the first
220 * argument to the comparison function, which makes it possible
221 * to write comparison functions that treat the first argument
224 * Assuming the following setup:
226 * typedef struct ex_node_s ex_node_t;
228 * rb_node(ex_node_t) ex_link;
230 * typedef rb_tree(ex_node_t) ex_t;
231 * rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp)
233 * The following API is generated:
236 * ex_new(ex_t *tree);
237 * Description: Initialize a red-black tree structure.
239 * tree: Pointer to an uninitialized red-black tree object.
242 * ex_empty(ex_t *tree);
243 * Description: Determine whether tree is empty.
245 * tree: Pointer to an initialized red-black tree object.
246 * Ret: True if tree is empty, false otherwise.
249 * ex_first(ex_t *tree);
251 * ex_last(ex_t *tree);
252 * Description: Get the first/last node in tree.
254 * tree: Pointer to an initialized red-black tree object.
255 * Ret: First/last node in tree, or NULL if tree is empty.
258 * ex_next(ex_t *tree, ex_node_t *node);
260 * ex_prev(ex_t *tree, ex_node_t *node);
261 * Description: Get node's successor/predecessor.
263 * tree: Pointer to an initialized red-black tree object.
264 * node: A node in tree.
265 * Ret: node's successor/predecessor in tree, or NULL if node is
269 * ex_search(ex_t *tree, const ex_node_t *key);
270 * Description: Search for node that matches key.
272 * tree: Pointer to an initialized red-black tree object.
274 * Ret: Node in tree that matches key, or NULL if no match.
277 * ex_nsearch(ex_t *tree, const ex_node_t *key);
279 * ex_psearch(ex_t *tree, const ex_node_t *key);
280 * Description: Search for node that matches key. If no match is found,
281 * return what would be key's successor/predecessor, were
284 * tree: Pointer to an initialized red-black tree object.
286 * Ret: Node in tree that matches key, or if no match, hypothetical node's
287 * successor/predecessor (NULL if no successor/predecessor).
290 * ex_insert(ex_t *tree, ex_node_t *node);
291 * Description: Insert node into tree.
293 * tree: Pointer to an initialized red-black tree object.
294 * node: Node to be inserted into tree.
297 * ex_remove(ex_t *tree, ex_node_t *node);
298 * Description: Remove node from tree.
300 * tree: Pointer to an initialized red-black tree object.
301 * node: Node in tree to be removed.
304 * ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,
305 * ex_node_t *, void *), void *arg);
307 * ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,
308 * ex_node_t *, void *), void *arg);
309 * Description: Iterate forward/backward over tree, starting at node. If
310 * tree is modified, iteration must be immediately
311 * terminated by the callback function that causes the
314 * tree : Pointer to an initialized red-black tree object.
315 * start: Node at which to start iteration, or NULL to start at
317 * cb : Callback function, which is called for each node during
318 * iteration. Under normal circumstances the callback function
319 * should return NULL, which causes iteration to continue. If a
320 * callback function returns non-NULL, iteration is immediately
321 * terminated and the non-NULL return value is returned by the
322 * iterator. This is useful for re-starting iteration after
324 * arg : Opaque pointer passed to cb().
325 * Ret: NULL if iteration completed, or the non-NULL callback return value
326 * that caused termination of the iteration.
329 * ex_destroy(ex_t *tree, void (*cb)(ex_node_t *, void *), void *arg);
330 * Description: Iterate over the tree with post-order traversal, remove
331 * each node, and run the callback if non-null. This is
332 * used for destroying a tree without paying the cost to
333 * rebalance it. The tree must not be otherwise altered
336 * tree: Pointer to an initialized red-black tree object.
337 * cb : Callback function, which, if non-null, is called for each node
338 * during iteration. There is no way to stop iteration once it
340 * arg : Opaque pointer passed to cb().
342 #define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \
344 a_prefix##new(a_rbt_type *rbtree) { \
345 rb_new(a_type, a_field, rbtree); \
348 a_prefix##empty(a_rbt_type *rbtree) { \
349 return (rbtree->rbt_root == NULL); \
352 a_prefix##first(a_rbt_type *rbtree) { \
354 rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
358 a_prefix##last(a_rbt_type *rbtree) { \
360 rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
364 a_prefix##next(a_rbt_type *rbtree, a_type *node) { \
366 if (rbtn_right_get(a_type, a_field, node) != NULL) { \
367 rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type, \
368 a_field, node), ret); \
370 a_type *tnode = rbtree->rbt_root; \
371 assert(tnode != NULL); \
374 int cmp = (a_cmp)(node, tnode); \
377 tnode = rbtn_left_get(a_type, a_field, tnode); \
378 } else if (cmp > 0) { \
379 tnode = rbtn_right_get(a_type, a_field, tnode); \
383 assert(tnode != NULL); \
389 a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \
391 if (rbtn_left_get(a_type, a_field, node) != NULL) { \
392 rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type, \
393 a_field, node), ret); \
395 a_type *tnode = rbtree->rbt_root; \
396 assert(tnode != NULL); \
399 int cmp = (a_cmp)(node, tnode); \
401 tnode = rbtn_left_get(a_type, a_field, tnode); \
402 } else if (cmp > 0) { \
404 tnode = rbtn_right_get(a_type, a_field, tnode); \
408 assert(tnode != NULL); \
414 a_prefix##search(a_rbt_type *rbtree, const a_type *key) { \
417 ret = rbtree->rbt_root; \
419 && (cmp = (a_cmp)(key, ret)) != 0) { \
421 ret = rbtn_left_get(a_type, a_field, ret); \
423 ret = rbtn_right_get(a_type, a_field, ret); \
429 a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) { \
431 a_type *tnode = rbtree->rbt_root; \
433 while (tnode != NULL) { \
434 int cmp = (a_cmp)(key, tnode); \
437 tnode = rbtn_left_get(a_type, a_field, tnode); \
438 } else if (cmp > 0) { \
439 tnode = rbtn_right_get(a_type, a_field, tnode); \
448 a_prefix##psearch(a_rbt_type *rbtree, const a_type *key) { \
450 a_type *tnode = rbtree->rbt_root; \
452 while (tnode != NULL) { \
453 int cmp = (a_cmp)(key, tnode); \
455 tnode = rbtn_left_get(a_type, a_field, tnode); \
456 } else if (cmp > 0) { \
458 tnode = rbtn_right_get(a_type, a_field, tnode); \
467 a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \
471 } path[sizeof(void *) << 4], *pathp; \
472 rbt_node_new(a_type, a_field, rbtree, node); \
474 path->node = rbtree->rbt_root; \
475 for (pathp = path; pathp->node != NULL; pathp++) { \
476 int cmp = pathp->cmp = a_cmp(node, pathp->node); \
479 pathp[1].node = rbtn_left_get(a_type, a_field, \
482 pathp[1].node = rbtn_right_get(a_type, a_field, \
486 pathp->node = node; \
488 for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \
489 a_type *cnode = pathp->node; \
490 if (pathp->cmp < 0) { \
491 a_type *left = pathp[1].node; \
492 rbtn_left_set(a_type, a_field, cnode, left); \
493 if (rbtn_red_get(a_type, a_field, left)) { \
494 a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
495 if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
497 /* Fix up 4-node. */ \
499 rbtn_black_set(a_type, a_field, leftleft); \
500 rbtn_rotate_right(a_type, a_field, cnode, tnode); \
507 a_type *right = pathp[1].node; \
508 rbtn_right_set(a_type, a_field, cnode, right); \
509 if (rbtn_red_get(a_type, a_field, right)) { \
510 a_type *left = rbtn_left_get(a_type, a_field, cnode); \
511 if (left != NULL && rbtn_red_get(a_type, a_field, \
513 /* Split 4-node. */ \
514 rbtn_black_set(a_type, a_field, left); \
515 rbtn_black_set(a_type, a_field, right); \
516 rbtn_red_set(a_type, a_field, cnode); \
520 bool tred = rbtn_red_get(a_type, a_field, cnode); \
521 rbtn_rotate_left(a_type, a_field, cnode, tnode); \
522 rbtn_color_set(a_type, a_field, tnode, tred); \
523 rbtn_red_set(a_type, a_field, cnode); \
530 pathp->node = cnode; \
532 /* Set root, and make it black. */ \
533 rbtree->rbt_root = path->node; \
534 rbtn_black_set(a_type, a_field, rbtree->rbt_root); \
537 a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
541 } *pathp, *nodep, path[sizeof(void *) << 4]; \
543 nodep = NULL; /* Silence compiler warning. */ \
544 path->node = rbtree->rbt_root; \
545 for (pathp = path; pathp->node != NULL; pathp++) { \
546 int cmp = pathp->cmp = a_cmp(node, pathp->node); \
548 pathp[1].node = rbtn_left_get(a_type, a_field, \
551 pathp[1].node = rbtn_right_get(a_type, a_field, \
554 /* Find node's successor, in preparation for swap. */ \
557 for (pathp++; pathp->node != NULL; pathp++) { \
559 pathp[1].node = rbtn_left_get(a_type, a_field, \
566 assert(nodep->node == node); \
568 if (pathp->node != node) { \
569 /* Swap node with its successor. */ \
570 bool tred = rbtn_red_get(a_type, a_field, pathp->node); \
571 rbtn_color_set(a_type, a_field, pathp->node, \
572 rbtn_red_get(a_type, a_field, node)); \
573 rbtn_left_set(a_type, a_field, pathp->node, \
574 rbtn_left_get(a_type, a_field, node)); \
575 /* If node's successor is its right child, the following code */\
576 /* will do the wrong thing for the right child pointer. */\
577 /* However, it doesn't matter, because the pointer will be */\
578 /* properly set when the successor is pruned. */\
579 rbtn_right_set(a_type, a_field, pathp->node, \
580 rbtn_right_get(a_type, a_field, node)); \
581 rbtn_color_set(a_type, a_field, node, tred); \
582 /* The pruned leaf node's child pointers are never accessed */\
583 /* again, so don't bother setting them to nil. */\
584 nodep->node = pathp->node; \
585 pathp->node = node; \
586 if (nodep == path) { \
587 rbtree->rbt_root = nodep->node; \
589 if (nodep[-1].cmp < 0) { \
590 rbtn_left_set(a_type, a_field, nodep[-1].node, \
593 rbtn_right_set(a_type, a_field, nodep[-1].node, \
598 a_type *left = rbtn_left_get(a_type, a_field, node); \
599 if (left != NULL) { \
600 /* node has no successor, but it has a left child. */\
601 /* Splice node out, without losing the left child. */\
602 assert(!rbtn_red_get(a_type, a_field, node)); \
603 assert(rbtn_red_get(a_type, a_field, left)); \
604 rbtn_black_set(a_type, a_field, left); \
605 if (pathp == path) { \
606 rbtree->rbt_root = left; \
608 if (pathp[-1].cmp < 0) { \
609 rbtn_left_set(a_type, a_field, pathp[-1].node, \
612 rbtn_right_set(a_type, a_field, pathp[-1].node, \
617 } else if (pathp == path) { \
618 /* The tree only contained one node. */ \
619 rbtree->rbt_root = NULL; \
623 if (rbtn_red_get(a_type, a_field, pathp->node)) { \
624 /* Prune red node, which requires no fixup. */ \
625 assert(pathp[-1].cmp < 0); \
626 rbtn_left_set(a_type, a_field, pathp[-1].node, NULL); \
629 /* The node to be pruned is black, so unwind until balance is */\
631 pathp->node = NULL; \
632 for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \
633 assert(pathp->cmp != 0); \
634 if (pathp->cmp < 0) { \
635 rbtn_left_set(a_type, a_field, pathp->node, \
637 if (rbtn_red_get(a_type, a_field, pathp->node)) { \
638 a_type *right = rbtn_right_get(a_type, a_field, \
640 a_type *rightleft = rbtn_left_get(a_type, a_field, \
643 if (rightleft != NULL && rbtn_red_get(a_type, a_field, \
645 /* In the following diagrams, ||, //, and \\ */\
646 /* indicate the path to the removed node. */\
655 rbtn_black_set(a_type, a_field, pathp->node); \
656 rbtn_rotate_right(a_type, a_field, right, tnode); \
657 rbtn_right_set(a_type, a_field, pathp->node, tnode);\
658 rbtn_rotate_left(a_type, a_field, pathp->node, \
668 rbtn_rotate_left(a_type, a_field, pathp->node, \
671 /* Balance restored, but rotation modified subtree */\
673 assert((uintptr_t)pathp > (uintptr_t)path); \
674 if (pathp[-1].cmp < 0) { \
675 rbtn_left_set(a_type, a_field, pathp[-1].node, \
678 rbtn_right_set(a_type, a_field, pathp[-1].node, \
683 a_type *right = rbtn_right_get(a_type, a_field, \
685 a_type *rightleft = rbtn_left_get(a_type, a_field, \
687 if (rightleft != NULL && rbtn_red_get(a_type, a_field, \
696 rbtn_black_set(a_type, a_field, rightleft); \
697 rbtn_rotate_right(a_type, a_field, right, tnode); \
698 rbtn_right_set(a_type, a_field, pathp->node, tnode);\
699 rbtn_rotate_left(a_type, a_field, pathp->node, \
701 /* Balance restored, but rotation modified */\
702 /* subtree root, which may actually be the tree */\
704 if (pathp == path) { \
706 rbtree->rbt_root = tnode; \
708 if (pathp[-1].cmp < 0) { \
709 rbtn_left_set(a_type, a_field, \
710 pathp[-1].node, tnode); \
712 rbtn_right_set(a_type, a_field, \
713 pathp[-1].node, tnode); \
725 rbtn_red_set(a_type, a_field, pathp->node); \
726 rbtn_rotate_left(a_type, a_field, pathp->node, \
728 pathp->node = tnode; \
733 rbtn_right_set(a_type, a_field, pathp->node, \
735 left = rbtn_left_get(a_type, a_field, pathp->node); \
736 if (rbtn_red_get(a_type, a_field, left)) { \
738 a_type *leftright = rbtn_right_get(a_type, a_field, \
740 a_type *leftrightleft = rbtn_left_get(a_type, a_field, \
742 if (leftrightleft != NULL && rbtn_red_get(a_type, \
743 a_field, leftrightleft)) { \
753 rbtn_black_set(a_type, a_field, leftrightleft); \
754 rbtn_rotate_right(a_type, a_field, pathp->node, \
756 rbtn_rotate_right(a_type, a_field, pathp->node, \
758 rbtn_right_set(a_type, a_field, unode, tnode); \
759 rbtn_rotate_left(a_type, a_field, unode, tnode); \
769 assert(leftright != NULL); \
770 rbtn_red_set(a_type, a_field, leftright); \
771 rbtn_rotate_right(a_type, a_field, pathp->node, \
773 rbtn_black_set(a_type, a_field, tnode); \
775 /* Balance restored, but rotation modified subtree */\
776 /* root, which may actually be the tree root. */\
777 if (pathp == path) { \
779 rbtree->rbt_root = tnode; \
781 if (pathp[-1].cmp < 0) { \
782 rbtn_left_set(a_type, a_field, pathp[-1].node, \
785 rbtn_right_set(a_type, a_field, pathp[-1].node, \
790 } else if (rbtn_red_get(a_type, a_field, pathp->node)) { \
791 a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
792 if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
801 rbtn_black_set(a_type, a_field, pathp->node); \
802 rbtn_red_set(a_type, a_field, left); \
803 rbtn_black_set(a_type, a_field, leftleft); \
804 rbtn_rotate_right(a_type, a_field, pathp->node, \
806 /* Balance restored, but rotation modified */\
808 assert((uintptr_t)pathp > (uintptr_t)path); \
809 if (pathp[-1].cmp < 0) { \
810 rbtn_left_set(a_type, a_field, pathp[-1].node, \
813 rbtn_right_set(a_type, a_field, pathp[-1].node, \
824 rbtn_red_set(a_type, a_field, left); \
825 rbtn_black_set(a_type, a_field, pathp->node); \
826 /* Balance restored. */ \
830 a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
831 if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
840 rbtn_black_set(a_type, a_field, leftleft); \
841 rbtn_rotate_right(a_type, a_field, pathp->node, \
843 /* Balance restored, but rotation modified */\
844 /* subtree root, which may actually be the tree */\
846 if (pathp == path) { \
848 rbtree->rbt_root = tnode; \
850 if (pathp[-1].cmp < 0) { \
851 rbtn_left_set(a_type, a_field, \
852 pathp[-1].node, tnode); \
854 rbtn_right_set(a_type, a_field, \
855 pathp[-1].node, tnode); \
866 rbtn_red_set(a_type, a_field, left); \
872 rbtree->rbt_root = path->node; \
873 assert(!rbtn_red_get(a_type, a_field, rbtree->rbt_root)); \
876 a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node, \
877 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
878 if (node == NULL) { \
882 if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type, \
883 a_field, node), cb, arg)) != NULL || (ret = cb(rbtree, node, \
887 return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
888 a_field, node), cb, arg); \
892 a_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node, \
893 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
894 int cmp = a_cmp(start, node); \
897 if ((ret = a_prefix##iter_start(rbtree, start, \
898 rbtn_left_get(a_type, a_field, node), cb, arg)) != NULL || \
899 (ret = cb(rbtree, node, arg)) != NULL) { \
902 return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
903 a_field, node), cb, arg); \
904 } else if (cmp > 0) { \
905 return a_prefix##iter_start(rbtree, start, \
906 rbtn_right_get(a_type, a_field, node), cb, arg); \
909 if ((ret = cb(rbtree, node, arg)) != NULL) { \
912 return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
913 a_field, node), cb, arg); \
917 a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \
918 a_rbt_type *, a_type *, void *), void *arg) { \
920 if (start != NULL) { \
921 ret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root, \
924 ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\
929 a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node, \
930 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
931 if (node == NULL) { \
935 if ((ret = a_prefix##reverse_iter_recurse(rbtree, \
936 rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL || \
937 (ret = cb(rbtree, node, arg)) != NULL) { \
940 return a_prefix##reverse_iter_recurse(rbtree, \
941 rbtn_left_get(a_type, a_field, node), cb, arg); \
945 a_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start, \
946 a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *), \
948 int cmp = a_cmp(start, node); \
951 if ((ret = a_prefix##reverse_iter_start(rbtree, start, \
952 rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL || \
953 (ret = cb(rbtree, node, arg)) != NULL) { \
956 return a_prefix##reverse_iter_recurse(rbtree, \
957 rbtn_left_get(a_type, a_field, node), cb, arg); \
958 } else if (cmp < 0) { \
959 return a_prefix##reverse_iter_start(rbtree, start, \
960 rbtn_left_get(a_type, a_field, node), cb, arg); \
963 if ((ret = cb(rbtree, node, arg)) != NULL) { \
966 return a_prefix##reverse_iter_recurse(rbtree, \
967 rbtn_left_get(a_type, a_field, node), cb, arg); \
971 a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \
972 a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
974 if (start != NULL) { \
975 ret = a_prefix##reverse_iter_start(rbtree, start, \
976 rbtree->rbt_root, cb, arg); \
978 ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root, \
984 a_prefix##destroy_recurse(a_rbt_type *rbtree, a_type *node, void (*cb)( \
985 a_type *, void *), void *arg) { \
986 if (node == NULL) { \
989 a_prefix##destroy_recurse(rbtree, rbtn_left_get(a_type, a_field, \
991 rbtn_left_set(a_type, a_field, (node), NULL); \
992 a_prefix##destroy_recurse(rbtree, rbtn_right_get(a_type, a_field, \
994 rbtn_right_set(a_type, a_field, (node), NULL); \
1000 a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \
1002 a_prefix##destroy_recurse(rbtree, rbtree->rbt_root, cb, arg); \
1003 rbtree->rbt_root = NULL; \