ipf_rb.h revision 1.2.4.4 1 1.2.4.4 yamt /* $NetBSD: ipf_rb.h,v 1.2.4.4 2013/01/23 00:06:18 yamt Exp $ */
2 1.2.4.2 yamt
3 1.2.4.2 yamt /*
4 1.2.4.3 yamt * Copyright (C) 2012 by Darren Reed.
5 1.2.4.2 yamt *
6 1.2.4.2 yamt * See the IPFILTER.LICENCE file for details on licencing.
7 1.2.4.2 yamt *
8 1.2.4.2 yamt */
9 1.2.4.4 yamt
10 1.2.4.4 yamt /*
11 1.2.4.4 yamt * If the OS has a red-black tree implementation, use it.
12 1.2.4.4 yamt */
13 1.2.4.4 yamt #ifdef HAVE_RBTREE
14 1.2.4.4 yamt
15 1.2.4.4 yamt #include <sys/rbtree.h>
16 1.2.4.4 yamt
17 1.2.4.4 yamt # define RBI_LINK(_n, _t)
18 1.2.4.4 yamt # define RBI_FIELD(_n) rb_node_t
19 1.2.4.4 yamt # define RBI_HEAD(_n, _t) rb_tree_t
20 1.2.4.4 yamt
21 1.2.4.4 yamt /* Define adapter code between the ipf-specific and the system rb impls. */
22 1.2.4.4 yamt # define RBI_CODE(_n, _t, _f, _cmp) \
23 1.2.4.4 yamt signed int _n##_compare_nodes(void *ctx, const void *n1, const void *n2);\
24 1.2.4.4 yamt signed int _n##_compare_key(void *ctx, const void *n1, const void *key);\
25 1.2.4.4 yamt typedef void (*_n##_rb_walker_t)(_t *, void *); \
26 1.2.4.4 yamt void _n##_rb_walktree(rb_tree_t *, _n##_rb_walker_t, void *); \
27 1.2.4.4 yamt \
28 1.2.4.4 yamt static const rb_tree_ops_t _n##_tree_ops = { \
29 1.2.4.4 yamt .rbto_compare_nodes = _n##_compare_nodes, \
30 1.2.4.4 yamt .rbto_compare_key = _n##_compare_key, \
31 1.2.4.4 yamt .rbto_node_offset = offsetof(_t, _f), \
32 1.2.4.4 yamt .rbto_context = NULL \
33 1.2.4.4 yamt }; \
34 1.2.4.4 yamt \
35 1.2.4.4 yamt int \
36 1.2.4.4 yamt _n##_compare_nodes(void *ctx, const void *n1, const void *n2) { \
37 1.2.4.4 yamt return _cmp(n1, n2); \
38 1.2.4.4 yamt } \
39 1.2.4.4 yamt \
40 1.2.4.4 yamt int \
41 1.2.4.4 yamt _n##_compare_key(void *ctx, const void *n1, const void *key) { \
42 1.2.4.4 yamt return _cmp(n1, key); \
43 1.2.4.4 yamt } \
44 1.2.4.4 yamt \
45 1.2.4.4 yamt void \
46 1.2.4.4 yamt _n##_rb_walktree(rb_tree_t *head, _n##_rb_walker_t func, void *arg) \
47 1.2.4.4 yamt { \
48 1.2.4.4 yamt _t *rb; \
49 1.2.4.4 yamt /* Take advantage of the fact that the ipf code only uses this \
50 1.2.4.4 yamt method to clear the tree, in order to do it more safely. */ \
51 1.2.4.4 yamt while ((rb = rb_tree_iterate(head, NULL, RB_DIR_RIGHT)) != NULL) {\
52 1.2.4.4 yamt rb_tree_remove_node(head, rb); \
53 1.2.4.4 yamt func(rb, arg); \
54 1.2.4.4 yamt } \
55 1.2.4.4 yamt }
56 1.2.4.4 yamt
57 1.2.4.4 yamt # define RBI_DELETE(_n, _h, _v) rb_tree_remove_node(_h, _v)
58 1.2.4.4 yamt # define RBI_INIT(_n, _h) rb_tree_init(_h, &_n##_tree_ops)
59 1.2.4.4 yamt # define RBI_INSERT(_n, _h, _v) rb_tree_insert_node(_h, _v)
60 1.2.4.4 yamt # define RBI_ISEMPTY(_h) (rb_tree_iterate(_h, NULL, RB_DIR_RIGHT) == NULL)
61 1.2.4.4 yamt # define RBI_SEARCH(_n, _h, _k) rb_tree_find_node(_h, _k)
62 1.2.4.4 yamt # define RBI_WALK(_n, _h, _w, _a) _n##_rb_walktree(_h, _w, _a)
63 1.2.4.4 yamt
64 1.2.4.4 yamt #else
65 1.2.4.4 yamt
66 1.2.4.2 yamt typedef enum rbcolour_e {
67 1.2.4.2 yamt C_BLACK = 0,
68 1.2.4.2 yamt C_RED = 1
69 1.2.4.2 yamt } rbcolour_t;
70 1.2.4.2 yamt
71 1.2.4.4 yamt #define RBI_LINK(_n, _t) \
72 1.2.4.2 yamt struct _n##_rb_link { \
73 1.2.4.2 yamt struct _t *left; \
74 1.2.4.2 yamt struct _t *right; \
75 1.2.4.2 yamt struct _t *parent; \
76 1.2.4.2 yamt rbcolour_t colour; \
77 1.2.4.2 yamt }
78 1.2.4.2 yamt
79 1.2.4.2 yamt #define RBI_HEAD(_n, _t) \
80 1.2.4.2 yamt struct _n##_rb_head { \
81 1.2.4.2 yamt struct _t top; \
82 1.2.4.2 yamt int count; \
83 1.2.4.2 yamt int (* compare)(struct _t *, struct _t *); \
84 1.2.4.2 yamt }
85 1.2.4.2 yamt
86 1.2.4.4 yamt #define RBI_FIELD(_n) struct _n##_rb_link
87 1.2.4.4 yamt
88 1.2.4.2 yamt #define RBI_CODE(_n, _t, _f, _cmp) \
89 1.2.4.2 yamt \
90 1.2.4.4 yamt _t RBI_ZERO(_n); \
91 1.2.4.4 yamt \
92 1.2.4.2 yamt typedef void (*_n##_rb_walker_t)(_t *, void *); \
93 1.2.4.2 yamt \
94 1.2.4.2 yamt _t * _n##_rb_delete(struct _n##_rb_head *, _t *); \
95 1.2.4.2 yamt void _n##_rb_init(struct _n##_rb_head *); \
96 1.2.4.2 yamt void _n##_rb_insert(struct _n##_rb_head *, _t *); \
97 1.2.4.2 yamt _t * _n##_rb_search(struct _n##_rb_head *, void *); \
98 1.2.4.2 yamt void _n##_rb_walktree(struct _n##_rb_head *, _n##_rb_walker_t, void *);\
99 1.2.4.2 yamt \
100 1.2.4.2 yamt static void \
101 1.2.4.2 yamt rotate_left(struct _n##_rb_head *head, _t *node) \
102 1.2.4.2 yamt { \
103 1.2.4.2 yamt _t *parent, *tmp1, *tmp2; \
104 1.2.4.2 yamt \
105 1.2.4.2 yamt parent = node->_f.parent; \
106 1.2.4.2 yamt tmp1 = node->_f.right; \
107 1.2.4.2 yamt tmp2 = tmp1->_f.left; \
108 1.2.4.2 yamt node->_f.right = tmp2; \
109 1.2.4.2 yamt if (tmp2 != & _n##_rb_zero) \
110 1.2.4.2 yamt tmp2->_f.parent = node; \
111 1.2.4.2 yamt if (parent == & _n##_rb_zero) \
112 1.2.4.2 yamt head->top._f.right = tmp1; \
113 1.2.4.2 yamt else if (parent->_f.right == node) \
114 1.2.4.2 yamt parent->_f.right = tmp1; \
115 1.2.4.2 yamt else \
116 1.2.4.2 yamt parent->_f.left = tmp1; \
117 1.2.4.2 yamt tmp1->_f.left = node; \
118 1.2.4.2 yamt tmp1->_f.parent = parent; \
119 1.2.4.2 yamt node->_f.parent = tmp1; \
120 1.2.4.2 yamt } \
121 1.2.4.2 yamt \
122 1.2.4.2 yamt static void \
123 1.2.4.2 yamt rotate_right(struct _n##_rb_head *head, _t *node) \
124 1.2.4.2 yamt { \
125 1.2.4.2 yamt _t *parent, *tmp1, *tmp2; \
126 1.2.4.2 yamt \
127 1.2.4.2 yamt parent = node->_f.parent; \
128 1.2.4.2 yamt tmp1 = node->_f.left; \
129 1.2.4.2 yamt tmp2 = tmp1->_f.right; \
130 1.2.4.2 yamt node->_f.left = tmp2; \
131 1.2.4.2 yamt if (tmp2 != &_n##_rb_zero) \
132 1.2.4.2 yamt tmp2->_f.parent = node; \
133 1.2.4.2 yamt if (parent == &_n##_rb_zero) \
134 1.2.4.2 yamt head->top._f.right = tmp1; \
135 1.2.4.2 yamt else if (parent->_f.right == node) \
136 1.2.4.2 yamt parent->_f.right = tmp1; \
137 1.2.4.2 yamt else \
138 1.2.4.2 yamt parent->_f.left = tmp1; \
139 1.2.4.2 yamt tmp1->_f.right = node; \
140 1.2.4.2 yamt tmp1->_f.parent = parent; \
141 1.2.4.2 yamt node->_f.parent = tmp1; \
142 1.2.4.2 yamt } \
143 1.2.4.2 yamt \
144 1.2.4.2 yamt void \
145 1.2.4.2 yamt _n##_rb_insert(struct _n##_rb_head *head, _t *node) \
146 1.2.4.2 yamt { \
147 1.2.4.2 yamt _t *n, *parent, **p, *tmp1, *gparent; \
148 1.2.4.2 yamt \
149 1.2.4.2 yamt parent = &head->top; \
150 1.2.4.2 yamt node->_f.left = &_n##_rb_zero; \
151 1.2.4.2 yamt node->_f.right = &_n##_rb_zero; \
152 1.2.4.2 yamt p = &head->top._f.right; \
153 1.2.4.2 yamt while ((n = *p) != &_n##_rb_zero) { \
154 1.2.4.2 yamt if (_cmp(node, n) < 0) \
155 1.2.4.2 yamt p = &n->_f.left; \
156 1.2.4.2 yamt else \
157 1.2.4.2 yamt p = &n->_f.right; \
158 1.2.4.2 yamt parent = n; \
159 1.2.4.2 yamt } \
160 1.2.4.2 yamt *p = node; \
161 1.2.4.2 yamt node->_f.colour = C_RED; \
162 1.2.4.2 yamt node->_f.parent = parent; \
163 1.2.4.2 yamt \
164 1.2.4.2 yamt while ((node != &_n##_rb_zero) && (parent->_f.colour == C_RED)){\
165 1.2.4.2 yamt gparent = parent->_f.parent; \
166 1.2.4.2 yamt if (parent == gparent->_f.left) { \
167 1.2.4.2 yamt tmp1 = gparent->_f.right; \
168 1.2.4.2 yamt if (tmp1->_f.colour == C_RED) { \
169 1.2.4.2 yamt parent->_f.colour = C_BLACK; \
170 1.2.4.2 yamt tmp1->_f.colour = C_BLACK; \
171 1.2.4.2 yamt gparent->_f.colour = C_RED; \
172 1.2.4.2 yamt node = gparent; \
173 1.2.4.2 yamt } else { \
174 1.2.4.2 yamt if (node == parent->_f.right) { \
175 1.2.4.2 yamt node = parent; \
176 1.2.4.2 yamt rotate_left(head, node); \
177 1.2.4.2 yamt parent = node->_f.parent; \
178 1.2.4.2 yamt } \
179 1.2.4.2 yamt parent->_f.colour = C_BLACK; \
180 1.2.4.2 yamt gparent->_f.colour = C_RED; \
181 1.2.4.2 yamt rotate_right(head, gparent); \
182 1.2.4.2 yamt } \
183 1.2.4.2 yamt } else { \
184 1.2.4.2 yamt tmp1 = gparent->_f.left; \
185 1.2.4.2 yamt if (tmp1->_f.colour == C_RED) { \
186 1.2.4.2 yamt parent->_f.colour = C_BLACK; \
187 1.2.4.2 yamt tmp1->_f.colour = C_BLACK; \
188 1.2.4.2 yamt gparent->_f.colour = C_RED; \
189 1.2.4.2 yamt node = gparent; \
190 1.2.4.2 yamt } else { \
191 1.2.4.2 yamt if (node == parent->_f.left) { \
192 1.2.4.2 yamt node = parent; \
193 1.2.4.2 yamt rotate_right(head, node); \
194 1.2.4.2 yamt parent = node->_f.parent; \
195 1.2.4.2 yamt } \
196 1.2.4.2 yamt parent->_f.colour = C_BLACK; \
197 1.2.4.2 yamt gparent->_f.colour = C_RED; \
198 1.2.4.2 yamt rotate_left(head, parent->_f.parent); \
199 1.2.4.2 yamt } \
200 1.2.4.2 yamt } \
201 1.2.4.2 yamt parent = node->_f.parent; \
202 1.2.4.2 yamt } \
203 1.2.4.2 yamt head->top._f.right->_f.colour = C_BLACK; \
204 1.2.4.2 yamt head->count++; \
205 1.2.4.2 yamt } \
206 1.2.4.2 yamt \
207 1.2.4.2 yamt static void \
208 1.2.4.2 yamt deleteblack(struct _n##_rb_head *head, _t *parent, _t *node) \
209 1.2.4.2 yamt { \
210 1.2.4.2 yamt _t *tmp; \
211 1.2.4.2 yamt \
212 1.2.4.2 yamt while ((node == &_n##_rb_zero || node->_f.colour == C_BLACK) && \
213 1.2.4.2 yamt node != &head->top) { \
214 1.2.4.2 yamt if (parent->_f.left == node) { \
215 1.2.4.2 yamt tmp = parent->_f.right; \
216 1.2.4.2 yamt if (tmp->_f.colour == C_RED) { \
217 1.2.4.2 yamt tmp->_f.colour = C_BLACK; \
218 1.2.4.2 yamt parent->_f.colour = C_RED; \
219 1.2.4.2 yamt rotate_left(head, parent); \
220 1.2.4.2 yamt tmp = parent->_f.right; \
221 1.2.4.2 yamt } \
222 1.2.4.2 yamt if ((tmp->_f.left == &_n##_rb_zero || \
223 1.2.4.2 yamt tmp->_f.left->_f.colour == C_BLACK) && \
224 1.2.4.2 yamt (tmp->_f.right == &_n##_rb_zero || \
225 1.2.4.2 yamt tmp->_f.right->_f.colour == C_BLACK)) { \
226 1.2.4.2 yamt tmp->_f.colour = C_RED; \
227 1.2.4.2 yamt node = parent; \
228 1.2.4.2 yamt parent = node->_f.parent; \
229 1.2.4.2 yamt } else { \
230 1.2.4.2 yamt if (tmp->_f.right == &_n##_rb_zero || \
231 1.2.4.2 yamt tmp->_f.right->_f.colour == C_BLACK) {\
232 1.2.4.2 yamt _t *tmp2 = tmp->_f.left; \
233 1.2.4.2 yamt \
234 1.2.4.2 yamt if (tmp2 != &_n##_rb_zero) \
235 1.2.4.2 yamt tmp2->_f.colour = C_BLACK;\
236 1.2.4.2 yamt tmp->_f.colour = C_RED; \
237 1.2.4.2 yamt rotate_right(head, tmp); \
238 1.2.4.2 yamt tmp = parent->_f.right; \
239 1.2.4.2 yamt } \
240 1.2.4.2 yamt tmp->_f.colour = parent->_f.colour; \
241 1.2.4.2 yamt parent->_f.colour = C_BLACK; \
242 1.2.4.2 yamt if (tmp->_f.right != &_n##_rb_zero) \
243 1.2.4.2 yamt tmp->_f.right->_f.colour = C_BLACK;\
244 1.2.4.2 yamt rotate_left(head, parent); \
245 1.2.4.2 yamt node = head->top._f.right; \
246 1.2.4.2 yamt } \
247 1.2.4.2 yamt } else { \
248 1.2.4.2 yamt tmp = parent->_f.left; \
249 1.2.4.2 yamt if (tmp->_f.colour == C_RED) { \
250 1.2.4.2 yamt tmp->_f.colour = C_BLACK; \
251 1.2.4.2 yamt parent->_f.colour = C_RED; \
252 1.2.4.2 yamt rotate_right(head, parent); \
253 1.2.4.2 yamt tmp = parent->_f.left; \
254 1.2.4.2 yamt } \
255 1.2.4.2 yamt if ((tmp->_f.left == &_n##_rb_zero || \
256 1.2.4.2 yamt tmp->_f.left->_f.colour == C_BLACK) && \
257 1.2.4.2 yamt (tmp->_f.right == &_n##_rb_zero || \
258 1.2.4.2 yamt tmp->_f.right->_f.colour == C_BLACK)) { \
259 1.2.4.2 yamt tmp->_f.colour = C_RED; \
260 1.2.4.2 yamt node = parent; \
261 1.2.4.2 yamt parent = node->_f.parent; \
262 1.2.4.2 yamt } else { \
263 1.2.4.2 yamt if (tmp->_f.left == &_n##_rb_zero || \
264 1.2.4.2 yamt tmp->_f.left->_f.colour == C_BLACK) {\
265 1.2.4.2 yamt _t *tmp2 = tmp->_f.right; \
266 1.2.4.2 yamt \
267 1.2.4.2 yamt if (tmp2 != &_n##_rb_zero) \
268 1.2.4.2 yamt tmp2->_f.colour = C_BLACK;\
269 1.2.4.2 yamt tmp->_f.colour = C_RED; \
270 1.2.4.2 yamt rotate_left(head, tmp); \
271 1.2.4.2 yamt tmp = parent->_f.left; \
272 1.2.4.2 yamt } \
273 1.2.4.2 yamt tmp->_f.colour = parent->_f.colour; \
274 1.2.4.2 yamt parent->_f.colour = C_BLACK; \
275 1.2.4.2 yamt if (tmp->_f.left != &_n##_rb_zero) \
276 1.2.4.2 yamt tmp->_f.left->_f.colour = C_BLACK;\
277 1.2.4.2 yamt rotate_right(head, parent); \
278 1.2.4.2 yamt node = head->top._f.right; \
279 1.2.4.2 yamt break; \
280 1.2.4.2 yamt } \
281 1.2.4.2 yamt } \
282 1.2.4.2 yamt } \
283 1.2.4.2 yamt if (node != &_n##_rb_zero) \
284 1.2.4.2 yamt node->_f.colour = C_BLACK; \
285 1.2.4.2 yamt } \
286 1.2.4.2 yamt \
287 1.2.4.2 yamt _t * \
288 1.2.4.2 yamt _n##_rb_delete(struct _n##_rb_head *head, _t *node) \
289 1.2.4.2 yamt { \
290 1.2.4.2 yamt _t *child, *parent, *old = node, *left; \
291 1.2.4.2 yamt rbcolour_t color; \
292 1.2.4.2 yamt \
293 1.2.4.2 yamt if (node->_f.left == &_n##_rb_zero) { \
294 1.2.4.2 yamt child = node->_f.right; \
295 1.2.4.2 yamt } else if (node->_f.right == &_n##_rb_zero) { \
296 1.2.4.2 yamt child = node->_f.left; \
297 1.2.4.2 yamt } else { \
298 1.2.4.2 yamt node = node->_f.right; \
299 1.2.4.2 yamt while ((left = node->_f.left) != &_n##_rb_zero) \
300 1.2.4.2 yamt node = left; \
301 1.2.4.2 yamt child = node->_f.right; \
302 1.2.4.2 yamt parent = node->_f.parent; \
303 1.2.4.2 yamt color = node->_f.colour; \
304 1.2.4.2 yamt if (child != &_n##_rb_zero) \
305 1.2.4.2 yamt child->_f.parent = parent; \
306 1.2.4.2 yamt if (parent != &_n##_rb_zero) { \
307 1.2.4.2 yamt if (parent->_f.left == node) \
308 1.2.4.2 yamt parent->_f.left = child; \
309 1.2.4.2 yamt else \
310 1.2.4.2 yamt parent->_f.right = child; \
311 1.2.4.2 yamt } else { \
312 1.2.4.2 yamt head->top._f.right = child; \
313 1.2.4.2 yamt } \
314 1.2.4.2 yamt if (node->_f.parent == old) \
315 1.2.4.2 yamt parent = node; \
316 1.2.4.2 yamt *node = *old; \
317 1.2.4.2 yamt if (old->_f.parent != &_n##_rb_zero) { \
318 1.2.4.2 yamt if (old->_f.parent->_f.left == old) \
319 1.2.4.2 yamt old->_f.parent->_f.left = node; \
320 1.2.4.2 yamt else \
321 1.2.4.2 yamt old->_f.parent->_f.right = node; \
322 1.2.4.2 yamt } else { \
323 1.2.4.2 yamt head->top._f.right = child; \
324 1.2.4.2 yamt } \
325 1.2.4.2 yamt old->_f.left->_f.parent = node; \
326 1.2.4.2 yamt if (old->_f.right != &_n##_rb_zero) \
327 1.2.4.2 yamt old->_f.right->_f.parent = node; \
328 1.2.4.2 yamt if (parent != &_n##_rb_zero) { \
329 1.2.4.2 yamt left = parent; \
330 1.2.4.2 yamt } \
331 1.2.4.2 yamt goto colour; \
332 1.2.4.2 yamt } \
333 1.2.4.2 yamt parent = node->_f.parent; \
334 1.2.4.2 yamt color= node->_f.colour; \
335 1.2.4.2 yamt if (child != &_n##_rb_zero) \
336 1.2.4.2 yamt child->_f.parent = parent; \
337 1.2.4.2 yamt if (parent != &_n##_rb_zero) { \
338 1.2.4.2 yamt if (parent->_f.left == node) \
339 1.2.4.2 yamt parent->_f.left = child; \
340 1.2.4.2 yamt else \
341 1.2.4.2 yamt parent->_f.right = child; \
342 1.2.4.2 yamt } else { \
343 1.2.4.2 yamt head->top._f.right = child; \
344 1.2.4.2 yamt } \
345 1.2.4.2 yamt colour: \
346 1.2.4.2 yamt if (color == C_BLACK) \
347 1.2.4.2 yamt deleteblack(head, parent, node); \
348 1.2.4.2 yamt head->count--; \
349 1.2.4.2 yamt return old; \
350 1.2.4.2 yamt } \
351 1.2.4.2 yamt \
352 1.2.4.2 yamt void \
353 1.2.4.2 yamt _n##_rb_init(struct _n##_rb_head *head) \
354 1.2.4.2 yamt { \
355 1.2.4.2 yamt memset(&_n##_rb_zero, 0, sizeof(_n##_rb_zero)); \
356 1.2.4.2 yamt head->top._f.left = &_n##_rb_zero; \
357 1.2.4.2 yamt head->top._f.right = &_n##_rb_zero; \
358 1.2.4.2 yamt head->top._f.parent = &head->top; \
359 1.2.4.2 yamt _n##_rb_zero._f.left = &_n##_rb_zero; \
360 1.2.4.2 yamt _n##_rb_zero._f.right = &_n##_rb_zero; \
361 1.2.4.2 yamt _n##_rb_zero._f.parent = &_n##_rb_zero; \
362 1.2.4.2 yamt } \
363 1.2.4.2 yamt \
364 1.2.4.2 yamt void \
365 1.2.4.2 yamt _n##_rb_walktree(struct _n##_rb_head *head, _n##_rb_walker_t func, void *arg)\
366 1.2.4.2 yamt { \
367 1.2.4.2 yamt _t *prev; \
368 1.2.4.2 yamt _t *next; \
369 1.2.4.2 yamt _t *node = head->top._f.right; \
370 1.2.4.2 yamt _t *base; \
371 1.2.4.2 yamt \
372 1.2.4.2 yamt while (node != &_n##_rb_zero) \
373 1.2.4.2 yamt node = node->_f.left; \
374 1.2.4.2 yamt \
375 1.2.4.2 yamt for (;;) { \
376 1.2.4.2 yamt base = node; \
377 1.2.4.2 yamt prev = node; \
378 1.2.4.2 yamt while ((node->_f.parent->_f.right == node) && \
379 1.2.4.2 yamt (node != &_n##_rb_zero)) { \
380 1.2.4.2 yamt prev = node; \
381 1.2.4.2 yamt node = node->_f.parent; \
382 1.2.4.2 yamt } \
383 1.2.4.2 yamt \
384 1.2.4.2 yamt node = prev; \
385 1.2.4.2 yamt for (node = node->_f.parent->_f.right; node != &_n##_rb_zero;\
386 1.2.4.2 yamt node = node->_f.left) \
387 1.2.4.2 yamt prev = node; \
388 1.2.4.2 yamt next = prev; \
389 1.2.4.2 yamt \
390 1.2.4.2 yamt if (node != &_n##_rb_zero) \
391 1.2.4.2 yamt func(node, arg); \
392 1.2.4.2 yamt \
393 1.2.4.2 yamt node = next; \
394 1.2.4.2 yamt if (node == &_n##_rb_zero) \
395 1.2.4.2 yamt break; \
396 1.2.4.2 yamt } \
397 1.2.4.2 yamt } \
398 1.2.4.2 yamt \
399 1.2.4.2 yamt _t * \
400 1.2.4.2 yamt _n##_rb_search(struct _n##_rb_head *head, void *key) \
401 1.2.4.2 yamt { \
402 1.2.4.2 yamt int match = 0; \
403 1.2.4.2 yamt _t *node; \
404 1.2.4.2 yamt node = head->top._f.right; \
405 1.2.4.2 yamt while (node != &_n##_rb_zero) { \
406 1.2.4.2 yamt match = _cmp(key, node); \
407 1.2.4.2 yamt if (match == 0) \
408 1.2.4.2 yamt break; \
409 1.2.4.2 yamt if (match< 0) \
410 1.2.4.2 yamt node = node->_f.left; \
411 1.2.4.2 yamt else \
412 1.2.4.2 yamt node = node->_f.right; \
413 1.2.4.2 yamt } \
414 1.2.4.2 yamt if (node == &_n##_rb_zero || match != 0) \
415 1.2.4.2 yamt return (NULL); \
416 1.2.4.2 yamt return (node); \
417 1.2.4.2 yamt }
418 1.2.4.2 yamt
419 1.2.4.2 yamt #define RBI_DELETE(_n, _h, _v) _n##_rb_delete(_h, _v)
420 1.2.4.2 yamt #define RBI_INIT(_n, _h) _n##_rb_init(_h)
421 1.2.4.2 yamt #define RBI_INSERT(_n, _h, _v) _n##_rb_insert(_h, _v)
422 1.2.4.2 yamt #define RBI_ISEMPTY(_h) ((_h)->count == 0)
423 1.2.4.2 yamt #define RBI_SEARCH(_n, _h, _k) _n##_rb_search(_h, _k)
424 1.2.4.2 yamt #define RBI_WALK(_n, _h, _w, _a) _n##_rb_walktree(_h, _w, _a)
425 1.2.4.2 yamt #define RBI_ZERO(_n) _n##_rb_zero
426 1.2.4.4 yamt
427 1.2.4.4 yamt #endif
428