• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*  $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $  */
2 /*  $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $    */
3 /* $FreeBSD: src/sys/sys/tree.h,v 1.9.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $ */
4 
5 /*-
6  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef _SYS_TREE_H_
31 #define _SYS_TREE_H_
32 
33 /* Ommit "struct" prefix if this code is built with C++,
34  * so it can build. */
35 #ifdef __cplusplus
36 #define SYS_TREE_STRUCT
37 #else
38 #define SYS_TREE_STRUCT  struct
39 #endif
40 
41 /*
42  * This file defines data structures for different types of trees:
43  * splay trees and red-black trees.
44  *
45  * A splay tree is a self-organizing data structure.  Every operation
46  * on the tree causes a splay to happen.  The splay moves the requested
47  * node to the root of the tree and partly rebalances it.
48  *
49  * This has the benefit that request locality causes faster lookups as
50  * the requested nodes move to the top of the tree.  On the other hand,
51  * every lookup causes memory writes.
52  *
53  * The Balance Theorem bounds the total access time for m operations
54  * and n inserts on an initially empty tree as O((m + n)lg n).  The
55  * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
56  *
57  * A red-black tree is a binary search tree with the node color as an
58  * extra attribute.  It fulfills a set of conditions:
59  *  - every search path from the root to a leaf consists of the
60  *    same number of black nodes,
61  *  - each red node (except for the root) has a black parent,
62  *  - each leaf node is black.
63  *
64  * Every operation on a red-black tree is bounded as O(lg n).
65  * The maximum height of a red-black tree is 2lg (n+1).
66  */
67 
68 #define SPLAY_HEAD(name, type)                      \
69 struct name {                               \
70     SYS_TREE_STRUCT type *sph_root; /* root of the tree */           \
71 }
72 
73 #define SPLAY_INITIALIZER(root)                     \
74     { NULL }
75 
76 #define SPLAY_INIT(root) do {                       \
77     (root)->sph_root = NULL;                    \
78 } while (/*CONSTCOND*/ 0)
79 
80 #define SPLAY_ENTRY(type)                       \
81 struct {                                \
82     SYS_TREE_STRUCT type *spe_left; /* left element */           \
83     SYS_TREE_STRUCT type *spe_right; /* right element */         \
84 }
85 
86 #define SPLAY_LEFT(elm, field)      (elm)->field.spe_left
87 #define SPLAY_RIGHT(elm, field)     (elm)->field.spe_right
88 #define SPLAY_ROOT(head)        (head)->sph_root
89 #define SPLAY_EMPTY(head)       (SPLAY_ROOT(head) == NULL)
90 
91 /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
92 #define SPLAY_ROTATE_RIGHT(head, tmp, field) do {           \
93     SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);  \
94     SPLAY_RIGHT(tmp, field) = (head)->sph_root;         \
95     (head)->sph_root = tmp;                     \
96 } while (/*CONSTCOND*/ 0)
97 
98 #define SPLAY_ROTATE_LEFT(head, tmp, field) do {            \
99     SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);  \
100     SPLAY_LEFT(tmp, field) = (head)->sph_root;          \
101     (head)->sph_root = tmp;                     \
102 } while (/*CONSTCOND*/ 0)
103 
104 #define SPLAY_LINKLEFT(head, tmp, field) do {               \
105     SPLAY_LEFT(tmp, field) = (head)->sph_root;          \
106     tmp = (head)->sph_root;                     \
107     (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);     \
108 } while (/*CONSTCOND*/ 0)
109 
110 #define SPLAY_LINKRIGHT(head, tmp, field) do {              \
111     SPLAY_RIGHT(tmp, field) = (head)->sph_root;         \
112     tmp = (head)->sph_root;                     \
113     (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);    \
114 } while (/*CONSTCOND*/ 0)
115 
116 #define SPLAY_ASSEMBLE(head, node, left, right, field) do {     \
117     SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
118     SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
119     SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
120     SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
121 } while (/*CONSTCOND*/ 0)
122 
123 /* Generates prototypes and inline functions */
124 
125 #define SPLAY_PROTOTYPE(name, type, field, cmp)             \
126 void name##_SPLAY(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *);            \
127 void name##_SPLAY_MINMAX(SYS_TREE_STRUCT name *, int);               \
128 SYS_TREE_STRUCT type *name##_SPLAY_INSERT(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *);     \
129 SYS_TREE_STRUCT type *name##_SPLAY_REMOVE(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *);     \
130                                     \
131 /* Finds the node with the same key as elm */               \
132 static __inline SYS_TREE_STRUCT type *                       \
133 name##_SPLAY_FIND(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)          \
134 {                                   \
135     if (SPLAY_EMPTY(head))                      \
136         return(NULL);                       \
137     name##_SPLAY(head, elm);                    \
138     if ((cmp)(elm, (head)->sph_root) == 0)              \
139         return (head->sph_root);                \
140     return (NULL);                          \
141 }                                   \
142                                     \
143 static __inline SYS_TREE_STRUCT type *                       \
144 name##_SPLAY_NEXT(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)          \
145 {                                   \
146     name##_SPLAY(head, elm);                    \
147     if (SPLAY_RIGHT(elm, field) != NULL) {              \
148         elm = SPLAY_RIGHT(elm, field);              \
149         while (SPLAY_LEFT(elm, field) != NULL) {        \
150             elm = SPLAY_LEFT(elm, field);           \
151         }                           \
152     } else                              \
153         elm = NULL;                     \
154     return (elm);                           \
155 }                                   \
156                                     \
157 static __inline SYS_TREE_STRUCT type *                       \
158 name##_SPLAY_MIN_MAX(SYS_TREE_STRUCT name *head, int val)            \
159 {                                   \
160     name##_SPLAY_MINMAX(head, val);                 \
161         return (SPLAY_ROOT(head));                  \
162 }
163 
164 /* Main splay operation.
165  * Moves node close to the key of elm to top
166  */
167 #define SPLAY_GENERATE(name, type, field, cmp)              \
168 SYS_TREE_STRUCT type *                               \
169 name##_SPLAY_INSERT(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)        \
170 {                                   \
171     if (SPLAY_EMPTY(head)) {                        \
172         SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;    \
173     } else {                                \
174         int __comp;                         \
175         name##_SPLAY(head, elm);                    \
176         __comp = (cmp)(elm, (head)->sph_root);          \
177         if(__comp < 0) {                        \
178             SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
179             SPLAY_RIGHT(elm, field) = (head)->sph_root;     \
180             SPLAY_LEFT((head)->sph_root, field) = NULL;     \
181         } else if (__comp > 0) {                    \
182             SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
183             SPLAY_LEFT(elm, field) = (head)->sph_root;      \
184             SPLAY_RIGHT((head)->sph_root, field) = NULL;    \
185         } else                          \
186             return ((head)->sph_root);              \
187     }                                   \
188     (head)->sph_root = (elm);                       \
189     return (NULL);                          \
190 }                                   \
191                                     \
192 SYS_TREE_STRUCT type *                               \
193 name##_SPLAY_REMOVE(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)        \
194 {                                   \
195     SYS_TREE_STRUCT type *__tmp;                     \
196     if (SPLAY_EMPTY(head))                      \
197         return (NULL);                      \
198     name##_SPLAY(head, elm);                    \
199     if ((cmp)(elm, (head)->sph_root) == 0) {            \
200         if (SPLAY_LEFT((head)->sph_root, field) == NULL) {  \
201             (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
202         } else {                        \
203             __tmp = SPLAY_RIGHT((head)->sph_root, field);   \
204             (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
205             name##_SPLAY(head, elm);            \
206             SPLAY_RIGHT((head)->sph_root, field) = __tmp;   \
207         }                           \
208         return (elm);                       \
209     }                               \
210     return (NULL);                          \
211 }                                   \
212                                     \
213 void                                    \
214 name##_SPLAY(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)           \
215 {                                   \
216     SYS_TREE_STRUCT type __node, *__left, *__right, *__tmp;          \
217     int __comp;                         \
218 \
219     SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
220     __left = __right = &__node;                 \
221 \
222     while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) {      \
223         if (__comp < 0) {                   \
224             __tmp = SPLAY_LEFT((head)->sph_root, field);    \
225             if (__tmp == NULL)              \
226                 break;                  \
227             if ((cmp)(elm, __tmp) < 0){         \
228                 SPLAY_ROTATE_RIGHT(head, __tmp, field); \
229                 if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
230                     break;              \
231             }                       \
232             SPLAY_LINKLEFT(head, __right, field);       \
233         } else if (__comp > 0) {                \
234             __tmp = SPLAY_RIGHT((head)->sph_root, field);   \
235             if (__tmp == NULL)              \
236                 break;                  \
237             if ((cmp)(elm, __tmp) > 0){         \
238                 SPLAY_ROTATE_LEFT(head, __tmp, field);  \
239                 if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
240                     break;              \
241             }                       \
242             SPLAY_LINKRIGHT(head, __left, field);       \
243         }                           \
244     }                               \
245     SPLAY_ASSEMBLE(head, &__node, __left, __right, field);      \
246 }                                   \
247                                     \
248 /* Splay with either the minimum or the maximum element         \
249  * Used to find minimum or maximum element in tree.         \
250  */                                 \
251 void name##_SPLAY_MINMAX(SYS_TREE_STRUCT name *head, int __comp) \
252 {                                   \
253     SYS_TREE_STRUCT type __node, *__left, *__right, *__tmp;          \
254 \
255     SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
256     __left = __right = &__node;                 \
257 \
258     while (1) {                         \
259         if (__comp < 0) {                   \
260             __tmp = SPLAY_LEFT((head)->sph_root, field);    \
261             if (__tmp == NULL)              \
262                 break;                  \
263             if (__comp < 0){                \
264                 SPLAY_ROTATE_RIGHT(head, __tmp, field); \
265                 if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
266                     break;              \
267             }                       \
268             SPLAY_LINKLEFT(head, __right, field);       \
269         } else if (__comp > 0) {                \
270             __tmp = SPLAY_RIGHT((head)->sph_root, field);   \
271             if (__tmp == NULL)              \
272                 break;                  \
273             if (__comp > 0) {               \
274                 SPLAY_ROTATE_LEFT(head, __tmp, field);  \
275                 if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
276                     break;              \
277             }                       \
278             SPLAY_LINKRIGHT(head, __left, field);       \
279         }                           \
280     }                               \
281     SPLAY_ASSEMBLE(head, &__node, __left, __right, field);      \
282 }
283 
284 #define SPLAY_NEGINF    -1
285 #define SPLAY_INF   1
286 
287 #define SPLAY_INSERT(name, x, y)    name##_SPLAY_INSERT(x, y)
288 #define SPLAY_REMOVE(name, x, y)    name##_SPLAY_REMOVE(x, y)
289 #define SPLAY_FIND(name, x, y)      name##_SPLAY_FIND(x, y)
290 #define SPLAY_NEXT(name, x, y)      name##_SPLAY_NEXT(x, y)
291 #define SPLAY_MIN(name, x)      (SPLAY_EMPTY(x) ? NULL  \
292                     : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
293 #define SPLAY_MAX(name, x)      (SPLAY_EMPTY(x) ? NULL  \
294                     : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
295 
296 #define SPLAY_FOREACH(x, name, head)                    \
297     for ((x) = SPLAY_MIN(name, head);               \
298          (x) != NULL;                       \
299          (x) = SPLAY_NEXT(name, head, x))
300 
301 /* Macros that define a red-black tree */
302 #define RB_HEAD(name, type)                     \
303 struct name {                               \
304     SYS_TREE_STRUCT type *rbh_root; /* root of the tree */           \
305 }
306 
307 #define RB_INITIALIZER(root)                        \
308     { NULL }
309 
310 #define RB_INIT(root) do {                      \
311     (root)->rbh_root = NULL;                    \
312 } while (/*CONSTCOND*/ 0)
313 
314 #define RB_BLACK    0
315 #define RB_RED      1
316 #define RB_ENTRY(type)                          \
317 struct {                                \
318     SYS_TREE_STRUCT type *rbe_left;      /* left element */      \
319     SYS_TREE_STRUCT type *rbe_right;     /* right element */     \
320     SYS_TREE_STRUCT type *rbe_parent;    /* parent element */        \
321     int rbe_color;          /* node color */        \
322 }
323 
324 #define RB_LEFT(elm, field)     (elm)->field.rbe_left
325 #define RB_RIGHT(elm, field)        (elm)->field.rbe_right
326 #define RB_PARENT(elm, field)       (elm)->field.rbe_parent
327 #define RB_COLOR(elm, field)        (elm)->field.rbe_color
328 #define RB_ROOT(head)           (head)->rbh_root
329 #define RB_EMPTY(head)          (RB_ROOT(head) == NULL)
330 
331 #define RB_SET(elm, parent, field) do {                 \
332     RB_PARENT(elm, field) = parent;                 \
333     RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;      \
334     RB_COLOR(elm, field) = RB_RED;                  \
335 } while (/*CONSTCOND*/ 0)
336 
337 #define RB_SET_BLACKRED(black, red, field) do {             \
338     RB_COLOR(black, field) = RB_BLACK;              \
339     RB_COLOR(red, field) = RB_RED;                  \
340 } while (/*CONSTCOND*/ 0)
341 
342 #ifndef RB_AUGMENT
343 #define RB_AUGMENT(x)   do {} while (0)
344 #endif
345 
346 #define RB_ROTATE_LEFT(head, elm, tmp, field) do {          \
347     (tmp) = RB_RIGHT(elm, field);                   \
348     if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
349         RB_PARENT(RB_LEFT(tmp, field), field) = (elm);      \
350     }                               \
351     RB_AUGMENT(elm);                        \
352     if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) {  \
353         if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
354             RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
355         else                            \
356             RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
357     } else                              \
358         (head)->rbh_root = (tmp);               \
359     RB_LEFT(tmp, field) = (elm);                    \
360     RB_PARENT(elm, field) = (tmp);                  \
361     RB_AUGMENT(tmp);                        \
362     if ((RB_PARENT(tmp, field)))                    \
363         RB_AUGMENT(RB_PARENT(tmp, field));          \
364 } while (/*CONSTCOND*/ 0)
365 
366 #define RB_ROTATE_RIGHT(head, elm, tmp, field) do {         \
367     (tmp) = RB_LEFT(elm, field);                    \
368     if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
369         RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);     \
370     }                               \
371     RB_AUGMENT(elm);                        \
372     if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) {  \
373         if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
374             RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
375         else                            \
376             RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
377     } else                              \
378         (head)->rbh_root = (tmp);               \
379     RB_RIGHT(tmp, field) = (elm);                   \
380     RB_PARENT(elm, field) = (tmp);                  \
381     RB_AUGMENT(tmp);                        \
382     if ((RB_PARENT(tmp, field)))                    \
383         RB_AUGMENT(RB_PARENT(tmp, field));          \
384 } while (/*CONSTCOND*/ 0)
385 
386 /* Generates prototypes and inline functions */
387 #define RB_PROTOTYPE(name, type, field, cmp)                \
388     RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
389 #define RB_PROTOTYPE_STATIC(name, type, field, cmp)         \
390     RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
391 #define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)     \
392 attr void name##_RB_INSERT_COLOR(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *);     \
393 attr void name##_RB_REMOVE_COLOR(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *, SYS_TREE_STRUCT type *);\
394 attr SYS_TREE_STRUCT type *name##_RB_REMOVE(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *);   \
395 attr SYS_TREE_STRUCT type *name##_RB_INSERT(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *);   \
396 attr SYS_TREE_STRUCT type *name##_RB_FIND(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *);     \
397 attr SYS_TREE_STRUCT type *name##_RB_NFIND(SYS_TREE_STRUCT name *, SYS_TREE_STRUCT type *);    \
398 attr SYS_TREE_STRUCT type *name##_RB_NEXT(SYS_TREE_STRUCT type *);            \
399 attr SYS_TREE_STRUCT type *name##_RB_PREV(SYS_TREE_STRUCT type *);            \
400 attr SYS_TREE_STRUCT type *name##_RB_MINMAX(SYS_TREE_STRUCT name *, int);         \
401                                     \
402 
403 /* Main rb operation.
404  * Moves node close to the key of elm to top
405  */
406 #define RB_GENERATE(name, type, field, cmp)             \
407     RB_GENERATE_INTERNAL(name, type, field, cmp,)
408 #define RB_GENERATE_STATIC(name, type, field, cmp)          \
409     RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
410 #define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)      \
411 attr void                               \
412 name##_RB_INSERT_COLOR(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)     \
413 {                                   \
414     SYS_TREE_STRUCT type *parent, *gparent, *tmp;                \
415     while ((parent = RB_PARENT(elm, field)) != NULL &&      \
416         RB_COLOR(parent, field) == RB_RED) {            \
417         gparent = RB_PARENT(parent, field);         \
418         if (parent == RB_LEFT(gparent, field)) {        \
419             tmp = RB_RIGHT(gparent, field);         \
420             if (tmp && RB_COLOR(tmp, field) == RB_RED) {    \
421                 RB_COLOR(tmp, field) = RB_BLACK;    \
422                 RB_SET_BLACKRED(parent, gparent, field);\
423                 elm = gparent;              \
424                 continue;               \
425             }                       \
426             if (RB_RIGHT(parent, field) == elm) {       \
427                 RB_ROTATE_LEFT(head, parent, tmp, field);\
428                 tmp = parent;               \
429                 parent = elm;               \
430                 elm = tmp;              \
431             }                       \
432             RB_SET_BLACKRED(parent, gparent, field);    \
433             RB_ROTATE_RIGHT(head, gparent, tmp, field); \
434         } else {                        \
435             tmp = RB_LEFT(gparent, field);          \
436             if (tmp && RB_COLOR(tmp, field) == RB_RED) {    \
437                 RB_COLOR(tmp, field) = RB_BLACK;    \
438                 RB_SET_BLACKRED(parent, gparent, field);\
439                 elm = gparent;              \
440                 continue;               \
441             }                       \
442             if (RB_LEFT(parent, field) == elm) {        \
443                 RB_ROTATE_RIGHT(head, parent, tmp, field);\
444                 tmp = parent;               \
445                 parent = elm;               \
446                 elm = tmp;              \
447             }                       \
448             RB_SET_BLACKRED(parent, gparent, field);    \
449             RB_ROTATE_LEFT(head, gparent, tmp, field);  \
450         }                           \
451     }                               \
452     RB_COLOR(head->rbh_root, field) = RB_BLACK;         \
453 }                                   \
454                                     \
455 attr void                               \
456 name##_RB_REMOVE_COLOR(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *parent, SYS_TREE_STRUCT type *elm) \
457 {                                   \
458     SYS_TREE_STRUCT type *tmp;                       \
459     while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
460         elm != RB_ROOT(head)) {                 \
461         if (RB_LEFT(parent, field) == elm) {            \
462             tmp = RB_RIGHT(parent, field);          \
463             if (RB_COLOR(tmp, field) == RB_RED) {       \
464                 RB_SET_BLACKRED(tmp, parent, field);    \
465                 RB_ROTATE_LEFT(head, parent, tmp, field);\
466                 tmp = RB_RIGHT(parent, field);      \
467             }                       \
468             if ((RB_LEFT(tmp, field) == NULL ||     \
469                 RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
470                 (RB_RIGHT(tmp, field) == NULL ||        \
471                 RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
472                 RB_COLOR(tmp, field) = RB_RED;      \
473                 elm = parent;               \
474                 parent = RB_PARENT(elm, field);     \
475             } else {                    \
476                 if (RB_RIGHT(tmp, field) == NULL || \
477                     RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
478                     SYS_TREE_STRUCT type *oleft;     \
479                     if ((oleft = RB_LEFT(tmp, field)) \
480                         != NULL)            \
481                         RB_COLOR(oleft, field) = RB_BLACK;\
482                     RB_COLOR(tmp, field) = RB_RED;  \
483                     RB_ROTATE_RIGHT(head, tmp, oleft, field);\
484                     tmp = RB_RIGHT(parent, field);  \
485                 }                   \
486                 RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
487                 RB_COLOR(parent, field) = RB_BLACK; \
488                 if (RB_RIGHT(tmp, field))       \
489                     RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
490                 RB_ROTATE_LEFT(head, parent, tmp, field);\
491                 elm = RB_ROOT(head);            \
492                 break;                  \
493             }                       \
494         } else {                        \
495             tmp = RB_LEFT(parent, field);           \
496             if (RB_COLOR(tmp, field) == RB_RED) {       \
497                 RB_SET_BLACKRED(tmp, parent, field);    \
498                 RB_ROTATE_RIGHT(head, parent, tmp, field);\
499                 tmp = RB_LEFT(parent, field);       \
500             }                       \
501             if ((RB_LEFT(tmp, field) == NULL ||     \
502                 RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
503                 (RB_RIGHT(tmp, field) == NULL ||        \
504                 RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
505                 RB_COLOR(tmp, field) = RB_RED;      \
506                 elm = parent;               \
507                 parent = RB_PARENT(elm, field);     \
508             } else {                    \
509                 if (RB_LEFT(tmp, field) == NULL ||  \
510                     RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
511                     SYS_TREE_STRUCT type *oright;        \
512                     if ((oright = RB_RIGHT(tmp, field)) \
513                         != NULL)            \
514                         RB_COLOR(oright, field) = RB_BLACK;\
515                     RB_COLOR(tmp, field) = RB_RED;  \
516                     RB_ROTATE_LEFT(head, tmp, oright, field);\
517                     tmp = RB_LEFT(parent, field);   \
518                 }                   \
519                 RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
520                 RB_COLOR(parent, field) = RB_BLACK; \
521                 if (RB_LEFT(tmp, field))        \
522                     RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
523                 RB_ROTATE_RIGHT(head, parent, tmp, field);\
524                 elm = RB_ROOT(head);            \
525                 break;                  \
526             }                       \
527         }                           \
528     }                               \
529     if (elm)                            \
530         RB_COLOR(elm, field) = RB_BLACK;            \
531 }                                   \
532                                     \
533 attr SYS_TREE_STRUCT type *                          \
534 name##_RB_REMOVE(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)           \
535 {                                   \
536     SYS_TREE_STRUCT type *child, *parent, *old = elm;            \
537     int color;                          \
538     if (RB_LEFT(elm, field) == NULL)                \
539         child = RB_RIGHT(elm, field);               \
540     else if (RB_RIGHT(elm, field) == NULL)              \
541         child = RB_LEFT(elm, field);                \
542     else {                              \
543         SYS_TREE_STRUCT type *left;                  \
544         elm = RB_RIGHT(elm, field);             \
545         while ((left = RB_LEFT(elm, field)) != NULL)        \
546             elm = left;                 \
547         child = RB_RIGHT(elm, field);               \
548         parent = RB_PARENT(elm, field);             \
549         color = RB_COLOR(elm, field);               \
550         if (child)                      \
551             RB_PARENT(child, field) = parent;       \
552         if (parent) {                       \
553             if (RB_LEFT(parent, field) == elm)      \
554                 RB_LEFT(parent, field) = child;     \
555             else                        \
556                 RB_RIGHT(parent, field) = child;    \
557             RB_AUGMENT(parent);             \
558         } else                          \
559             RB_ROOT(head) = child;              \
560         if (RB_PARENT(elm, field) == old)           \
561             parent = elm;                   \
562         (elm)->field = (old)->field;                \
563         if (RB_PARENT(old, field)) {                \
564             if (RB_LEFT(RB_PARENT(old, field), field) == old)\
565                 RB_LEFT(RB_PARENT(old, field), field) = elm;\
566             else                        \
567                 RB_RIGHT(RB_PARENT(old, field), field) = elm;\
568             RB_AUGMENT(RB_PARENT(old, field));      \
569         } else                          \
570             RB_ROOT(head) = elm;                \
571         RB_PARENT(RB_LEFT(old, field), field) = elm;        \
572         if (RB_RIGHT(old, field))               \
573             RB_PARENT(RB_RIGHT(old, field), field) = elm;   \
574         if (parent) {                       \
575             left = parent;                  \
576             do {                        \
577                 RB_AUGMENT(left);           \
578             } while ((left = RB_PARENT(left, field)) != NULL); \
579         }                           \
580         goto color;                     \
581     }                               \
582     parent = RB_PARENT(elm, field);                 \
583     color = RB_COLOR(elm, field);                   \
584     if (child)                          \
585         RB_PARENT(child, field) = parent;           \
586     if (parent) {                           \
587         if (RB_LEFT(parent, field) == elm)          \
588             RB_LEFT(parent, field) = child;         \
589         else                            \
590             RB_RIGHT(parent, field) = child;        \
591         RB_AUGMENT(parent);                 \
592     } else                              \
593         RB_ROOT(head) = child;                  \
594 color:                                  \
595     if (color == RB_BLACK)                      \
596         name##_RB_REMOVE_COLOR(head, parent, child);        \
597     return (old);                           \
598 }                                   \
599                                     \
600 /* Inserts a node into the RB tree */                   \
601 attr SYS_TREE_STRUCT type *                          \
602 name##_RB_INSERT(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)           \
603 {                                   \
604     SYS_TREE_STRUCT type *tmp;                       \
605     SYS_TREE_STRUCT type *parent = NULL;                 \
606     int comp = 0;                           \
607     tmp = RB_ROOT(head);                        \
608     while (tmp) {                           \
609         parent = tmp;                       \
610         comp = (cmp)(elm, parent);              \
611         if (comp < 0)                       \
612             tmp = RB_LEFT(tmp, field);          \
613         else if (comp > 0)                  \
614             tmp = RB_RIGHT(tmp, field);         \
615         else                            \
616             return (tmp);                   \
617     }                               \
618     RB_SET(elm, parent, field);                 \
619     if (parent != NULL) {                       \
620         if (comp < 0)                       \
621             RB_LEFT(parent, field) = elm;           \
622         else                            \
623             RB_RIGHT(parent, field) = elm;          \
624         RB_AUGMENT(parent);                 \
625     } else                              \
626         RB_ROOT(head) = elm;                    \
627     name##_RB_INSERT_COLOR(head, elm);              \
628     return (NULL);                          \
629 }                                   \
630                                     \
631 /* Finds the node with the same key as elm */               \
632 attr SYS_TREE_STRUCT type *                          \
633 name##_RB_FIND(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)         \
634 {                                   \
635     SYS_TREE_STRUCT type *tmp = RB_ROOT(head);               \
636     int comp;                           \
637     while (tmp) {                           \
638         comp = cmp(elm, tmp);                   \
639         if (comp < 0)                       \
640             tmp = RB_LEFT(tmp, field);          \
641         else if (comp > 0)                  \
642             tmp = RB_RIGHT(tmp, field);         \
643         else                            \
644             return (tmp);                   \
645     }                               \
646     return (NULL);                          \
647 }                                   \
648                                     \
649 /* Finds the first node greater than or equal to the search key */  \
650 attr SYS_TREE_STRUCT type *                          \
651 name##_RB_NFIND(SYS_TREE_STRUCT name *head, SYS_TREE_STRUCT type *elm)            \
652 {                                   \
653     SYS_TREE_STRUCT type *tmp = RB_ROOT(head);               \
654     SYS_TREE_STRUCT type *res = NULL;                    \
655     int comp;                           \
656     while (tmp) {                           \
657         comp = cmp(elm, tmp);                   \
658         if (comp < 0) {                     \
659             res = tmp;                  \
660             tmp = RB_LEFT(tmp, field);          \
661         }                           \
662         else if (comp > 0)                  \
663             tmp = RB_RIGHT(tmp, field);         \
664         else                            \
665             return (tmp);                   \
666     }                               \
667     return (res);                           \
668 }                                   \
669                                     \
670 /* ARGSUSED */                              \
671 attr SYS_TREE_STRUCT type *                          \
672 name##_RB_NEXT(SYS_TREE_STRUCT type *elm)                    \
673 {                                   \
674     if (RB_RIGHT(elm, field)) {                 \
675         elm = RB_RIGHT(elm, field);             \
676         while (RB_LEFT(elm, field))             \
677             elm = RB_LEFT(elm, field);          \
678     } else {                            \
679         if (RB_PARENT(elm, field) &&                \
680             (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
681             elm = RB_PARENT(elm, field);            \
682         else {                          \
683             while (RB_PARENT(elm, field) &&         \
684                 (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
685                 elm = RB_PARENT(elm, field);        \
686             elm = RB_PARENT(elm, field);            \
687         }                           \
688     }                               \
689     return (elm);                           \
690 }                                   \
691                                     \
692 /* ARGSUSED */                              \
693 attr SYS_TREE_STRUCT type *                          \
694 name##_RB_PREV(SYS_TREE_STRUCT type *elm)                    \
695 {                                   \
696     if (RB_LEFT(elm, field)) {                  \
697         elm = RB_LEFT(elm, field);              \
698         while (RB_RIGHT(elm, field))                \
699             elm = RB_RIGHT(elm, field);         \
700     } else {                            \
701         if (RB_PARENT(elm, field) &&                \
702             (elm == RB_RIGHT(RB_PARENT(elm, field), field)))    \
703             elm = RB_PARENT(elm, field);            \
704         else {                          \
705             while (RB_PARENT(elm, field) &&         \
706                 (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
707                 elm = RB_PARENT(elm, field);        \
708             elm = RB_PARENT(elm, field);            \
709         }                           \
710     }                               \
711     return (elm);                           \
712 }                                   \
713                                     \
714 attr SYS_TREE_STRUCT type *                          \
715 name##_RB_MINMAX(SYS_TREE_STRUCT name *head, int val)                \
716 {                                   \
717     SYS_TREE_STRUCT type *tmp = RB_ROOT(head);               \
718     SYS_TREE_STRUCT type *parent = NULL;                 \
719     while (tmp) {                           \
720         parent = tmp;                       \
721         if (val < 0)                        \
722             tmp = RB_LEFT(tmp, field);          \
723         else                            \
724             tmp = RB_RIGHT(tmp, field);         \
725     }                               \
726     return (parent);                        \
727 }
728 
729 #define RB_NEGINF   -1
730 #define RB_INF  1
731 
732 #define RB_INSERT(name, x, y)   name##_RB_INSERT(x, y)
733 #define RB_REMOVE(name, x, y)   name##_RB_REMOVE(x, y)
734 #define RB_FIND(name, x, y) name##_RB_FIND(x, y)
735 #define RB_NFIND(name, x, y)    name##_RB_NFIND(x, y)
736 #define RB_NEXT(name, x, y) name##_RB_NEXT(y)
737 #define RB_PREV(name, x, y) name##_RB_PREV(y)
738 #define RB_MIN(name, x)     name##_RB_MINMAX(x, RB_NEGINF)
739 #define RB_MAX(name, x)     name##_RB_MINMAX(x, RB_INF)
740 
741 #define RB_FOREACH(x, name, head)                   \
742     for ((x) = RB_MIN(name, head);                  \
743          (x) != NULL;                       \
744          (x) = name##_RB_NEXT(x))
745 
746 #define RB_FOREACH_FROM(x, name, y)                 \
747     for ((x) = (y);                         \
748         ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL);    \
749          (x) = (y))
750 
751 #define RB_FOREACH_SAFE(x, name, head, y)               \
752     for ((x) = RB_MIN(name, head);                  \
753         ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL);    \
754          (x) = (y))
755 
756 #define RB_FOREACH_REVERSE(x, name, head)               \
757     for ((x) = RB_MAX(name, head);                  \
758          (x) != NULL;                       \
759          (x) = name##_RB_PREV(x))
760 
761 #define RB_FOREACH_REVERSE_FROM(x, name, y)             \
762     for ((x) = (y);                         \
763         ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL);    \
764          (x) = (y))
765 
766 #define RB_FOREACH_REVERSE_SAFE(x, name, head, y)           \
767     for ((x) = RB_MAX(name, head);                  \
768         ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL);    \
769          (x) = (y))
770 
771 #endif  /* _SYS_TREE_H_ */
772