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