2 * Originally sys/tree.h from FreeBSD. Changes:
4 * - name changed to avoid collisions
8 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #ifndef __PSCNV_TREE_H__
33 #define __PSCNV_TREE_H__
35 #define __unused __attribute__((__unused__))
37 /* Macros that define a red-black tree */
38 #define PSCNV_RB_HEAD(name, type) \
40 struct type *rbh_root; /* root of the tree */ \
43 #define PSCNV_RB_INITIALIZER(root) \
46 #define PSCNV_RB_INIT(root) do { \
47 (root)->rbh_root = NULL; \
48 } while (/*CONSTCOND*/ 0)
50 #define PSCNV_RB_BLACK 0
51 #define PSCNV_RB_RED 1
52 #define PSCNV_RB_ENTRY(type) \
54 struct type *rbe_left; /* left element */ \
55 struct type *rbe_right; /* right element */ \
56 struct type *rbe_parent; /* parent element */ \
57 int rbe_color; /* node color */ \
60 #define PSCNV_RB_LEFT(elm, field) (elm)->field.rbe_left
61 #define PSCNV_RB_RIGHT(elm, field) (elm)->field.rbe_right
62 #define PSCNV_RB_PARENT(elm, field) (elm)->field.rbe_parent
63 #define PSCNV_RB_COLOR(elm, field) (elm)->field.rbe_color
64 #define PSCNV_RB_ROOT(head) (head)->rbh_root
65 #define PSCNV_RB_EMPTY(head) (PSCNV_RB_ROOT(head) == NULL)
67 #define PSCNV_RB_SET(elm, parent, field) do { \
68 PSCNV_RB_PARENT(elm, field) = parent; \
69 PSCNV_RB_LEFT(elm, field) = PSCNV_RB_RIGHT(elm, field) = NULL; \
70 PSCNV_RB_COLOR(elm, field) = PSCNV_RB_RED; \
71 } while (/*CONSTCOND*/ 0)
73 #define PSCNV_RB_SET_BLACKRED(black, red, field) do { \
74 PSCNV_RB_COLOR(black, field) = PSCNV_RB_BLACK; \
75 PSCNV_RB_COLOR(red, field) = PSCNV_RB_RED; \
76 } while (/*CONSTCOND*/ 0)
78 #ifndef PSCNV_RB_AUGMENT
79 #define PSCNV_RB_AUGMENT(x) (void)(x)
82 #define PSCNV_RB_ROTATE_LEFT(head, elm, tmp, field) do { \
83 (tmp) = PSCNV_RB_RIGHT(elm, field); \
84 if ((PSCNV_RB_RIGHT(elm, field) = PSCNV_RB_LEFT(tmp, field)) != NULL) { \
85 PSCNV_RB_PARENT(PSCNV_RB_LEFT(tmp, field), field) = (elm); \
87 PSCNV_RB_AUGMENT(elm); \
88 if ((PSCNV_RB_PARENT(tmp, field) = PSCNV_RB_PARENT(elm, field)) != NULL) { \
89 if ((elm) == PSCNV_RB_LEFT(PSCNV_RB_PARENT(elm, field), field)) \
90 PSCNV_RB_LEFT(PSCNV_RB_PARENT(elm, field), field) = (tmp); \
92 PSCNV_RB_RIGHT(PSCNV_RB_PARENT(elm, field), field) = (tmp); \
94 (head)->rbh_root = (tmp); \
95 PSCNV_RB_LEFT(tmp, field) = (elm); \
96 PSCNV_RB_PARENT(elm, field) = (tmp); \
97 PSCNV_RB_AUGMENT(tmp); \
98 if ((PSCNV_RB_PARENT(tmp, field))) \
99 PSCNV_RB_AUGMENT(PSCNV_RB_PARENT(tmp, field)); \
100 } while (/*CONSTCOND*/ 0)
102 #define PSCNV_RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
103 (tmp) = PSCNV_RB_LEFT(elm, field); \
104 if ((PSCNV_RB_LEFT(elm, field) = PSCNV_RB_RIGHT(tmp, field)) != NULL) { \
105 PSCNV_RB_PARENT(PSCNV_RB_RIGHT(tmp, field), field) = (elm); \
107 PSCNV_RB_AUGMENT(elm); \
108 if ((PSCNV_RB_PARENT(tmp, field) = PSCNV_RB_PARENT(elm, field)) != NULL) { \
109 if ((elm) == PSCNV_RB_LEFT(PSCNV_RB_PARENT(elm, field), field)) \
110 PSCNV_RB_LEFT(PSCNV_RB_PARENT(elm, field), field) = (tmp); \
112 PSCNV_RB_RIGHT(PSCNV_RB_PARENT(elm, field), field) = (tmp); \
114 (head)->rbh_root = (tmp); \
115 PSCNV_RB_RIGHT(tmp, field) = (elm); \
116 PSCNV_RB_PARENT(elm, field) = (tmp); \
117 PSCNV_RB_AUGMENT(tmp); \
118 if ((PSCNV_RB_PARENT(tmp, field))) \
119 PSCNV_RB_AUGMENT(PSCNV_RB_PARENT(tmp, field)); \
120 } while (/*CONSTCOND*/ 0)
122 /* Generates prototypes and inline functions */
123 #define PSCNV_RB_PROTOTYPE(name, type, field, cmp) \
124 PSCNV_RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
125 #define PSCNV_RB_PROTOTYPE_STATIC(name, type, field, cmp) \
126 PSCNV_RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
127 #define PSCNV_RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
128 attr void name##_PSCNV_RB_INSERT_COLOR(struct name *, struct type *); \
129 attr void name##_PSCNV_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
130 attr struct type *name##_PSCNV_RB_REMOVE(struct name *, struct type *); \
131 attr struct type *name##_PSCNV_RB_INSERT(struct name *, struct type *); \
132 attr struct type *name##_PSCNV_RB_FIND(struct name *, struct type *); \
133 attr struct type *name##_PSCNV_RB_NFIND(struct name *, struct type *); \
134 attr struct type *name##_PSCNV_RB_NEXT(struct type *); \
135 attr struct type *name##_PSCNV_RB_PREV(struct type *); \
136 attr struct type *name##_PSCNV_RB_MINMAX(struct name *, int); \
139 /* Main rb operation.
140 * Moves node close to the key of elm to top
142 #define PSCNV_RB_GENERATE(name, type, field, cmp) \
143 PSCNV_RB_GENERATE_INTERNAL(name, type, field, cmp,)
144 #define PSCNV_RB_GENERATE_STATIC(name, type, field, cmp) \
145 PSCNV_RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
146 #define PSCNV_RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
148 name##_PSCNV_RB_INSERT_COLOR(struct name *head, struct type *elm) \
150 struct type *parent, *gparent, *tmp; \
151 while ((parent = PSCNV_RB_PARENT(elm, field)) != NULL && \
152 PSCNV_RB_COLOR(parent, field) == PSCNV_RB_RED) { \
153 gparent = PSCNV_RB_PARENT(parent, field); \
154 if (parent == PSCNV_RB_LEFT(gparent, field)) { \
155 tmp = PSCNV_RB_RIGHT(gparent, field); \
156 if (tmp && PSCNV_RB_COLOR(tmp, field) == PSCNV_RB_RED) { \
157 PSCNV_RB_COLOR(tmp, field) = PSCNV_RB_BLACK; \
158 PSCNV_RB_SET_BLACKRED(parent, gparent, field);\
162 if (PSCNV_RB_RIGHT(parent, field) == elm) { \
163 PSCNV_RB_ROTATE_LEFT(head, parent, tmp, field);\
168 PSCNV_RB_SET_BLACKRED(parent, gparent, field); \
169 PSCNV_RB_ROTATE_RIGHT(head, gparent, tmp, field); \
171 tmp = PSCNV_RB_LEFT(gparent, field); \
172 if (tmp && PSCNV_RB_COLOR(tmp, field) == PSCNV_RB_RED) { \
173 PSCNV_RB_COLOR(tmp, field) = PSCNV_RB_BLACK; \
174 PSCNV_RB_SET_BLACKRED(parent, gparent, field);\
178 if (PSCNV_RB_LEFT(parent, field) == elm) { \
179 PSCNV_RB_ROTATE_RIGHT(head, parent, tmp, field);\
184 PSCNV_RB_SET_BLACKRED(parent, gparent, field); \
185 PSCNV_RB_ROTATE_LEFT(head, gparent, tmp, field); \
188 PSCNV_RB_COLOR(head->rbh_root, field) = PSCNV_RB_BLACK; \
192 name##_PSCNV_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
195 while ((elm == NULL || PSCNV_RB_COLOR(elm, field) == PSCNV_RB_BLACK) && \
196 elm != PSCNV_RB_ROOT(head)) { \
197 if (PSCNV_RB_LEFT(parent, field) == elm) { \
198 tmp = PSCNV_RB_RIGHT(parent, field); \
199 if (PSCNV_RB_COLOR(tmp, field) == PSCNV_RB_RED) { \
200 PSCNV_RB_SET_BLACKRED(tmp, parent, field); \
201 PSCNV_RB_ROTATE_LEFT(head, parent, tmp, field);\
202 tmp = PSCNV_RB_RIGHT(parent, field); \
204 if ((PSCNV_RB_LEFT(tmp, field) == NULL || \
205 PSCNV_RB_COLOR(PSCNV_RB_LEFT(tmp, field), field) == PSCNV_RB_BLACK) &&\
206 (PSCNV_RB_RIGHT(tmp, field) == NULL || \
207 PSCNV_RB_COLOR(PSCNV_RB_RIGHT(tmp, field), field) == PSCNV_RB_BLACK)) {\
208 PSCNV_RB_COLOR(tmp, field) = PSCNV_RB_RED; \
210 parent = PSCNV_RB_PARENT(elm, field); \
212 if (PSCNV_RB_RIGHT(tmp, field) == NULL || \
213 PSCNV_RB_COLOR(PSCNV_RB_RIGHT(tmp, field), field) == PSCNV_RB_BLACK) {\
214 struct type *oleft; \
215 if ((oleft = PSCNV_RB_LEFT(tmp, field)) \
217 PSCNV_RB_COLOR(oleft, field) = PSCNV_RB_BLACK;\
218 PSCNV_RB_COLOR(tmp, field) = PSCNV_RB_RED; \
219 PSCNV_RB_ROTATE_RIGHT(head, tmp, oleft, field);\
220 tmp = PSCNV_RB_RIGHT(parent, field); \
222 PSCNV_RB_COLOR(tmp, field) = PSCNV_RB_COLOR(parent, field);\
223 PSCNV_RB_COLOR(parent, field) = PSCNV_RB_BLACK; \
224 if (PSCNV_RB_RIGHT(tmp, field)) \
225 PSCNV_RB_COLOR(PSCNV_RB_RIGHT(tmp, field), field) = PSCNV_RB_BLACK;\
226 PSCNV_RB_ROTATE_LEFT(head, parent, tmp, field);\
227 elm = PSCNV_RB_ROOT(head); \
231 tmp = PSCNV_RB_LEFT(parent, field); \
232 if (PSCNV_RB_COLOR(tmp, field) == PSCNV_RB_RED) { \
233 PSCNV_RB_SET_BLACKRED(tmp, parent, field); \
234 PSCNV_RB_ROTATE_RIGHT(head, parent, tmp, field);\
235 tmp = PSCNV_RB_LEFT(parent, field); \
237 if ((PSCNV_RB_LEFT(tmp, field) == NULL || \
238 PSCNV_RB_COLOR(PSCNV_RB_LEFT(tmp, field), field) == PSCNV_RB_BLACK) &&\
239 (PSCNV_RB_RIGHT(tmp, field) == NULL || \
240 PSCNV_RB_COLOR(PSCNV_RB_RIGHT(tmp, field), field) == PSCNV_RB_BLACK)) {\
241 PSCNV_RB_COLOR(tmp, field) = PSCNV_RB_RED; \
243 parent = PSCNV_RB_PARENT(elm, field); \
245 if (PSCNV_RB_LEFT(tmp, field) == NULL || \
246 PSCNV_RB_COLOR(PSCNV_RB_LEFT(tmp, field), field) == PSCNV_RB_BLACK) {\
247 struct type *oright; \
248 if ((oright = PSCNV_RB_RIGHT(tmp, field)) \
250 PSCNV_RB_COLOR(oright, field) = PSCNV_RB_BLACK;\
251 PSCNV_RB_COLOR(tmp, field) = PSCNV_RB_RED; \
252 PSCNV_RB_ROTATE_LEFT(head, tmp, oright, field);\
253 tmp = PSCNV_RB_LEFT(parent, field); \
255 PSCNV_RB_COLOR(tmp, field) = PSCNV_RB_COLOR(parent, field);\
256 PSCNV_RB_COLOR(parent, field) = PSCNV_RB_BLACK; \
257 if (PSCNV_RB_LEFT(tmp, field)) \
258 PSCNV_RB_COLOR(PSCNV_RB_LEFT(tmp, field), field) = PSCNV_RB_BLACK;\
259 PSCNV_RB_ROTATE_RIGHT(head, parent, tmp, field);\
260 elm = PSCNV_RB_ROOT(head); \
266 PSCNV_RB_COLOR(elm, field) = PSCNV_RB_BLACK; \
270 name##_PSCNV_RB_REMOVE(struct name *head, struct type *elm) \
272 struct type *child, *parent, *old = elm; \
274 if (PSCNV_RB_LEFT(elm, field) == NULL) \
275 child = PSCNV_RB_RIGHT(elm, field); \
276 else if (PSCNV_RB_RIGHT(elm, field) == NULL) \
277 child = PSCNV_RB_LEFT(elm, field); \
280 elm = PSCNV_RB_RIGHT(elm, field); \
281 while ((left = PSCNV_RB_LEFT(elm, field)) != NULL) \
283 child = PSCNV_RB_RIGHT(elm, field); \
284 parent = PSCNV_RB_PARENT(elm, field); \
285 color = PSCNV_RB_COLOR(elm, field); \
287 PSCNV_RB_PARENT(child, field) = parent; \
289 if (PSCNV_RB_LEFT(parent, field) == elm) \
290 PSCNV_RB_LEFT(parent, field) = child; \
292 PSCNV_RB_RIGHT(parent, field) = child; \
293 PSCNV_RB_AUGMENT(parent); \
295 PSCNV_RB_ROOT(head) = child; \
296 if (PSCNV_RB_PARENT(elm, field) == old) \
298 (elm)->field = (old)->field; \
299 if (PSCNV_RB_PARENT(old, field)) { \
300 if (PSCNV_RB_LEFT(PSCNV_RB_PARENT(old, field), field) == old)\
301 PSCNV_RB_LEFT(PSCNV_RB_PARENT(old, field), field) = elm;\
303 PSCNV_RB_RIGHT(PSCNV_RB_PARENT(old, field), field) = elm;\
304 PSCNV_RB_AUGMENT(PSCNV_RB_PARENT(old, field)); \
306 PSCNV_RB_ROOT(head) = elm; \
307 PSCNV_RB_PARENT(PSCNV_RB_LEFT(old, field), field) = elm; \
308 if (PSCNV_RB_RIGHT(old, field)) \
309 PSCNV_RB_PARENT(PSCNV_RB_RIGHT(old, field), field) = elm; \
313 PSCNV_RB_AUGMENT(left); \
314 } while ((left = PSCNV_RB_PARENT(left, field)) != NULL); \
318 parent = PSCNV_RB_PARENT(elm, field); \
319 color = PSCNV_RB_COLOR(elm, field); \
321 PSCNV_RB_PARENT(child, field) = parent; \
323 if (PSCNV_RB_LEFT(parent, field) == elm) \
324 PSCNV_RB_LEFT(parent, field) = child; \
326 PSCNV_RB_RIGHT(parent, field) = child; \
327 PSCNV_RB_AUGMENT(parent); \
329 PSCNV_RB_ROOT(head) = child; \
331 if (color == PSCNV_RB_BLACK) \
332 name##_PSCNV_RB_REMOVE_COLOR(head, parent, child); \
336 /* Inserts a node into the RB tree */ \
338 name##_PSCNV_RB_INSERT(struct name *head, struct type *elm) \
341 struct type *parent = NULL; \
343 tmp = PSCNV_RB_ROOT(head); \
346 comp = (cmp)(elm, parent); \
348 tmp = PSCNV_RB_LEFT(tmp, field); \
350 tmp = PSCNV_RB_RIGHT(tmp, field); \
354 PSCNV_RB_SET(elm, parent, field); \
355 if (parent != NULL) { \
357 PSCNV_RB_LEFT(parent, field) = elm; \
359 PSCNV_RB_RIGHT(parent, field) = elm; \
360 PSCNV_RB_AUGMENT(parent); \
362 PSCNV_RB_ROOT(head) = elm; \
363 name##_PSCNV_RB_INSERT_COLOR(head, elm); \
367 /* Finds the node with the same key as elm */ \
369 name##_PSCNV_RB_FIND(struct name *head, struct type *elm) \
371 struct type *tmp = PSCNV_RB_ROOT(head); \
374 comp = cmp(elm, tmp); \
376 tmp = PSCNV_RB_LEFT(tmp, field); \
378 tmp = PSCNV_RB_RIGHT(tmp, field); \
385 /* Finds the first node greater than or equal to the search key */ \
387 name##_PSCNV_RB_NFIND(struct name *head, struct type *elm) \
389 struct type *tmp = PSCNV_RB_ROOT(head); \
390 struct type *res = NULL; \
393 comp = cmp(elm, tmp); \
396 tmp = PSCNV_RB_LEFT(tmp, field); \
399 tmp = PSCNV_RB_RIGHT(tmp, field); \
408 name##_PSCNV_RB_NEXT(struct type *elm) \
410 if (PSCNV_RB_RIGHT(elm, field)) { \
411 elm = PSCNV_RB_RIGHT(elm, field); \
412 while (PSCNV_RB_LEFT(elm, field)) \
413 elm = PSCNV_RB_LEFT(elm, field); \
415 if (PSCNV_RB_PARENT(elm, field) && \
416 (elm == PSCNV_RB_LEFT(PSCNV_RB_PARENT(elm, field), field))) \
417 elm = PSCNV_RB_PARENT(elm, field); \
419 while (PSCNV_RB_PARENT(elm, field) && \
420 (elm == PSCNV_RB_RIGHT(PSCNV_RB_PARENT(elm, field), field)))\
421 elm = PSCNV_RB_PARENT(elm, field); \
422 elm = PSCNV_RB_PARENT(elm, field); \
430 name##_PSCNV_RB_PREV(struct type *elm) \
432 if (PSCNV_RB_LEFT(elm, field)) { \
433 elm = PSCNV_RB_LEFT(elm, field); \
434 while (PSCNV_RB_RIGHT(elm, field)) \
435 elm = PSCNV_RB_RIGHT(elm, field); \
437 if (PSCNV_RB_PARENT(elm, field) && \
438 (elm == PSCNV_RB_RIGHT(PSCNV_RB_PARENT(elm, field), field))) \
439 elm = PSCNV_RB_PARENT(elm, field); \
441 while (PSCNV_RB_PARENT(elm, field) && \
442 (elm == PSCNV_RB_LEFT(PSCNV_RB_PARENT(elm, field), field)))\
443 elm = PSCNV_RB_PARENT(elm, field); \
444 elm = PSCNV_RB_PARENT(elm, field); \
451 name##_PSCNV_RB_MINMAX(struct name *head, int val) \
453 struct type *tmp = PSCNV_RB_ROOT(head); \
454 struct type *parent = NULL; \
458 tmp = PSCNV_RB_LEFT(tmp, field); \
460 tmp = PSCNV_RB_RIGHT(tmp, field); \
465 #define PSCNV_RB_NEGINF -1
466 #define PSCNV_RB_INF 1
468 #define PSCNV_RB_INSERT(name, x, y) name##_PSCNV_RB_INSERT(x, y)
469 #define PSCNV_RB_REMOVE(name, x, y) name##_PSCNV_RB_REMOVE(x, y)
470 #define PSCNV_RB_FIND(name, x, y) name##_PSCNV_RB_FIND(x, y)
471 #define PSCNV_RB_NFIND(name, x, y) name##_PSCNV_RB_NFIND(x, y)
472 #define PSCNV_RB_NEXT(name, x, y) name##_PSCNV_RB_NEXT(y)
473 #define PSCNV_RB_PREV(name, x, y) name##_PSCNV_RB_PREV(y)
474 #define PSCNV_RB_MIN(name, x) name##_PSCNV_RB_MINMAX(x, PSCNV_RB_NEGINF)
475 #define PSCNV_RB_MAX(name, x) name##_PSCNV_RB_MINMAX(x, PSCNV_RB_INF)
477 #define PSCNV_RB_FOREACH(x, name, head) \
478 for ((x) = PSCNV_RB_MIN(name, head); \
480 (x) = name##_PSCNV_RB_NEXT(x))
482 #define PSCNV_RB_FOREACH_REVERSE(x, name, head) \
483 for ((x) = PSCNV_RB_MAX(name, head); \
485 (x) = name##_PSCNV_RB_PREV(x))
487 #endif /* __PSCNV_TREE_H__ */