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