## Coverage Report

#### Created: 2026-05-04 15:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/liu/actions-runner/_work/ccv/ccv/lib/3rdparty/jemalloc/rb.h

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