memory/mozjemalloc/rb.h

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

     1 /******************************************************************************
     2  *
     3  * Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
     4  * All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions
     8  * are met:
     9  * 1. Redistributions of source code must retain the above copyright
    10  *    notice(s), this list of conditions and the following disclaimer
    11  *    unmodified other than the allowable addition of one or more
    12  *    copyright notices.
    13  * 2. Redistributions in binary form must reproduce the above copyright
    14  *    notice(s), this list of conditions and the following disclaimer in
    15  *    the documentation and/or other materials provided with the
    16  *    distribution.
    17  *
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
    19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
    22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
    25  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
    27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    29  *
    30  ******************************************************************************
    31  *
    32  * cpp macro implementation of left-leaning red-black trees.
    33  *
    34  * Usage:
    35  *
    36  *   (Optional.)
    37  *   #define SIZEOF_PTR ...
    38  *   #define SIZEOF_PTR_2POW ...
    39  *   #define RB_NO_C99_VARARRAYS
    40  *
    41  *   (Optional, see assert(3).)
    42  *   #define NDEBUG
    43  *
    44  *   (Required.)
    45  *   #include <assert.h>
    46  *   #include <rb.h>
    47  *   ...
    48  *
    49  * All operations are done non-recursively.  Parent pointers are not used, and
    50  * color bits are stored in the least significant bit of right-child pointers,
    51  * thus making node linkage as compact as is possible for red-black trees.
    52  *
    53  * Some macros use a comparison function pointer, which is expected to have the
    54  * following prototype:
    55  *
    56  *   int (a_cmp *)(a_type *a_node, a_type *a_other);
    57  *                         ^^^^^^
    58  *                      or a_key
    59  *
    60  * Interpretation of comparision function return values:
    61  *
    62  *   -1 : a_node <  a_other
    63  *    0 : a_node == a_other
    64  *    1 : a_node >  a_other
    65  *
    66  * In all cases, the a_node or a_key macro argument is the first argument to the
    67  * comparison function, which makes it possible to write comparison functions
    68  * that treat the first argument specially.
    69  *
    70  ******************************************************************************/
    72 #ifndef RB_H_
    73 #define	RB_H_
    75 #if 0
    76 #include <sys/cdefs.h>
    77 __FBSDID("$FreeBSD: head/lib/libc/stdlib/rb.h 178995 2008-05-14 18:33:13Z jasone $");
    78 #endif
    80 /* Node structure. */
    81 #define	rb_node(a_type)							\
    82 struct {								\
    83     a_type *rbn_left;							\
    84     a_type *rbn_right_red;						\
    85 }
    87 /* Root structure. */
    88 #define	rb_tree(a_type)							\
    89 struct {								\
    90     a_type *rbt_root;							\
    91     a_type rbt_nil;							\
    92 }
    94 /* Left accessors. */
    95 #define	rbp_left_get(a_type, a_field, a_node)				\
    96     ((a_node)->a_field.rbn_left)
    97 #define	rbp_left_set(a_type, a_field, a_node, a_left) do {		\
    98     (a_node)->a_field.rbn_left = a_left;				\
    99 } while (0)
   101 /* Right accessors. */
   102 #define	rbp_right_get(a_type, a_field, a_node)				\
   103     ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red)		\
   104       & ((ssize_t)-2)))
   105 #define	rbp_right_set(a_type, a_field, a_node, a_right) do {		\
   106     (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right)	\
   107       | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1)));	\
   108 } while (0)
   110 /* Color accessors. */
   111 #define	rbp_red_get(a_type, a_field, a_node)				\
   112     ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red)		\
   113       & ((size_t)1)))
   114 #define	rbp_color_set(a_type, a_field, a_node, a_red) do {		\
   115     (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t)		\
   116       (a_node)->a_field.rbn_right_red) & ((ssize_t)-2))			\
   117       | ((ssize_t)a_red));						\
   118 } while (0)
   119 #define	rbp_red_set(a_type, a_field, a_node) do {			\
   120     (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t)		\
   121       (a_node)->a_field.rbn_right_red) | ((size_t)1));			\
   122 } while (0)
   123 #define	rbp_black_set(a_type, a_field, a_node) do {			\
   124     (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t)		\
   125       (a_node)->a_field.rbn_right_red) & ((ssize_t)-2));		\
   126 } while (0)
   128 /* Node initializer. */
   129 #define	rbp_node_new(a_type, a_field, a_tree, a_node) do {		\
   130     rbp_left_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil);	\
   131     rbp_right_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil);	\
   132     rbp_red_set(a_type, a_field, (a_node));				\
   133 } while (0)
   135 /* Tree initializer. */
   136 #define	rb_new(a_type, a_field, a_tree) do {				\
   137     (a_tree)->rbt_root = &(a_tree)->rbt_nil;				\
   138     rbp_node_new(a_type, a_field, a_tree, &(a_tree)->rbt_nil);		\
   139     rbp_black_set(a_type, a_field, &(a_tree)->rbt_nil);			\
   140 } while (0)
   142 /* Tree operations. */
   143 #define	rbp_black_height(a_type, a_field, a_tree, r_height) do {	\
   144     a_type *rbp_bh_t;							\
   145     for (rbp_bh_t = (a_tree)->rbt_root, (r_height) = 0;			\
   146       rbp_bh_t != &(a_tree)->rbt_nil;					\
   147       rbp_bh_t = rbp_left_get(a_type, a_field, rbp_bh_t)) {		\
   148 	if (rbp_red_get(a_type, a_field, rbp_bh_t) == false) {		\
   149 	    (r_height)++;						\
   150 	}								\
   151     }									\
   152 } while (0)
   154 #define	rbp_first(a_type, a_field, a_tree, a_root, r_node) do {		\
   155     for ((r_node) = (a_root);						\
   156       rbp_left_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil;	\
   157       (r_node) = rbp_left_get(a_type, a_field, (r_node))) {		\
   158     }									\
   159 } while (0)
   161 #define	rbp_last(a_type, a_field, a_tree, a_root, r_node) do {		\
   162     for ((r_node) = (a_root);						\
   163       rbp_right_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil;	\
   164       (r_node) = rbp_right_get(a_type, a_field, (r_node))) {		\
   165     }									\
   166 } while (0)
   168 #define	rbp_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {	\
   169     if (rbp_right_get(a_type, a_field, (a_node))			\
   170       != &(a_tree)->rbt_nil) {						\
   171 	rbp_first(a_type, a_field, a_tree, rbp_right_get(a_type,	\
   172 	  a_field, (a_node)), (r_node));				\
   173     } else {								\
   174 	a_type *rbp_n_t = (a_tree)->rbt_root;				\
   175 	assert(rbp_n_t != &(a_tree)->rbt_nil);				\
   176 	(r_node) = &(a_tree)->rbt_nil;					\
   177 	while (true) {							\
   178 	    int rbp_n_cmp = (a_cmp)((a_node), rbp_n_t);			\
   179 	    if (rbp_n_cmp < 0) {					\
   180 		(r_node) = rbp_n_t;					\
   181 		rbp_n_t = rbp_left_get(a_type, a_field, rbp_n_t);	\
   182 	    } else if (rbp_n_cmp > 0) {					\
   183 		rbp_n_t = rbp_right_get(a_type, a_field, rbp_n_t);	\
   184 	    } else {							\
   185 		break;							\
   186 	    }								\
   187 	    assert(rbp_n_t != &(a_tree)->rbt_nil);			\
   188 	}								\
   189     }									\
   190 } while (0)
   192 #define	rbp_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {	\
   193     if (rbp_left_get(a_type, a_field, (a_node)) != &(a_tree)->rbt_nil) {\
   194 	rbp_last(a_type, a_field, a_tree, rbp_left_get(a_type,		\
   195 	  a_field, (a_node)), (r_node));				\
   196     } else {								\
   197 	a_type *rbp_p_t = (a_tree)->rbt_root;				\
   198 	assert(rbp_p_t != &(a_tree)->rbt_nil);				\
   199 	(r_node) = &(a_tree)->rbt_nil;					\
   200 	while (true) {							\
   201 	    int rbp_p_cmp = (a_cmp)((a_node), rbp_p_t);			\
   202 	    if (rbp_p_cmp < 0) {					\
   203 		rbp_p_t = rbp_left_get(a_type, a_field, rbp_p_t);	\
   204 	    } else if (rbp_p_cmp > 0) {					\
   205 		(r_node) = rbp_p_t;					\
   206 		rbp_p_t = rbp_right_get(a_type, a_field, rbp_p_t);	\
   207 	    } else {							\
   208 		break;							\
   209 	    }								\
   210 	    assert(rbp_p_t != &(a_tree)->rbt_nil);			\
   211 	}								\
   212     }									\
   213 } while (0)
   215 #define	rb_first(a_type, a_field, a_tree, r_node) do {			\
   216     rbp_first(a_type, a_field, a_tree, (a_tree)->rbt_root, (r_node));	\
   217     if ((r_node) == &(a_tree)->rbt_nil) {				\
   218 	(r_node) = NULL;						\
   219     }									\
   220 } while (0)
   222 #define	rb_last(a_type, a_field, a_tree, r_node) do {			\
   223     rbp_last(a_type, a_field, a_tree, (a_tree)->rbt_root, r_node);	\
   224     if ((r_node) == &(a_tree)->rbt_nil) {				\
   225 	(r_node) = NULL;						\
   226     }									\
   227 } while (0)
   229 #define	rb_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {	\
   230     rbp_next(a_type, a_field, a_cmp, a_tree, (a_node), (r_node));	\
   231     if ((r_node) == &(a_tree)->rbt_nil) {				\
   232 	(r_node) = NULL;						\
   233     }									\
   234 } while (0)
   236 #define	rb_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do {	\
   237     rbp_prev(a_type, a_field, a_cmp, a_tree, (a_node), (r_node));	\
   238     if ((r_node) == &(a_tree)->rbt_nil) {				\
   239 	(r_node) = NULL;						\
   240     }									\
   241 } while (0)
   243 #define	rb_search(a_type, a_field, a_cmp, a_tree, a_key, r_node) do {	\
   244     int rbp_se_cmp;							\
   245     (r_node) = (a_tree)->rbt_root;					\
   246     while ((r_node) != &(a_tree)->rbt_nil				\
   247       && (rbp_se_cmp = (a_cmp)((a_key), (r_node))) != 0) {		\
   248 	if (rbp_se_cmp < 0) {						\
   249 	    (r_node) = rbp_left_get(a_type, a_field, (r_node));		\
   250 	} else {							\
   251 	    (r_node) = rbp_right_get(a_type, a_field, (r_node));	\
   252 	}								\
   253     }									\
   254     if ((r_node) == &(a_tree)->rbt_nil) {				\
   255 	(r_node) = NULL;						\
   256     }									\
   257 } while (0)
   259 /*
   260  * Find a match if it exists.  Otherwise, find the next greater node, if one
   261  * exists.
   262  */
   263 #define	rb_nsearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do {	\
   264     a_type *rbp_ns_t = (a_tree)->rbt_root;				\
   265     (r_node) = NULL;							\
   266     while (rbp_ns_t != &(a_tree)->rbt_nil) {				\
   267 	int rbp_ns_cmp = (a_cmp)((a_key), rbp_ns_t);			\
   268 	if (rbp_ns_cmp < 0) {						\
   269 	    (r_node) = rbp_ns_t;					\
   270 	    rbp_ns_t = rbp_left_get(a_type, a_field, rbp_ns_t);		\
   271 	} else if (rbp_ns_cmp > 0) {					\
   272 	    rbp_ns_t = rbp_right_get(a_type, a_field, rbp_ns_t);	\
   273 	} else {							\
   274 	    (r_node) = rbp_ns_t;					\
   275 	    break;							\
   276 	}								\
   277     }									\
   278 } while (0)
   280 /*
   281  * Find a match if it exists.  Otherwise, find the previous lesser node, if one
   282  * exists.
   283  */
   284 #define	rb_psearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do {	\
   285     a_type *rbp_ps_t = (a_tree)->rbt_root;				\
   286     (r_node) = NULL;							\
   287     while (rbp_ps_t != &(a_tree)->rbt_nil) {				\
   288 	int rbp_ps_cmp = (a_cmp)((a_key), rbp_ps_t);			\
   289 	if (rbp_ps_cmp < 0) {						\
   290 	    rbp_ps_t = rbp_left_get(a_type, a_field, rbp_ps_t);		\
   291 	} else if (rbp_ps_cmp > 0) {					\
   292 	    (r_node) = rbp_ps_t;					\
   293 	    rbp_ps_t = rbp_right_get(a_type, a_field, rbp_ps_t);	\
   294 	} else {							\
   295 	    (r_node) = rbp_ps_t;					\
   296 	    break;							\
   297 	}								\
   298     }									\
   299 } while (0)
   301 #define	rbp_rotate_left(a_type, a_field, a_node, r_node) do {		\
   302     (r_node) = rbp_right_get(a_type, a_field, (a_node));		\
   303     rbp_right_set(a_type, a_field, (a_node),				\
   304       rbp_left_get(a_type, a_field, (r_node)));				\
   305     rbp_left_set(a_type, a_field, (r_node), (a_node));			\
   306 } while (0)
   308 #define	rbp_rotate_right(a_type, a_field, a_node, r_node) do {		\
   309     (r_node) = rbp_left_get(a_type, a_field, (a_node));			\
   310     rbp_left_set(a_type, a_field, (a_node),				\
   311       rbp_right_get(a_type, a_field, (r_node)));			\
   312     rbp_right_set(a_type, a_field, (r_node), (a_node));			\
   313 } while (0)
   315 #define	rbp_lean_left(a_type, a_field, a_node, r_node) do {		\
   316     bool rbp_ll_red;							\
   317     rbp_rotate_left(a_type, a_field, (a_node), (r_node));		\
   318     rbp_ll_red = rbp_red_get(a_type, a_field, (a_node));		\
   319     rbp_color_set(a_type, a_field, (r_node), rbp_ll_red);		\
   320     rbp_red_set(a_type, a_field, (a_node));				\
   321 } while (0)
   323 #define	rbp_lean_right(a_type, a_field, a_node, r_node) do {		\
   324     bool rbp_lr_red;							\
   325     rbp_rotate_right(a_type, a_field, (a_node), (r_node));		\
   326     rbp_lr_red = rbp_red_get(a_type, a_field, (a_node));		\
   327     rbp_color_set(a_type, a_field, (r_node), rbp_lr_red);		\
   328     rbp_red_set(a_type, a_field, (a_node));				\
   329 } while (0)
   331 #define	rbp_move_red_left(a_type, a_field, a_node, r_node) do {		\
   332     a_type *rbp_mrl_t, *rbp_mrl_u;					\
   333     rbp_mrl_t = rbp_left_get(a_type, a_field, (a_node));		\
   334     rbp_red_set(a_type, a_field, rbp_mrl_t);				\
   335     rbp_mrl_t = rbp_right_get(a_type, a_field, (a_node));		\
   336     rbp_mrl_u = rbp_left_get(a_type, a_field, rbp_mrl_t);		\
   337     if (rbp_red_get(a_type, a_field, rbp_mrl_u)) {			\
   338 	rbp_rotate_right(a_type, a_field, rbp_mrl_t, rbp_mrl_u);	\
   339 	rbp_right_set(a_type, a_field, (a_node), rbp_mrl_u);		\
   340 	rbp_rotate_left(a_type, a_field, (a_node), (r_node));		\
   341 	rbp_mrl_t = rbp_right_get(a_type, a_field, (a_node));		\
   342 	if (rbp_red_get(a_type, a_field, rbp_mrl_t)) {			\
   343 	    rbp_black_set(a_type, a_field, rbp_mrl_t);			\
   344 	    rbp_red_set(a_type, a_field, (a_node));			\
   345 	    rbp_rotate_left(a_type, a_field, (a_node), rbp_mrl_t);	\
   346 	    rbp_left_set(a_type, a_field, (r_node), rbp_mrl_t);		\
   347 	} else {							\
   348 	    rbp_black_set(a_type, a_field, (a_node));			\
   349 	}								\
   350     } else {								\
   351 	rbp_red_set(a_type, a_field, (a_node));				\
   352 	rbp_rotate_left(a_type, a_field, (a_node), (r_node));		\
   353     }									\
   354 } while (0)
   356 #define	rbp_move_red_right(a_type, a_field, a_node, r_node) do {	\
   357     a_type *rbp_mrr_t;							\
   358     rbp_mrr_t = rbp_left_get(a_type, a_field, (a_node));		\
   359     if (rbp_red_get(a_type, a_field, rbp_mrr_t)) {			\
   360 	a_type *rbp_mrr_u, *rbp_mrr_v;					\
   361 	rbp_mrr_u = rbp_right_get(a_type, a_field, rbp_mrr_t);		\
   362 	rbp_mrr_v = rbp_left_get(a_type, a_field, rbp_mrr_u);		\
   363 	if (rbp_red_get(a_type, a_field, rbp_mrr_v)) {			\
   364 	    rbp_color_set(a_type, a_field, rbp_mrr_u,			\
   365 	      rbp_red_get(a_type, a_field, (a_node)));			\
   366 	    rbp_black_set(a_type, a_field, rbp_mrr_v);			\
   367 	    rbp_rotate_left(a_type, a_field, rbp_mrr_t, rbp_mrr_u);	\
   368 	    rbp_left_set(a_type, a_field, (a_node), rbp_mrr_u);		\
   369 	    rbp_rotate_right(a_type, a_field, (a_node), (r_node));	\
   370 	    rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t);	\
   371 	    rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t);	\
   372 	} else {							\
   373 	    rbp_color_set(a_type, a_field, rbp_mrr_t,			\
   374 	      rbp_red_get(a_type, a_field, (a_node)));			\
   375 	    rbp_red_set(a_type, a_field, rbp_mrr_u);			\
   376 	    rbp_rotate_right(a_type, a_field, (a_node), (r_node));	\
   377 	    rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t);	\
   378 	    rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t);	\
   379 	}								\
   380 	rbp_red_set(a_type, a_field, (a_node));				\
   381     } else {								\
   382 	rbp_red_set(a_type, a_field, rbp_mrr_t);			\
   383 	rbp_mrr_t = rbp_left_get(a_type, a_field, rbp_mrr_t);		\
   384 	if (rbp_red_get(a_type, a_field, rbp_mrr_t)) {			\
   385 	    rbp_black_set(a_type, a_field, rbp_mrr_t);			\
   386 	    rbp_rotate_right(a_type, a_field, (a_node), (r_node));	\
   387 	    rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t);	\
   388 	    rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t);	\
   389 	} else {							\
   390 	    rbp_rotate_left(a_type, a_field, (a_node), (r_node));	\
   391 	}								\
   392     }									\
   393 } while (0)
   395 #define	rb_insert(a_type, a_field, a_cmp, a_tree, a_node) do {		\
   396     a_type rbp_i_s;							\
   397     a_type *rbp_i_g, *rbp_i_p, *rbp_i_c, *rbp_i_t, *rbp_i_u;		\
   398     int rbp_i_cmp = 0;							\
   399     rbp_i_g = &(a_tree)->rbt_nil;					\
   400     rbp_left_set(a_type, a_field, &rbp_i_s, (a_tree)->rbt_root);	\
   401     rbp_right_set(a_type, a_field, &rbp_i_s, &(a_tree)->rbt_nil);	\
   402     rbp_black_set(a_type, a_field, &rbp_i_s);				\
   403     rbp_i_p = &rbp_i_s;							\
   404     rbp_i_c = (a_tree)->rbt_root;					\
   405     /* Iteratively search down the tree for the insertion point,      */\
   406     /* splitting 4-nodes as they are encountered.  At the end of each */\
   407     /* iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down    */\
   408     /* the tree, assuming a sufficiently deep tree.                   */\
   409     while (rbp_i_c != &(a_tree)->rbt_nil) {				\
   410 	rbp_i_t = rbp_left_get(a_type, a_field, rbp_i_c);		\
   411 	rbp_i_u = rbp_left_get(a_type, a_field, rbp_i_t);		\
   412 	if (rbp_red_get(a_type, a_field, rbp_i_t)			\
   413 	  && rbp_red_get(a_type, a_field, rbp_i_u)) {			\
   414 	    /* rbp_i_c is the top of a logical 4-node, so split it.   */\
   415 	    /* This iteration does not move down the tree, due to the */\
   416 	    /* disruptiveness of node splitting.                      */\
   417 	    /*                                                        */\
   418 	    /* Rotate right.                                          */\
   419 	    rbp_rotate_right(a_type, a_field, rbp_i_c, rbp_i_t);	\
   420 	    /* Pass red links up one level.                           */\
   421 	    rbp_i_u = rbp_left_get(a_type, a_field, rbp_i_t);		\
   422 	    rbp_black_set(a_type, a_field, rbp_i_u);			\
   423 	    if (rbp_left_get(a_type, a_field, rbp_i_p) == rbp_i_c) {	\
   424 		rbp_left_set(a_type, a_field, rbp_i_p, rbp_i_t);	\
   425 		rbp_i_c = rbp_i_t;					\
   426 	    } else {							\
   427 		/* rbp_i_c was the right child of rbp_i_p, so rotate  */\
   428 		/* left in order to maintain the left-leaning         */\
   429 		/* invariant.                                         */\
   430 		assert(rbp_right_get(a_type, a_field, rbp_i_p)		\
   431 		  == rbp_i_c);						\
   432 		rbp_right_set(a_type, a_field, rbp_i_p, rbp_i_t);	\
   433 		rbp_lean_left(a_type, a_field, rbp_i_p, rbp_i_u);	\
   434 		if (rbp_left_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\
   435 		    rbp_left_set(a_type, a_field, rbp_i_g, rbp_i_u);	\
   436 		} else {						\
   437 		    assert(rbp_right_get(a_type, a_field, rbp_i_g)	\
   438 		      == rbp_i_p);					\
   439 		    rbp_right_set(a_type, a_field, rbp_i_g, rbp_i_u);	\
   440 		}							\
   441 		rbp_i_p = rbp_i_u;					\
   442 		rbp_i_cmp = (a_cmp)((a_node), rbp_i_p);			\
   443 		if (rbp_i_cmp < 0) {					\
   444 		    rbp_i_c = rbp_left_get(a_type, a_field, rbp_i_p);	\
   445 		} else {						\
   446 		    assert(rbp_i_cmp > 0);				\
   447 		    rbp_i_c = rbp_right_get(a_type, a_field, rbp_i_p);	\
   448 		}							\
   449 		continue;						\
   450 	    }								\
   451 	}								\
   452 	rbp_i_g = rbp_i_p;						\
   453 	rbp_i_p = rbp_i_c;						\
   454 	rbp_i_cmp = (a_cmp)((a_node), rbp_i_c);				\
   455 	if (rbp_i_cmp < 0) {						\
   456 	    rbp_i_c = rbp_left_get(a_type, a_field, rbp_i_c);		\
   457 	} else {							\
   458 	    assert(rbp_i_cmp > 0);					\
   459 	    rbp_i_c = rbp_right_get(a_type, a_field, rbp_i_c);		\
   460 	}								\
   461     }									\
   462     /* rbp_i_p now refers to the node under which to insert.          */\
   463     rbp_node_new(a_type, a_field, a_tree, (a_node));			\
   464     if (rbp_i_cmp > 0) {						\
   465 	rbp_right_set(a_type, a_field, rbp_i_p, (a_node));		\
   466 	rbp_lean_left(a_type, a_field, rbp_i_p, rbp_i_t);		\
   467 	if (rbp_left_get(a_type, a_field, rbp_i_g) == rbp_i_p) {	\
   468 	    rbp_left_set(a_type, a_field, rbp_i_g, rbp_i_t);		\
   469 	} else if (rbp_right_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\
   470 	    rbp_right_set(a_type, a_field, rbp_i_g, rbp_i_t);		\
   471 	}								\
   472     } else {								\
   473 	rbp_left_set(a_type, a_field, rbp_i_p, (a_node));		\
   474     }									\
   475     /* Update the root and make sure that it is black.                */\
   476     (a_tree)->rbt_root = rbp_left_get(a_type, a_field, &rbp_i_s);	\
   477     rbp_black_set(a_type, a_field, (a_tree)->rbt_root);			\
   478 } while (0)
   480 #define	rb_remove(a_type, a_field, a_cmp, a_tree, a_node) do {		\
   481     a_type rbp_r_s;							\
   482     a_type *rbp_r_p, *rbp_r_c, *rbp_r_xp, *rbp_r_t, *rbp_r_u;		\
   483     int rbp_r_cmp;							\
   484     rbp_left_set(a_type, a_field, &rbp_r_s, (a_tree)->rbt_root);	\
   485     rbp_right_set(a_type, a_field, &rbp_r_s, &(a_tree)->rbt_nil);	\
   486     rbp_black_set(a_type, a_field, &rbp_r_s);				\
   487     rbp_r_p = &rbp_r_s;							\
   488     rbp_r_c = (a_tree)->rbt_root;					\
   489     rbp_r_xp = &(a_tree)->rbt_nil;					\
   490     /* Iterate down the tree, but always transform 2-nodes to 3- or   */\
   491     /* 4-nodes in order to maintain the invariant that the current    */\
   492     /* node is not a 2-node.  This allows simple deletion once a leaf */\
   493     /* is reached.  Handle the root specially though, since there may */\
   494     /* be no way to convert it from a 2-node to a 3-node.             */\
   495     rbp_r_cmp = (a_cmp)((a_node), rbp_r_c);				\
   496     if (rbp_r_cmp < 0) {						\
   497 	rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c);		\
   498 	rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t);		\
   499 	if (rbp_red_get(a_type, a_field, rbp_r_t) == false		\
   500 	  && rbp_red_get(a_type, a_field, rbp_r_u) == false) {		\
   501 	    /* Apply standard transform to prepare for left move.     */\
   502 	    rbp_move_red_left(a_type, a_field, rbp_r_c, rbp_r_t);	\
   503 	    rbp_black_set(a_type, a_field, rbp_r_t);			\
   504 	    rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);		\
   505 	    rbp_r_c = rbp_r_t;						\
   506 	} else {							\
   507 	    /* Move left.                                             */\
   508 	    rbp_r_p = rbp_r_c;						\
   509 	    rbp_r_c = rbp_left_get(a_type, a_field, rbp_r_c);		\
   510 	}								\
   511     } else {								\
   512 	if (rbp_r_cmp == 0) {						\
   513 	    assert((a_node) == rbp_r_c);				\
   514 	    if (rbp_right_get(a_type, a_field, rbp_r_c)			\
   515 	      == &(a_tree)->rbt_nil) {					\
   516 		/* Delete root node (which is also a leaf node).      */\
   517 		if (rbp_left_get(a_type, a_field, rbp_r_c)		\
   518 		  != &(a_tree)->rbt_nil) {				\
   519 		    rbp_lean_right(a_type, a_field, rbp_r_c, rbp_r_t);	\
   520 		    rbp_right_set(a_type, a_field, rbp_r_t,		\
   521 		      &(a_tree)->rbt_nil);				\
   522 		} else {						\
   523 		    rbp_r_t = &(a_tree)->rbt_nil;			\
   524 		}							\
   525 		rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);	\
   526 	    } else {							\
   527 		/* This is the node we want to delete, but we will    */\
   528 		/* instead swap it with its successor and delete the  */\
   529 		/* successor.  Record enough information to do the    */\
   530 		/* swap later.  rbp_r_xp is the a_node's parent.      */\
   531 		rbp_r_xp = rbp_r_p;					\
   532 		rbp_r_cmp = 1; /* Note that deletion is incomplete.   */\
   533 	    }								\
   534 	}								\
   535 	if (rbp_r_cmp == 1) {						\
   536 	    if (rbp_red_get(a_type, a_field, rbp_left_get(a_type,	\
   537 	      a_field, rbp_right_get(a_type, a_field, rbp_r_c)))	\
   538 	      == false) {						\
   539 		rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c);	\
   540 		if (rbp_red_get(a_type, a_field, rbp_r_t)) {		\
   541 		    /* Standard transform.                            */\
   542 		    rbp_move_red_right(a_type, a_field, rbp_r_c,	\
   543 		      rbp_r_t);						\
   544 		} else {						\
   545 		    /* Root-specific transform.                       */\
   546 		    rbp_red_set(a_type, a_field, rbp_r_c);		\
   547 		    rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t);	\
   548 		    if (rbp_red_get(a_type, a_field, rbp_r_u)) {	\
   549 			rbp_black_set(a_type, a_field, rbp_r_u);	\
   550 			rbp_rotate_right(a_type, a_field, rbp_r_c,	\
   551 			  rbp_r_t);					\
   552 			rbp_rotate_left(a_type, a_field, rbp_r_c,	\
   553 			  rbp_r_u);					\
   554 			rbp_right_set(a_type, a_field, rbp_r_t,		\
   555 			  rbp_r_u);					\
   556 		    } else {						\
   557 			rbp_red_set(a_type, a_field, rbp_r_t);		\
   558 			rbp_rotate_left(a_type, a_field, rbp_r_c,	\
   559 			  rbp_r_t);					\
   560 		    }							\
   561 		}							\
   562 		rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);	\
   563 		rbp_r_c = rbp_r_t;					\
   564 	    } else {							\
   565 		/* Move right.                                        */\
   566 		rbp_r_p = rbp_r_c;					\
   567 		rbp_r_c = rbp_right_get(a_type, a_field, rbp_r_c);	\
   568 	    }								\
   569 	}								\
   570     }									\
   571     if (rbp_r_cmp != 0) {						\
   572 	while (true) {							\
   573 	    assert(rbp_r_p != &(a_tree)->rbt_nil);			\
   574 	    rbp_r_cmp = (a_cmp)((a_node), rbp_r_c);			\
   575 	    if (rbp_r_cmp < 0) {					\
   576 		rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c);	\
   577 		if (rbp_r_t == &(a_tree)->rbt_nil) {			\
   578 		    /* rbp_r_c now refers to the successor node to    */\
   579 		    /* relocate, and rbp_r_xp/a_node refer to the     */\
   580 		    /* context for the relocation.                    */\
   581 		    if (rbp_left_get(a_type, a_field, rbp_r_xp)		\
   582 		      == (a_node)) {					\
   583 			rbp_left_set(a_type, a_field, rbp_r_xp,		\
   584 			  rbp_r_c);					\
   585 		    } else {						\
   586 			assert(rbp_right_get(a_type, a_field,		\
   587 			  rbp_r_xp) == (a_node));			\
   588 			rbp_right_set(a_type, a_field, rbp_r_xp,	\
   589 			  rbp_r_c);					\
   590 		    }							\
   591 		    rbp_left_set(a_type, a_field, rbp_r_c,		\
   592 		      rbp_left_get(a_type, a_field, (a_node)));		\
   593 		    rbp_right_set(a_type, a_field, rbp_r_c,		\
   594 		      rbp_right_get(a_type, a_field, (a_node)));	\
   595 		    rbp_color_set(a_type, a_field, rbp_r_c,		\
   596 		      rbp_red_get(a_type, a_field, (a_node)));		\
   597 		    if (rbp_left_get(a_type, a_field, rbp_r_p)		\
   598 		      == rbp_r_c) {					\
   599 			rbp_left_set(a_type, a_field, rbp_r_p,		\
   600 			  &(a_tree)->rbt_nil);				\
   601 		    } else {						\
   602 			assert(rbp_right_get(a_type, a_field, rbp_r_p)	\
   603 			  == rbp_r_c);					\
   604 			rbp_right_set(a_type, a_field, rbp_r_p,		\
   605 			  &(a_tree)->rbt_nil);				\
   606 		    }							\
   607 		    break;						\
   608 		}							\
   609 		rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t);	\
   610 		if (rbp_red_get(a_type, a_field, rbp_r_t) == false	\
   611 		  && rbp_red_get(a_type, a_field, rbp_r_u) == false) {	\
   612 		    rbp_move_red_left(a_type, a_field, rbp_r_c,		\
   613 		      rbp_r_t);						\
   614 		    if (rbp_left_get(a_type, a_field, rbp_r_p)		\
   615 		      == rbp_r_c) {					\
   616 			rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
   617 		    } else {						\
   618 			rbp_right_set(a_type, a_field, rbp_r_p,		\
   619 			  rbp_r_t);					\
   620 		    }							\
   621 		    rbp_r_c = rbp_r_t;					\
   622 		} else {						\
   623 		    rbp_r_p = rbp_r_c;					\
   624 		    rbp_r_c = rbp_left_get(a_type, a_field, rbp_r_c);	\
   625 		}							\
   626 	    } else {							\
   627 		/* Check whether to delete this node (it has to be    */\
   628 		/* the correct node and a leaf node).                 */\
   629 		if (rbp_r_cmp == 0) {					\
   630 		    assert((a_node) == rbp_r_c);			\
   631 		    if (rbp_right_get(a_type, a_field, rbp_r_c)		\
   632 		      == &(a_tree)->rbt_nil) {				\
   633 			/* Delete leaf node.                          */\
   634 			if (rbp_left_get(a_type, a_field, rbp_r_c)	\
   635 			  != &(a_tree)->rbt_nil) {			\
   636 			    rbp_lean_right(a_type, a_field, rbp_r_c,	\
   637 			      rbp_r_t);					\
   638 			    rbp_right_set(a_type, a_field, rbp_r_t,	\
   639 			      &(a_tree)->rbt_nil);			\
   640 			} else {					\
   641 			    rbp_r_t = &(a_tree)->rbt_nil;		\
   642 			}						\
   643 			if (rbp_left_get(a_type, a_field, rbp_r_p)	\
   644 			  == rbp_r_c) {					\
   645 			    rbp_left_set(a_type, a_field, rbp_r_p,	\
   646 			      rbp_r_t);					\
   647 			} else {					\
   648 			    rbp_right_set(a_type, a_field, rbp_r_p,	\
   649 			      rbp_r_t);					\
   650 			}						\
   651 			break;						\
   652 		    } else {						\
   653 			/* This is the node we want to delete, but we */\
   654 			/* will instead swap it with its successor    */\
   655 			/* and delete the successor.  Record enough   */\
   656 			/* information to do the swap later.          */\
   657 			/* rbp_r_xp is a_node's parent.               */\
   658 			rbp_r_xp = rbp_r_p;				\
   659 		    }							\
   660 		}							\
   661 		rbp_r_t = rbp_right_get(a_type, a_field, rbp_r_c);	\
   662 		rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t);	\
   663 		if (rbp_red_get(a_type, a_field, rbp_r_u) == false) {	\
   664 		    rbp_move_red_right(a_type, a_field, rbp_r_c,	\
   665 		      rbp_r_t);						\
   666 		    if (rbp_left_get(a_type, a_field, rbp_r_p)		\
   667 		      == rbp_r_c) {					\
   668 			rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
   669 		    } else {						\
   670 			rbp_right_set(a_type, a_field, rbp_r_p,		\
   671 			  rbp_r_t);					\
   672 		    }							\
   673 		    rbp_r_c = rbp_r_t;					\
   674 		} else {						\
   675 		    rbp_r_p = rbp_r_c;					\
   676 		    rbp_r_c = rbp_right_get(a_type, a_field, rbp_r_c);	\
   677 		}							\
   678 	    }								\
   679 	}								\
   680     }									\
   681     /* Update root.                                                   */\
   682     (a_tree)->rbt_root = rbp_left_get(a_type, a_field, &rbp_r_s);	\
   683 } while (0)
   685 /*
   686  * The rb_wrap() macro provides a convenient way to wrap functions around the
   687  * cpp macros.  The main benefits of wrapping are that 1) repeated macro
   688  * expansion can cause code bloat, especially for rb_{insert,remove)(), and
   689  * 2) type, linkage, comparison functions, etc. need not be specified at every
   690  * call point.
   691  */
   693 #define	rb_wrap(a_attr, a_prefix, a_tree_type, a_type, a_field, a_cmp)	\
   694 a_attr void								\
   695 a_prefix##new(a_tree_type *tree) {					\
   696     rb_new(a_type, a_field, tree);					\
   697 }									\
   698 a_attr a_type *								\
   699 a_prefix##first(a_tree_type *tree) {					\
   700     a_type *ret;							\
   701     rb_first(a_type, a_field, tree, ret);				\
   702     return (ret);							\
   703 }									\
   704 a_attr a_type *								\
   705 a_prefix##last(a_tree_type *tree) {					\
   706     a_type *ret;							\
   707     rb_last(a_type, a_field, tree, ret);				\
   708     return (ret);							\
   709 }									\
   710 a_attr a_type *								\
   711 a_prefix##next(a_tree_type *tree, a_type *node) {			\
   712     a_type *ret;							\
   713     rb_next(a_type, a_field, a_cmp, tree, node, ret);			\
   714     return (ret);							\
   715 }									\
   716 a_attr a_type *								\
   717 a_prefix##prev(a_tree_type *tree, a_type *node) {			\
   718     a_type *ret;							\
   719     rb_prev(a_type, a_field, a_cmp, tree, node, ret);			\
   720     return (ret);							\
   721 }									\
   722 a_attr a_type *								\
   723 a_prefix##search(a_tree_type *tree, a_type *key) {			\
   724     a_type *ret;							\
   725     rb_search(a_type, a_field, a_cmp, tree, key, ret);			\
   726     return (ret);							\
   727 }									\
   728 a_attr a_type *								\
   729 a_prefix##nsearch(a_tree_type *tree, a_type *key) {			\
   730     a_type *ret;							\
   731     rb_nsearch(a_type, a_field, a_cmp, tree, key, ret);			\
   732     return (ret);							\
   733 }									\
   734 a_attr a_type *								\
   735 a_prefix##psearch(a_tree_type *tree, a_type *key) {			\
   736     a_type *ret;							\
   737     rb_psearch(a_type, a_field, a_cmp, tree, key, ret);			\
   738     return (ret);							\
   739 }									\
   740 a_attr void								\
   741 a_prefix##insert(a_tree_type *tree, a_type *node) {			\
   742     rb_insert(a_type, a_field, a_cmp, tree, node);			\
   743 }									\
   744 a_attr void								\
   745 a_prefix##remove(a_tree_type *tree, a_type *node) {			\
   746     rb_remove(a_type, a_field, a_cmp, tree, node);			\
   747 }
   749 /*
   750  * The iterators simulate recursion via an array of pointers that store the
   751  * current path.  This is critical to performance, since a series of calls to
   752  * rb_{next,prev}() would require time proportional to (n lg n), whereas this
   753  * implementation only requires time proportional to (n).
   754  *
   755  * Since the iterators cache a path down the tree, any tree modification may
   756  * cause the cached path to become invalid.  In order to continue iteration,
   757  * use something like the following sequence:
   758  *
   759  *   {
   760  *       a_type *node, *tnode;
   761  *
   762  *       rb_foreach_begin(a_type, a_field, a_tree, node) {
   763  *           ...
   764  *           rb_next(a_type, a_field, a_cmp, a_tree, node, tnode);
   765  *           rb_remove(a_type, a_field, a_cmp, a_tree, node);
   766  *           rb_foreach_next(a_type, a_field, a_cmp, a_tree, tnode);
   767  *           ...
   768  *       } rb_foreach_end(a_type, a_field, a_tree, node)
   769  *   }
   770  *
   771  * Note that this idiom is not advised if every iteration modifies the tree,
   772  * since in that case there is no algorithmic complexity improvement over a
   773  * series of rb_{next,prev}() calls, thus making the setup overhead wasted
   774  * effort.
   775  */
   777 #ifdef RB_NO_C99_VARARRAYS
   778    /*
   779     * Avoid using variable-length arrays, at the cost of using more stack space.
   780     * Size the path arrays such that they are always large enough, even if a
   781     * tree consumes all of memory.  Since each node must contain a minimum of
   782     * two pointers, there can never be more nodes than:
   783     *
   784     *   1 << ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1))
   785     *
   786     * Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
   787     * is:
   788     *
   789     *   (3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1)))
   790     *
   791     * This works out to a maximum depth of 87 and 180 for 32- and 64-bit
   792     * systems, respectively (approximatly 348 and 1440 bytes, respectively).
   793     */
   794 #  define rbp_compute_f_height(a_type, a_field, a_tree)
   795 #  define rbp_f_height	(3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1)))
   796 #  define rbp_compute_fr_height(a_type, a_field, a_tree)
   797 #  define rbp_fr_height	(3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1)))
   798 #else
   799 #  define rbp_compute_f_height(a_type, a_field, a_tree)			\
   800     /* Compute the maximum possible tree depth (3X the black height). */\
   801     unsigned rbp_f_height;						\
   802     rbp_black_height(a_type, a_field, a_tree, rbp_f_height);		\
   803     rbp_f_height *= 3;
   804 #  define rbp_compute_fr_height(a_type, a_field, a_tree)		\
   805     /* Compute the maximum possible tree depth (3X the black height). */\
   806     unsigned rbp_fr_height;						\
   807     rbp_black_height(a_type, a_field, a_tree, rbp_fr_height);		\
   808     rbp_fr_height *= 3;
   809 #endif
   811 #define	rb_foreach_begin(a_type, a_field, a_tree, a_var) {		\
   812     rbp_compute_f_height(a_type, a_field, a_tree)			\
   813     {									\
   814 	/* Initialize the path to contain the left spine.             */\
   815 	a_type *rbp_f_path[rbp_f_height];				\
   816 	a_type *rbp_f_node;						\
   817 	bool rbp_f_synced = false;					\
   818 	unsigned rbp_f_depth = 0;					\
   819 	if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {			\
   820 	    rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root;		\
   821 	    rbp_f_depth++;						\
   822 	    while ((rbp_f_node = rbp_left_get(a_type, a_field,		\
   823 	      rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) {	\
   824 		rbp_f_path[rbp_f_depth] = rbp_f_node;			\
   825 		rbp_f_depth++;						\
   826 	    }								\
   827 	}								\
   828 	/* While the path is non-empty, iterate.                      */\
   829 	while (rbp_f_depth > 0) {					\
   830 	    (a_var) = rbp_f_path[rbp_f_depth-1];
   832 /* Only use if modifying the tree during iteration. */
   833 #define	rb_foreach_next(a_type, a_field, a_cmp, a_tree, a_node)		\
   834 	    /* Re-initialize the path to contain the path to a_node.  */\
   835 	    rbp_f_depth = 0;						\
   836 	    if (a_node != NULL) {					\
   837 		if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {		\
   838 		    rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root;	\
   839 		    rbp_f_depth++;					\
   840 		    rbp_f_node = rbp_f_path[0];				\
   841 		    while (true) {					\
   842 			int rbp_f_cmp = (a_cmp)((a_node),		\
   843 			  rbp_f_path[rbp_f_depth-1]);			\
   844 			if (rbp_f_cmp < 0) {				\
   845 			    rbp_f_node = rbp_left_get(a_type, a_field,	\
   846 			      rbp_f_path[rbp_f_depth-1]);		\
   847 			} else if (rbp_f_cmp > 0) {			\
   848 			    rbp_f_node = rbp_right_get(a_type, a_field,	\
   849 			      rbp_f_path[rbp_f_depth-1]);		\
   850 			} else {					\
   851 			    break;					\
   852 			}						\
   853 			assert(rbp_f_node != &(a_tree)->rbt_nil);	\
   854 			rbp_f_path[rbp_f_depth] = rbp_f_node;		\
   855 			rbp_f_depth++;					\
   856 		    }							\
   857 		}							\
   858 	    }								\
   859 	    rbp_f_synced = true;
   861 #define	rb_foreach_end(a_type, a_field, a_tree, a_var)			\
   862 	    if (rbp_f_synced) {						\
   863 		rbp_f_synced = false;					\
   864 		continue;						\
   865 	    }								\
   866 	    /* Find the successor.                                    */\
   867 	    if ((rbp_f_node = rbp_right_get(a_type, a_field,		\
   868 	      rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) {	\
   869 	        /* The successor is the left-most node in the right   */\
   870 		/* subtree.                                           */\
   871 		rbp_f_path[rbp_f_depth] = rbp_f_node;			\
   872 		rbp_f_depth++;						\
   873 		while ((rbp_f_node = rbp_left_get(a_type, a_field,	\
   874 		  rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) {	\
   875 		    rbp_f_path[rbp_f_depth] = rbp_f_node;		\
   876 		    rbp_f_depth++;					\
   877 		}							\
   878 	    } else {							\
   879 		/* The successor is above the current node.  Unwind   */\
   880 		/* until a left-leaning edge is removed from the      */\
   881 		/* path, or the path is empty.                        */\
   882 		for (rbp_f_depth--; rbp_f_depth > 0; rbp_f_depth--) {	\
   883 		    if (rbp_left_get(a_type, a_field,			\
   884 		      rbp_f_path[rbp_f_depth-1])			\
   885 		      == rbp_f_path[rbp_f_depth]) {			\
   886 			break;						\
   887 		    }							\
   888 		}							\
   889 	    }								\
   890 	}								\
   891     }									\
   892 }
   894 #define	rb_foreach_reverse_begin(a_type, a_field, a_tree, a_var) {	\
   895     rbp_compute_fr_height(a_type, a_field, a_tree)			\
   896     {									\
   897 	/* Initialize the path to contain the right spine.            */\
   898 	a_type *rbp_fr_path[rbp_fr_height];				\
   899 	a_type *rbp_fr_node;						\
   900 	bool rbp_fr_synced = false;					\
   901 	unsigned rbp_fr_depth = 0;					\
   902 	if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {			\
   903 	    rbp_fr_path[rbp_fr_depth] = (a_tree)->rbt_root;		\
   904 	    rbp_fr_depth++;						\
   905 	    while ((rbp_fr_node = rbp_right_get(a_type, a_field,	\
   906 	      rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) {	\
   907 		rbp_fr_path[rbp_fr_depth] = rbp_fr_node;		\
   908 		rbp_fr_depth++;						\
   909 	    }								\
   910 	}								\
   911 	/* While the path is non-empty, iterate.                      */\
   912 	while (rbp_fr_depth > 0) {					\
   913 	    (a_var) = rbp_fr_path[rbp_fr_depth-1];
   915 /* Only use if modifying the tree during iteration. */
   916 #define	rb_foreach_reverse_prev(a_type, a_field, a_cmp, a_tree, a_node)	\
   917 	    /* Re-initialize the path to contain the path to a_node.  */\
   918 	    rbp_fr_depth = 0;						\
   919 	    if (a_node != NULL) {					\
   920 		if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {		\
   921 		    rbp_fr_path[rbp_fr_depth] = (a_tree)->rbt_root;	\
   922 		    rbp_fr_depth++;					\
   923 		    rbp_fr_node = rbp_fr_path[0];			\
   924 		    while (true) {					\
   925 			int rbp_fr_cmp = (a_cmp)((a_node),		\
   926 			  rbp_fr_path[rbp_fr_depth-1]);			\
   927 			if (rbp_fr_cmp < 0) {				\
   928 			    rbp_fr_node = rbp_left_get(a_type, a_field,	\
   929 			      rbp_fr_path[rbp_fr_depth-1]);		\
   930 			} else if (rbp_fr_cmp > 0) {			\
   931 			    rbp_fr_node = rbp_right_get(a_type, a_field,\
   932 			      rbp_fr_path[rbp_fr_depth-1]);		\
   933 			} else {					\
   934 			    break;					\
   935 			}						\
   936 			assert(rbp_fr_node != &(a_tree)->rbt_nil);	\
   937 			rbp_fr_path[rbp_fr_depth] = rbp_fr_node;	\
   938 			rbp_fr_depth++;					\
   939 		    }							\
   940 		}							\
   941 	    }								\
   942 	    rbp_fr_synced = true;
   944 #define	rb_foreach_reverse_end(a_type, a_field, a_tree, a_var)		\
   945 	    if (rbp_fr_synced) {					\
   946 		rbp_fr_synced = false;					\
   947 		continue;						\
   948 	    }								\
   949 	    if (rbp_fr_depth == 0) {					\
   950 		/* rb_foreach_reverse_sync() was called with a NULL   */\
   951 		/* a_node.                                            */\
   952 		break;							\
   953 	    }								\
   954 	    /* Find the predecessor.                                  */\
   955 	    if ((rbp_fr_node = rbp_left_get(a_type, a_field,		\
   956 	      rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) {	\
   957 	        /* The predecessor is the right-most node in the left */\
   958 		/* subtree.                                           */\
   959 		rbp_fr_path[rbp_fr_depth] = rbp_fr_node;		\
   960 		rbp_fr_depth++;						\
   961 		while ((rbp_fr_node = rbp_right_get(a_type, a_field,	\
   962 		  rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) {\
   963 		    rbp_fr_path[rbp_fr_depth] = rbp_fr_node;		\
   964 		    rbp_fr_depth++;					\
   965 		}							\
   966 	    } else {							\
   967 		/* The predecessor is above the current node.  Unwind */\
   968 		/* until a right-leaning edge is removed from the     */\
   969 		/* path, or the path is empty.                        */\
   970 		for (rbp_fr_depth--; rbp_fr_depth > 0; rbp_fr_depth--) {\
   971 		    if (rbp_right_get(a_type, a_field,			\
   972 		      rbp_fr_path[rbp_fr_depth-1])			\
   973 		      == rbp_fr_path[rbp_fr_depth]) {			\
   974 			break;						\
   975 		    }							\
   976 		}							\
   977 	    }								\
   978 	}								\
   979     }									\
   980 }
   982 #endif /* RB_H_ */

mercurial