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