Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmlibarchive/libarchive/archive_rb.c
Line
Count
Source
1
/*-
2
 * Copyright (c) 2001 The NetBSD Foundation, Inc.
3
 * All rights reserved.
4
 *
5
 * This code is derived from software contributed to The NetBSD Foundation
6
 * by Matt Thomas <matt@3am-software.com>.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * Based on: NetBSD: rb.c,v 1.6 2010/04/30 13:58:09 joerg Exp
30
 */
31
32
#include "archive_platform.h"
33
34
#include <stddef.h>
35
36
#include "archive_rb.h"
37
38
/* Keep in sync with archive_rb.h */
39
10.3k
#define RB_DIR_LEFT   0
40
4.22k
#define RB_DIR_RIGHT    1
41
1.62k
#define RB_DIR_OTHER    1
42
3.28k
#define rb_left     rb_nodes[RB_DIR_LEFT]
43
4.05k
#define rb_right    rb_nodes[RB_DIR_RIGHT]
44
45
13.0k
#define RB_FLAG_POSITION  0x2
46
14.5k
#define RB_FLAG_RED   0x1
47
8.14k
#define RB_FLAG_MASK    (RB_FLAG_POSITION|RB_FLAG_RED)
48
#define RB_FATHER(rb) \
49
2.39k
    ((struct archive_rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
50
#define RB_SET_FATHER(rb, father) \
51
4.93k
    ((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
52
53
20.8k
#define RB_SENTINEL_P(rb) ((rb) == NULL)
54
0
#define RB_LEFT_SENTINEL_P(rb)  RB_SENTINEL_P((rb)->rb_left)
55
0
#define RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right)
56
#define RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
57
#define RB_CHILDLESS_P(rb) \
58
0
    (RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
59
#define RB_TWOCHILDREN_P(rb) \
60
0
    (!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
61
62
#define RB_POSITION(rb) \
63
806
    (((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
64
#define RB_RIGHT_P(rb)    (RB_POSITION(rb) == RB_DIR_RIGHT)
65
#define RB_LEFT_P(rb)   (RB_POSITION(rb) == RB_DIR_LEFT)
66
1.59k
#define RB_RED_P(rb)    (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
67
856
#define RB_BLACK_P(rb)    (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
68
1.67k
#define RB_MARK_RED(rb)   ((void)((rb)->rb_info |= RB_FLAG_RED))
69
2.73k
#define RB_MARK_BLACK(rb)   ((void)((rb)->rb_info &= ~RB_FLAG_RED))
70
#define RB_INVERT_COLOR(rb)   ((void)((rb)->rb_info ^= RB_FLAG_RED))
71
268
#define RB_ROOT_P(rbt, rb)  ((rbt)->rbt_root == (rb))
72
#define RB_SET_POSITION(rb, position) \
73
4.13k
    ((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
74
4.13k
    ((rb)->rb_info &= ~RB_FLAG_POSITION)))
75
#define RB_ZERO_PROPERTIES(rb)  ((void)((rb)->rb_info &= ~RB_FLAG_MASK))
76
#define RB_COPY_PROPERTIES(dst, src) \
77
0
    ((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
78
806
#define RB_SWAP_PROPERTIES(a, b) do { \
79
806
    uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
80
806
    (a)->rb_info ^= xorinfo; \
81
806
    (b)->rb_info ^= xorinfo; \
82
806
  } while (/*CONSTCOND*/ 0)
83
84
static void __archive_rb_tree_insert_rebalance(struct archive_rb_tree *,
85
    struct archive_rb_node *);
86
static void __archive_rb_tree_removal_rebalance(struct archive_rb_tree *,
87
    struct archive_rb_node *, unsigned int);
88
89
58.3k
#define RB_SENTINEL_NODE  NULL
90
91
3.28k
#define T 1
92
4.85k
#define F 0
93
94
void
95
__archive_rb_tree_init(struct archive_rb_tree *rbt,
96
    const struct archive_rb_tree_ops *ops)
97
58.3k
{
98
58.3k
  rbt->rbt_ops = ops;
99
58.3k
  *((struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
100
58.3k
}
101
102
struct archive_rb_node *
103
__archive_rb_tree_find_node(struct archive_rb_tree *rbt, const void *key)
104
4.40k
{
105
4.40k
  archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
106
4.40k
  struct archive_rb_node *parent = rbt->rbt_root;
107
108
5.37k
  while (!RB_SENTINEL_P(parent)) {
109
5.37k
    const signed int diff = (*compare_key)(parent, key);
110
5.37k
    if (diff == 0)
111
4.40k
      return parent;
112
972
    parent = parent->rb_nodes[diff > 0];
113
972
  }
114
115
0
  return NULL;
116
4.40k
}
117
 
118
struct archive_rb_node *
119
__archive_rb_tree_find_node_geq(struct archive_rb_tree *rbt, const void *key)
120
0
{
121
0
  archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
122
0
  struct archive_rb_node *parent = rbt->rbt_root;
123
0
  struct archive_rb_node *last = NULL;
124
125
0
  while (!RB_SENTINEL_P(parent)) {
126
0
    const signed int diff = (*compare_key)(parent, key);
127
0
    if (diff == 0)
128
0
      return parent;
129
0
    if (diff < 0)
130
0
      last = parent;
131
0
    parent = parent->rb_nodes[diff > 0];
132
0
  }
133
134
0
  return last;
135
0
}
136
 
137
struct archive_rb_node *
138
__archive_rb_tree_find_node_leq(struct archive_rb_tree *rbt, const void *key)
139
0
{
140
0
  archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
141
0
  struct archive_rb_node *parent = rbt->rbt_root;
142
0
  struct archive_rb_node *last = NULL;
143
144
0
  while (!RB_SENTINEL_P(parent)) {
145
0
    const signed int diff = (*compare_key)(parent, key);
146
0
    if (diff == 0)
147
0
      return parent;
148
0
    if (diff > 0)
149
0
      last = parent;
150
0
    parent = parent->rb_nodes[diff > 0];
151
0
  }
152
153
0
  return last;
154
0
}
155

156
int
157
__archive_rb_tree_insert_node(struct archive_rb_tree *rbt,
158
    struct archive_rb_node *self)
159
6.44k
{
160
6.44k
  archive_rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
161
6.44k
  struct archive_rb_node *parent, *tmp;
162
6.44k
  unsigned int position;
163
6.44k
  int rebalance;
164
165
6.44k
  tmp = rbt->rbt_root;
166
  /*
167
   * This is a hack.  Because rbt->rbt_root is just a
168
   * struct archive_rb_node *, just like rb_node->rb_nodes[RB_DIR_LEFT],
169
   * we can use this fact to avoid a lot of tests for root and know
170
   * that even at root, updating
171
   * RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will
172
   * update rbt->rbt_root.
173
   */
174
6.44k
  parent = (struct archive_rb_node *)(void *)&rbt->rbt_root;
175
6.44k
  position = RB_DIR_LEFT;
176
177
  /*
178
   * Find out where to place this new leaf.
179
   */
180
9.76k
  while (!RB_SENTINEL_P(tmp)) {
181
6.47k
    const signed int diff = (*compare_nodes)(tmp, self);
182
6.47k
    if (diff == 0) {
183
      /*
184
       * Node already exists; don't insert.
185
       */
186
3.15k
      return F;
187
3.15k
    }
188
3.32k
    parent = tmp;
189
3.32k
    position = (diff > 0);
190
3.32k
    tmp = parent->rb_nodes[position];
191
3.32k
  }
192
193
  /*
194
   * Initialize the node and insert as a leaf into the tree.
195
   */
196
3.28k
  RB_SET_FATHER(self, parent);
197
3.28k
  RB_SET_POSITION(self, position);
198
3.28k
  if (parent == (struct archive_rb_node *)(void *)&rbt->rbt_root) {
199
1.69k
    RB_MARK_BLACK(self);   /* root is always black */
200
1.69k
    rebalance = F;
201
1.69k
  } else {
202
    /*
203
     * All new nodes are colored red.  We only need to rebalance
204
     * if our parent is also red.
205
     */
206
1.59k
    RB_MARK_RED(self);
207
1.59k
    rebalance = RB_RED_P(parent);
208
1.59k
  }
209
3.28k
  self->rb_left = parent->rb_nodes[position];
210
3.28k
  self->rb_right = parent->rb_nodes[position];
211
3.28k
  parent->rb_nodes[position] = self;
212
213
  /*
214
   * Rebalance tree after insertion
215
   */
216
3.28k
  if (rebalance)
217
736
    __archive_rb_tree_insert_rebalance(rbt, self);
218
219
3.28k
  return T;
220
6.44k
}
221

222
/*
223
 * Swap the location and colors of 'self' and its child @ which.  The child
224
 * can not be a sentinel node.  This is our rotation function.  However,
225
 * since it preserves coloring, it great simplifies both insertion and
226
 * removal since rotation almost always involves the exchanging of colors
227
 * as a separate step.
228
 */
229
/*ARGSUSED*/
230
static void
231
__archive_rb_tree_reparent_nodes(
232
    struct archive_rb_node *old_father, const unsigned int which)
233
806
{
234
806
  const unsigned int other = which ^ RB_DIR_OTHER;
235
806
  struct archive_rb_node * const grandpa = RB_FATHER(old_father);
236
806
  struct archive_rb_node * const old_child = old_father->rb_nodes[which];
237
806
  struct archive_rb_node * const new_father = old_child;
238
806
  struct archive_rb_node * const new_child = old_father;
239
240
806
  if (new_father == NULL)
241
0
    return;
242
  /*
243
   * Exchange descendant linkages.
244
   */
245
806
  grandpa->rb_nodes[RB_POSITION(old_father)] = new_father;
246
806
  new_child->rb_nodes[which] = old_child->rb_nodes[other];
247
806
  new_father->rb_nodes[other] = new_child;
248
249
  /*
250
   * Update ancestor linkages
251
   */
252
806
  RB_SET_FATHER(new_father, grandpa);
253
806
  RB_SET_FATHER(new_child, new_father);
254
255
  /*
256
   * Exchange properties between new_father and new_child.  The only
257
   * change is that new_child's position is now on the other side.
258
   */
259
806
  RB_SWAP_PROPERTIES(new_father, new_child);
260
806
  RB_SET_POSITION(new_child, other);
261
262
  /*
263
   * Make sure to reparent the new child to ourself.
264
   */
265
806
  if (!RB_SENTINEL_P(new_child->rb_nodes[which])) {
266
38
    RB_SET_FATHER(new_child->rb_nodes[which], new_child);
267
38
    RB_SET_POSITION(new_child->rb_nodes[which], which);
268
38
  }
269
270
806
}
271

272
static void
273
__archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
274
    struct archive_rb_node *self)
275
736
{
276
736
  struct archive_rb_node * father = RB_FATHER(self);
277
736
  struct archive_rb_node * grandpa;
278
736
  struct archive_rb_node * uncle;
279
736
  unsigned int which;
280
736
  unsigned int other;
281
282
768
  for (;;) {
283
    /*
284
     * We are red and our parent is red, therefore we must have a
285
     * grandfather and he must be black.
286
     */
287
768
    grandpa = RB_FATHER(father);
288
768
    which = (father == grandpa->rb_right);
289
768
    other = which ^ RB_DIR_OTHER;
290
768
    uncle = grandpa->rb_nodes[other];
291
292
768
    if (RB_BLACK_P(uncle))
293
500
      break;
294
295
    /*
296
     * Case 1: our uncle is red
297
     *   Simply invert the colors of our parent and
298
     *   uncle and make our grandparent red.  And
299
     *   then solve the problem up at his level.
300
     */
301
268
    RB_MARK_BLACK(uncle);
302
268
    RB_MARK_BLACK(father);
303
268
    if (RB_ROOT_P(rbt, grandpa)) {
304
      /*
305
       * If our grandpa is root, don't bother
306
       * setting him to red, just return.
307
       */
308
180
      return;
309
180
    }
310
88
    RB_MARK_RED(grandpa);
311
88
    self = grandpa;
312
88
    father = RB_FATHER(self);
313
88
    if (RB_BLACK_P(father)) {
314
      /*
315
       * If our great-grandpa is black, we're done.
316
       */
317
56
      return;
318
56
    }
319
88
  }
320
321
  /*
322
   * Case 2&3: our uncle is black.
323
   */
324
500
  if (self == father->rb_nodes[other]) {
325
    /*
326
     * Case 2: we are on the same side as our uncle
327
     *   Swap ourselves with our parent so this case
328
     *   becomes case 3.  Basically our parent becomes our
329
     *   child.
330
     */
331
306
    __archive_rb_tree_reparent_nodes(father, other);
332
306
  }
333
  /*
334
   * Case 3: we are opposite a child of a black uncle.
335
   *   Swap our parent and grandparent.  Since our grandfather
336
   *   is black, our father will become black and our new sibling
337
   *   (former grandparent) will become red.
338
   */
339
500
  __archive_rb_tree_reparent_nodes(grandpa, which);
340
341
  /*
342
   * Final step: Set the root to black.
343
   */
344
500
  RB_MARK_BLACK(rbt->rbt_root);
345
500
}
346

347
static void
348
__archive_rb_tree_prune_node(struct archive_rb_tree *rbt,
349
    struct archive_rb_node *self, int rebalance)
350
0
{
351
0
  const unsigned int which = RB_POSITION(self);
352
0
  struct archive_rb_node *father = RB_FATHER(self);
353
354
  /*
355
   * Since we are childless, we know that self->rb_left is pointing
356
   * to the sentinel node.
357
   */
358
0
  father->rb_nodes[which] = self->rb_left;
359
360
  /*
361
   * Rebalance if requested.
362
   */
363
0
  if (rebalance)
364
0
    __archive_rb_tree_removal_rebalance(rbt, father, which);
365
0
}
366

367
/*
368
 * When deleting an interior node
369
 */
370
static void
371
__archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
372
    struct archive_rb_node *self, struct archive_rb_node *standin)
373
0
{
374
0
  const unsigned int standin_which = RB_POSITION(standin);
375
0
  unsigned int standin_other = standin_which ^ RB_DIR_OTHER;
376
0
  struct archive_rb_node *standin_son;
377
0
  struct archive_rb_node *standin_father = RB_FATHER(standin);
378
0
  int rebalance = RB_BLACK_P(standin);
379
380
0
  if (standin_father == self) {
381
    /*
382
     * As a child of self, any children would be opposite of
383
     * our parent.
384
     */
385
0
    standin_son = standin->rb_nodes[standin_which];
386
0
  } else {
387
    /*
388
     * Since we aren't a child of self, any children would be
389
     * on the same side as our parent.
390
     */
391
0
    standin_son = standin->rb_nodes[standin_other];
392
0
  }
393
394
0
  if (RB_RED_P(standin_son)) {
395
    /*
396
     * We know we have a red child so if we flip it to black
397
     * we don't have to rebalance.
398
     */
399
0
    RB_MARK_BLACK(standin_son);
400
0
    rebalance = F;
401
402
0
    if (standin_father != self) {
403
      /*
404
       * Change the son's parentage to point to his grandpa.
405
       */
406
0
      RB_SET_FATHER(standin_son, standin_father);
407
0
      RB_SET_POSITION(standin_son, standin_which);
408
0
    }
409
0
  }
410
411
0
  if (standin_father == self) {
412
    /*
413
     * If we are about to delete the standin's father, then when
414
     * we call rebalance, we need to use ourselves as our father.
415
     * Otherwise remember our original father.  Also, since we are
416
     * our standin's father we only need to reparent the standin's
417
     * brother.
418
     *
419
     * |    R      -->     S    |
420
     * |  Q   S    -->   Q   T  |
421
     * |        t  -->          |
422
     *
423
     * Have our son/standin adopt his brother as his new son.
424
     */
425
0
    standin_father = standin;
426
0
  } else {
427
    /*
428
     * |    R          -->    S       .  |
429
     * |   / \  |   T  -->   / \  |  /   |
430
     * |  ..... | S    -->  ..... | T    |
431
     *
432
     * Sever standin's connection to his father.
433
     */
434
0
    standin_father->rb_nodes[standin_which] = standin_son;
435
    /*
436
     * Adopt the far son.
437
     */
438
0
    standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
439
0
    RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
440
    /*
441
     * Use standin_other because we need to preserve standin_which
442
     * for the removal_rebalance.
443
     */
444
0
    standin_other = standin_which;
445
0
  }
446
447
  /*
448
   * Move the only remaining son to our standin.  If our standin is our
449
   * son, this will be the only son needed to be moved.
450
   */
451
0
  standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
452
0
  RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
453
454
  /*
455
   * Now copy the result of self to standin and then replace
456
   * self with standin in the tree.
457
   */
458
0
  RB_COPY_PROPERTIES(standin, self);
459
0
  RB_SET_FATHER(standin, RB_FATHER(self));
460
0
  RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin;
461
462
0
  if (rebalance)
463
0
    __archive_rb_tree_removal_rebalance(rbt, standin_father, standin_which);
464
0
}
465
466
/*
467
 * We could do this by doing
468
 *  __archive_rb_tree_node_swap(rbt, self, which);
469
 *  __archive_rb_tree_prune_node(rbt, self, F);
470
 *
471
 * But it's more efficient to just evaluate and recolor the child.
472
 */
473
static void
474
__archive_rb_tree_prune_blackred_branch(
475
    struct archive_rb_node *self, unsigned int which)
476
0
{
477
0
  struct archive_rb_node *father = RB_FATHER(self);
478
0
  struct archive_rb_node *son = self->rb_nodes[which];
479
480
  /*
481
   * Remove ourselves from the tree and give our former child our
482
   * properties (position, color, root).
483
   */
484
0
  RB_COPY_PROPERTIES(son, self);
485
0
  father->rb_nodes[RB_POSITION(son)] = son;
486
0
  RB_SET_FATHER(son, father);
487
0
}
488
/*
489
 *
490
 */
491
void
492
__archive_rb_tree_remove_node(struct archive_rb_tree *rbt,
493
    struct archive_rb_node *self)
494
0
{
495
0
  struct archive_rb_node *standin;
496
0
  unsigned int which;
497
498
  /*
499
   * In the following diagrams, we (the node to be removed) are S.  Red
500
   * nodes are lowercase.  T could be either red or black.
501
   *
502
   * Remember the major axiom of the red-black tree: the number of
503
   * black nodes from the root to each leaf is constant across all
504
   * leaves, only the number of red nodes varies.
505
   *
506
   * Thus removing a red leaf doesn't require any other changes to a
507
   * red-black tree.  So if we must remove a node, attempt to rearrange
508
   * the tree so we can remove a red node.
509
   *
510
   * The simplest case is a childless red node or a childless root node:
511
   *
512
   * |    T  -->    T  |    or    |  R  -->  *  |
513
   * |  s    -->  *    |
514
   */
515
0
  if (RB_CHILDLESS_P(self)) {
516
0
    const int rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self);
517
0
    __archive_rb_tree_prune_node(rbt, self, rebalance);
518
0
    return;
519
0
  }
520
0
  if (!RB_TWOCHILDREN_P(self)) {
521
    /*
522
     * The next simplest case is the node we are deleting is
523
     * black and has one red child.
524
     *
525
     * |      T  -->      T  -->      T  |
526
     * |    S    -->  R      -->  R      |
527
     * |  r      -->    s    -->    *    |
528
     */
529
0
    which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT;
530
0
    __archive_rb_tree_prune_blackred_branch(self, which);
531
0
    return;
532
0
  }
533
534
  /*
535
   * We invert these because we prefer to remove from the inside of
536
   * the tree.
537
   */
538
0
  which = RB_POSITION(self) ^ RB_DIR_OTHER;
539
540
  /*
541
   * Let's find the node closes to us opposite of our parent
542
   * Now swap it with ourself, "prune" it, and rebalance, if needed.
543
   */
544
0
  standin = __archive_rb_tree_iterate(rbt, self, which);
545
0
  __archive_rb_tree_swap_prune_and_rebalance(rbt, self, standin);
546
0
}
547
548
static void
549
__archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
550
    struct archive_rb_node *parent, unsigned int which)
551
0
{
552
553
0
  while (RB_BLACK_P(parent->rb_nodes[which])) {
554
0
    unsigned int other = which ^ RB_DIR_OTHER;
555
0
    struct archive_rb_node *brother = parent->rb_nodes[other];
556
557
0
    if (brother == NULL)
558
0
      return;/* The tree may be broken. */
559
    /*
560
     * For cases 1, 2a, and 2b, our brother's children must
561
     * be black and our father must be black
562
     */
563
0
    if (RB_BLACK_P(parent)
564
0
        && RB_BLACK_P(brother->rb_left)
565
0
        && RB_BLACK_P(brother->rb_right)) {
566
0
      if (RB_RED_P(brother)) {
567
        /*
568
         * Case 1: Our brother is red, swap its
569
         * position (and colors) with our parent. 
570
         * This should now be case 2b (unless C or E
571
         * has a red child which is case 3; thus no
572
         * explicit branch to case 2b).
573
         *
574
         *    B         ->        D
575
         *  A     d     ->    b     E
576
         *      C   E   ->  A   C
577
         */
578
0
        __archive_rb_tree_reparent_nodes(parent, other);
579
0
        brother = parent->rb_nodes[other];
580
0
        if (brother == NULL)
581
0
          return;/* The tree may be broken. */
582
0
      } else {
583
        /*
584
         * Both our parent and brother are black.
585
         * Change our brother to red, advance up rank
586
         * and go through the loop again.
587
         *
588
         *    B         ->   *B
589
         * *A     D     ->  A     d
590
         *      C   E   ->      C   E
591
         */
592
0
        RB_MARK_RED(brother);
593
0
        if (RB_ROOT_P(rbt, parent))
594
0
          return; /* root == parent == black */
595
0
        which = RB_POSITION(parent);
596
0
        parent = RB_FATHER(parent);
597
0
        continue;
598
0
      }
599
0
    }
600
    /*
601
     * Avoid an else here so that case 2a above can hit either
602
     * case 2b, 3, or 4.
603
     */
604
0
    if (RB_RED_P(parent)
605
0
        && RB_BLACK_P(brother)
606
0
        && RB_BLACK_P(brother->rb_left)
607
0
        && RB_BLACK_P(brother->rb_right)) {
608
      /*
609
       * We are black, our father is red, our brother and
610
       * both nephews are black.  Simply invert/exchange the
611
       * colors of our father and brother (to black and red
612
       * respectively).
613
       *
614
       *  |    f        -->    F        |
615
       *  |  *     B    -->  *     b    |
616
       *  |      N   N  -->      N   N  |
617
       */
618
0
      RB_MARK_BLACK(parent);
619
0
      RB_MARK_RED(brother);
620
0
      break;    /* We're done! */
621
0
    } else {
622
      /*
623
       * Our brother must be black and have at least one
624
       * red child (it may have two).
625
       */
626
0
      if (RB_BLACK_P(brother->rb_nodes[other])) {
627
        /*
628
         * Case 3: our brother is black, our near
629
         * nephew is red, and our far nephew is black.
630
         * Swap our brother with our near nephew.  
631
         * This result in a tree that matches case 4.
632
         * (Our father could be red or black).
633
         *
634
         *  |    F      -->    F      |
635
         *  |  x     B  -->  x   B    |
636
         *  |      n    -->        n  |
637
         */
638
0
        __archive_rb_tree_reparent_nodes(brother, which);
639
0
        brother = parent->rb_nodes[other];
640
0
      }
641
      /*
642
       * Case 4: our brother is black and our far nephew
643
       * is red.  Swap our father and brother locations and
644
       * change our far nephew to black.  (these can be
645
       * done in either order so we change the color first).
646
       * The result is a valid red-black tree and is a
647
       * terminal case.  (again we don't care about the
648
       * father's color)
649
       *
650
       * If the father is red, we will get a red-black-black
651
       * tree:
652
       *  |  f      ->  f      -->    b    |
653
       *  |    B    ->    B    -->  F   N  |
654
       *  |      n  ->      N  -->         |
655
       *
656
       * If the father is black, we will get an all black
657
       * tree:
658
       *  |  F      ->  F      -->    B    |
659
       *  |    B    ->    B    -->  F   N  |
660
       *  |      n  ->      N  -->         |
661
       *
662
       * If we had two red nephews, then after the swap,
663
       * our former father would have a red grandson. 
664
       */
665
0
      if (brother->rb_nodes[other] == NULL)
666
0
        return;/* The tree may be broken. */
667
0
      RB_MARK_BLACK(brother->rb_nodes[other]);
668
0
      __archive_rb_tree_reparent_nodes(parent, other);
669
0
      break;   /* We're done! */
670
0
    }
671
0
  }
672
0
}
673
674
struct archive_rb_node *
675
__archive_rb_tree_iterate(struct archive_rb_tree *rbt,
676
    struct archive_rb_node *self, const unsigned int direction)
677
54
{
678
54
  const unsigned int other = direction ^ RB_DIR_OTHER;
679
680
54
  if (self == NULL) {
681
54
    self = rbt->rbt_root;
682
54
    if (RB_SENTINEL_P(self))
683
54
      return NULL;
684
0
    while (!RB_SENTINEL_P(self->rb_nodes[direction]))
685
0
      self = self->rb_nodes[direction];
686
0
    return self;
687
54
  }
688
  /*
689
   * We can't go any further in this direction.  We proceed up in the
690
   * opposite direction until our parent is in direction we want to go.
691
   */
692
0
  if (RB_SENTINEL_P(self->rb_nodes[direction])) {
693
0
    while (!RB_ROOT_P(rbt, self)) {
694
0
      if (other == (unsigned int)RB_POSITION(self))
695
0
        return RB_FATHER(self);
696
0
      self = RB_FATHER(self);
697
0
    }
698
0
    return NULL;
699
0
  }
700
701
  /*
702
   * Advance down one in current direction and go down as far as possible
703
   * in the opposite direction.
704
   */
705
0
  self = self->rb_nodes[direction];
706
0
  while (!RB_SENTINEL_P(self->rb_nodes[other]))
707
0
    self = self->rb_nodes[other];
708
0
  return self;
709
0
}