Coverage Report

Created: 2026-04-04 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c
Line
Count
Source
1
/** @file
2
  An OrderedCollectionLib instance that provides a red-black tree
3
  implementation, and allocates and releases tree nodes with
4
  MemoryAllocationLib.
5
6
  This library instance is useful when a fast associative container is needed.
7
  Worst case time complexity is O(log n) for Find(), Next(), Prev(), Min(),
8
  Max(), Insert(), and Delete(), where "n" is the number of elements in the
9
  tree. Complete ordered traversal takes O(n) time.
10
11
  The implementation is also useful as a fast priority queue.
12
13
  Copyright (C) 2014, Red Hat, Inc.
14
  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
15
16
  SPDX-License-Identifier: BSD-2-Clause-Patent
17
**/
18
19
#include <Library/OrderedCollectionLib.h>
20
#include <Library/DebugLib.h>
21
#include <Library/MemoryAllocationLib.h>
22
23
typedef enum {
24
  RedBlackTreeRed,
25
  RedBlackTreeBlack
26
} RED_BLACK_TREE_COLOR;
27
28
//
29
// Incomplete types and convenience typedefs are present in the library class
30
// header. Beside completing the types, we introduce typedefs here that reflect
31
// the implementation closely.
32
//
33
typedef ORDERED_COLLECTION               RED_BLACK_TREE;
34
typedef ORDERED_COLLECTION_ENTRY         RED_BLACK_TREE_NODE;
35
typedef ORDERED_COLLECTION_USER_COMPARE  RED_BLACK_TREE_USER_COMPARE;
36
typedef ORDERED_COLLECTION_KEY_COMPARE   RED_BLACK_TREE_KEY_COMPARE;
37
38
struct ORDERED_COLLECTION {
39
  RED_BLACK_TREE_NODE            *Root;
40
  RED_BLACK_TREE_USER_COMPARE    UserStructCompare;
41
  RED_BLACK_TREE_KEY_COMPARE     KeyCompare;
42
};
43
44
struct ORDERED_COLLECTION_ENTRY {
45
  VOID                    *UserStruct;
46
  RED_BLACK_TREE_NODE     *Parent;
47
  RED_BLACK_TREE_NODE     *Left;
48
  RED_BLACK_TREE_NODE     *Right;
49
  RED_BLACK_TREE_COLOR    Color;
50
};
51
52
/**
53
  Retrieve the user structure linked by the specified tree node.
54
55
  Read-only operation.
56
57
  @param[in] Node  Pointer to the tree node whose associated user structure we
58
                   want to retrieve. The caller is responsible for passing a
59
                   non-NULL argument.
60
61
  @return  Pointer to user structure linked by Node.
62
**/
63
VOID *
64
EFIAPI
65
OrderedCollectionUserStruct (
66
  IN CONST RED_BLACK_TREE_NODE  *Node
67
  )
68
31.0k
{
69
31.0k
  return Node->UserStruct;
70
31.0k
}
71
72
/**
73
  A slow function that asserts that the tree is a valid red-black tree, and
74
  that it orders user structures correctly.
75
76
  Read-only operation.
77
78
  This function uses the stack for recursion and is not recommended for
79
  "production use".
80
81
  @param[in] Tree  The tree to validate.
82
**/
83
VOID
84
RedBlackTreeValidate (
85
  IN CONST RED_BLACK_TREE  *Tree
86
  );
87
88
/**
89
  Allocate and initialize the RED_BLACK_TREE structure.
90
91
  Allocation occurs via MemoryAllocationLib's AllocatePool() function.
92
93
  @param[in]  UserStructCompare  This caller-provided function will be used to
94
                                 order two user structures linked into the
95
                                 tree, during the insertion procedure.
96
97
  @param[in]  KeyCompare         This caller-provided function will be used to
98
                                 order the standalone search key against user
99
                                 structures linked into the tree, during the
100
                                 lookup procedure.
101
102
  @retval NULL  If allocation failed.
103
104
  @return       Pointer to the allocated, initialized RED_BLACK_TREE structure,
105
                otherwise.
106
**/
107
RED_BLACK_TREE *
108
EFIAPI
109
OrderedCollectionInit (
110
  IN RED_BLACK_TREE_USER_COMPARE  UserStructCompare,
111
  IN RED_BLACK_TREE_KEY_COMPARE   KeyCompare
112
  )
113
1.59k
{
114
1.59k
  RED_BLACK_TREE  *Tree;
115
116
1.59k
  Tree = AllocatePool (sizeof *Tree);
117
1.59k
  if (Tree == NULL) {
118
0
    return NULL;
119
0
  }
120
121
1.59k
  Tree->Root              = NULL;
122
1.59k
  Tree->UserStructCompare = UserStructCompare;
123
1.59k
  Tree->KeyCompare        = KeyCompare;
124
125
1.59k
  if (FeaturePcdGet (PcdValidateOrderedCollection)) {
126
0
    RedBlackTreeValidate (Tree);
127
0
  }
128
129
1.59k
  return Tree;
130
1.59k
}
131
132
/**
133
  Check whether the tree is empty (has no nodes).
134
135
  Read-only operation.
136
137
  @param[in] Tree  The tree to check for emptiness.
138
139
  @retval TRUE   The tree is empty.
140
141
  @retval FALSE  The tree is not empty.
142
**/
143
BOOLEAN
144
EFIAPI
145
OrderedCollectionIsEmpty (
146
  IN CONST RED_BLACK_TREE  *Tree
147
  )
148
2.14k
{
149
2.14k
  return (BOOLEAN)(Tree->Root == NULL);
150
2.14k
}
151
152
/**
153
  Uninitialize and release an empty RED_BLACK_TREE structure.
154
155
  Read-write operation.
156
157
  Release occurs via MemoryAllocationLib's FreePool() function.
158
159
  It is the caller's responsibility to delete all nodes from the tree before
160
  calling this function.
161
162
  @param[in] Tree  The empty tree to uninitialize and release.
163
**/
164
VOID
165
EFIAPI
166
OrderedCollectionUninit (
167
  IN RED_BLACK_TREE  *Tree
168
  )
169
1.59k
{
170
1.59k
  ASSERT (OrderedCollectionIsEmpty (Tree));
171
1.59k
  FreePool (Tree);
172
1.59k
}
173
174
/**
175
  Look up the tree node that links the user structure that matches the
176
  specified standalone key.
177
178
  Read-only operation.
179
180
  @param[in] Tree           The tree to search for StandaloneKey.
181
182
  @param[in] StandaloneKey  The key to locate among the user structures linked
183
                            into Tree. StandaloneKey will be passed to
184
                            Tree->KeyCompare().
185
186
  @retval NULL  StandaloneKey could not be found.
187
188
  @return       The tree node that links to the user structure matching
189
                StandaloneKey, otherwise.
190
**/
191
RED_BLACK_TREE_NODE *
192
EFIAPI
193
OrderedCollectionFind (
194
  IN CONST RED_BLACK_TREE  *Tree,
195
  IN CONST VOID            *StandaloneKey
196
  )
197
1.35k
{
198
1.35k
  RED_BLACK_TREE_NODE  *Node;
199
200
1.35k
  Node = Tree->Root;
201
5.44k
  while (Node != NULL) {
202
4.97k
    INTN  Result;
203
204
4.97k
    Result = Tree->KeyCompare (StandaloneKey, Node->UserStruct);
205
4.97k
    if (Result == 0) {
206
880
      break;
207
880
    }
208
209
4.09k
    Node = (Result < 0) ? Node->Left : Node->Right;
210
4.09k
  }
211
212
1.35k
  return Node;
213
1.35k
}
214
215
/**
216
  Find the tree node of the minimum user structure stored in the tree.
217
218
  Read-only operation.
219
220
  @param[in] Tree  The tree to return the minimum node of. The user structure
221
                   linked by the minimum node compares less than all other user
222
                   structures in the tree.
223
224
  @retval NULL  If Tree is empty.
225
226
  @return       The tree node that links the minimum user structure, otherwise.
227
**/
228
RED_BLACK_TREE_NODE *
229
EFIAPI
230
OrderedCollectionMin (
231
  IN CONST RED_BLACK_TREE  *Tree
232
  )
233
2.14k
{
234
2.14k
  RED_BLACK_TREE_NODE  *Node;
235
236
2.14k
  Node = Tree->Root;
237
2.14k
  if (Node == NULL) {
238
54
    return NULL;
239
54
  }
240
241
6.79k
  while (Node->Left != NULL) {
242
4.70k
    Node = Node->Left;
243
4.70k
  }
244
245
2.09k
  return Node;
246
2.14k
}
247
248
/**
249
  Find the tree node of the maximum user structure stored in the tree.
250
251
  Read-only operation.
252
253
  @param[in] Tree  The tree to return the maximum node of. The user structure
254
                   linked by the maximum node compares greater than all other
255
                   user structures in the tree.
256
257
  @retval NULL  If Tree is empty.
258
259
  @return       The tree node that links the maximum user structure, otherwise.
260
**/
261
RED_BLACK_TREE_NODE *
262
EFIAPI
263
OrderedCollectionMax (
264
  IN CONST RED_BLACK_TREE  *Tree
265
  )
266
0
{
267
0
  RED_BLACK_TREE_NODE  *Node;
268
269
0
  Node = Tree->Root;
270
0
  if (Node == NULL) {
271
0
    return NULL;
272
0
  }
273
274
0
  while (Node->Right != NULL) {
275
0
    Node = Node->Right;
276
0
  }
277
278
0
  return Node;
279
0
}
280
281
/**
282
  Get the tree node of the least user structure that is greater than the one
283
  linked by Node.
284
285
  Read-only operation.
286
287
  @param[in] Node  The node to get the successor node of.
288
289
  @retval NULL  If Node is NULL, or Node is the maximum node of its containing
290
                tree (ie. Node has no successor node).
291
292
  @return       The tree node linking the least user structure that is greater
293
                than the one linked by Node, otherwise.
294
**/
295
RED_BLACK_TREE_NODE *
296
EFIAPI
297
OrderedCollectionNext (
298
  IN CONST RED_BLACK_TREE_NODE  *Node
299
  )
300
53.1k
{
301
53.1k
  RED_BLACK_TREE_NODE        *Walk;
302
53.1k
  CONST RED_BLACK_TREE_NODE  *Child;
303
304
53.1k
  if (Node == NULL) {
305
0
    return NULL;
306
0
  }
307
308
  //
309
  // If Node has a right subtree, then the successor is the minimum node of
310
  // that subtree.
311
  //
312
53.1k
  Walk = Node->Right;
313
53.1k
  if (Walk != NULL) {
314
27.9k
    while (Walk->Left != NULL) {
315
5.06k
      Walk = Walk->Left;
316
5.06k
    }
317
318
22.9k
    return Walk;
319
22.9k
  }
320
321
  //
322
  // Otherwise we have to ascend as long as we're our parent's right child (ie.
323
  // ascending to the left).
324
  //
325
30.1k
  Child = Node;
326
30.1k
  Walk  = Child->Parent;
327
36.4k
  while (Walk != NULL && Child == Walk->Right) {
328
6.27k
    Child = Walk;
329
6.27k
    Walk  = Child->Parent;
330
6.27k
  }
331
332
30.1k
  return Walk;
333
53.1k
}
334
335
/**
336
  Get the tree node of the greatest user structure that is less than the one
337
  linked by Node.
338
339
  Read-only operation.
340
341
  @param[in] Node  The node to get the predecessor node of.
342
343
  @retval NULL  If Node is NULL, or Node is the minimum node of its containing
344
                tree (ie. Node has no predecessor node).
345
346
  @return       The tree node linking the greatest user structure that is less
347
                than the one linked by Node, otherwise.
348
**/
349
RED_BLACK_TREE_NODE *
350
EFIAPI
351
OrderedCollectionPrev (
352
  IN CONST RED_BLACK_TREE_NODE  *Node
353
  )
354
0
{
355
0
  RED_BLACK_TREE_NODE        *Walk;
356
0
  CONST RED_BLACK_TREE_NODE  *Child;
357
358
0
  if (Node == NULL) {
359
0
    return NULL;
360
0
  }
361
362
  //
363
  // If Node has a left subtree, then the predecessor is the maximum node of
364
  // that subtree.
365
  //
366
0
  Walk = Node->Left;
367
0
  if (Walk != NULL) {
368
0
    while (Walk->Right != NULL) {
369
0
      Walk = Walk->Right;
370
0
    }
371
372
0
    return Walk;
373
0
  }
374
375
  //
376
  // Otherwise we have to ascend as long as we're our parent's left child (ie.
377
  // ascending to the right).
378
  //
379
0
  Child = Node;
380
0
  Walk  = Child->Parent;
381
0
  while (Walk != NULL && Child == Walk->Left) {
382
0
    Child = Walk;
383
0
    Walk  = Child->Parent;
384
0
  }
385
386
0
  return Walk;
387
0
}
388
389
/**
390
  Rotate tree nodes around Pivot to the right.
391
392
                Parent                       Parent
393
                  |                            |
394
                Pivot                      LeftChild
395
               /     .                    .         \_
396
      LeftChild       Node1   --->   Node2           Pivot
397
         . \                                          / .
398
    Node2   LeftRightChild              LeftRightChild   Node1
399
400
  The ordering Node2 < LeftChild < LeftRightChild < Pivot < Node1 is kept
401
  intact. Parent (if any) is either at the left extreme or the right extreme of
402
  this ordering, and that relation is also kept intact.
403
404
  Edges marked with a dot (".") don't change during rotation.
405
406
  Internal read-write operation.
407
408
  @param[in,out] Pivot    The tree node to rotate other nodes right around. It
409
                          is the caller's responsibility to ensure that
410
                          Pivot->Left is not NULL.
411
412
  @param[out]    NewRoot  If Pivot has a parent node on input, then the
413
                          function updates Pivot's original parent on output
414
                          according to the rotation, and NewRoot is not
415
                          accessed.
416
417
                          If Pivot has no parent node on input (ie. Pivot is
418
                          the root of the tree), then the function stores the
419
                          new root node of the tree in NewRoot.
420
**/
421
VOID
422
RedBlackTreeRotateRight (
423
  IN OUT RED_BLACK_TREE_NODE  *Pivot,
424
  OUT    RED_BLACK_TREE_NODE  **NewRoot
425
  )
426
14.8k
{
427
14.8k
  RED_BLACK_TREE_NODE  *Parent;
428
14.8k
  RED_BLACK_TREE_NODE  *LeftChild;
429
14.8k
  RED_BLACK_TREE_NODE  *LeftRightChild;
430
431
14.8k
  Parent         = Pivot->Parent;
432
14.8k
  LeftChild      = Pivot->Left;
433
14.8k
  LeftRightChild = LeftChild->Right;
434
435
14.8k
  Pivot->Left = LeftRightChild;
436
14.8k
  if (LeftRightChild != NULL) {
437
3.84k
    LeftRightChild->Parent = Pivot;
438
3.84k
  }
439
440
14.8k
  LeftChild->Parent = Parent;
441
14.8k
  if (Parent == NULL) {
442
730
    *NewRoot = LeftChild;
443
14.1k
  } else {
444
14.1k
    if (Pivot == Parent->Left) {
445
3.11k
      Parent->Left = LeftChild;
446
11.0k
    } else {
447
11.0k
      Parent->Right = LeftChild;
448
11.0k
    }
449
14.1k
  }
450
451
14.8k
  LeftChild->Right = Pivot;
452
14.8k
  Pivot->Parent    = LeftChild;
453
14.8k
}
454
455
/**
456
  Rotate tree nodes around Pivot to the left.
457
458
          Parent                                 Parent
459
            |                                      |
460
          Pivot                                RightChild
461
         .     \                              /          .
462
    Node1       RightChild    --->       Pivot            Node2
463
                    /.                    . \_
464
      RightLeftChild  Node2          Node1   RightLeftChild
465
466
  The ordering Node1 < Pivot < RightLeftChild < RightChild < Node2 is kept
467
  intact. Parent (if any) is either at the left extreme or the right extreme of
468
  this ordering, and that relation is also kept intact.
469
470
  Edges marked with a dot (".") don't change during rotation.
471
472
  Internal read-write operation.
473
474
  @param[in,out] Pivot    The tree node to rotate other nodes left around. It
475
                          is the caller's responsibility to ensure that
476
                          Pivot->Right is not NULL.
477
478
  @param[out]    NewRoot  If Pivot has a parent node on input, then the
479
                          function updates Pivot's original parent on output
480
                          according to the rotation, and NewRoot is not
481
                          accessed.
482
483
                          If Pivot has no parent node on input (ie. Pivot is
484
                          the root of the tree), then the function stores the
485
                          new root node of the tree in NewRoot.
486
**/
487
VOID
488
RedBlackTreeRotateLeft (
489
  IN OUT RED_BLACK_TREE_NODE  *Pivot,
490
  OUT    RED_BLACK_TREE_NODE  **NewRoot
491
  )
492
31.8k
{
493
31.8k
  RED_BLACK_TREE_NODE  *Parent;
494
31.8k
  RED_BLACK_TREE_NODE  *RightChild;
495
31.8k
  RED_BLACK_TREE_NODE  *RightLeftChild;
496
497
31.8k
  Parent         = Pivot->Parent;
498
31.8k
  RightChild     = Pivot->Right;
499
31.8k
  RightLeftChild = RightChild->Left;
500
501
31.8k
  Pivot->Right = RightLeftChild;
502
31.8k
  if (RightLeftChild != NULL) {
503
16.6k
    RightLeftChild->Parent = Pivot;
504
16.6k
  }
505
506
31.8k
  RightChild->Parent = Parent;
507
31.8k
  if (Parent == NULL) {
508
4.61k
    *NewRoot = RightChild;
509
27.2k
  } else {
510
27.2k
    if (Pivot == Parent->Left) {
511
22.2k
      Parent->Left = RightChild;
512
22.2k
    } else {
513
4.97k
      Parent->Right = RightChild;
514
4.97k
    }
515
27.2k
  }
516
517
31.8k
  RightChild->Left = Pivot;
518
31.8k
  Pivot->Parent    = RightChild;
519
31.8k
}
520
521
/**
522
  Insert (link) a user structure into the tree.
523
524
  Read-write operation.
525
526
  This function allocates the new tree node with MemoryAllocationLib's
527
  AllocatePool() function.
528
529
  @param[in,out] Tree        The tree to insert UserStruct into.
530
531
  @param[out]    Node        The meaning of this optional, output-only
532
                             parameter depends on the return value of the
533
                             function.
534
535
                             When insertion is successful (RETURN_SUCCESS),
536
                             Node is set on output to the new tree node that
537
                             now links UserStruct.
538
539
                             When insertion fails due to lack of memory
540
                             (RETURN_OUT_OF_RESOURCES), Node is not changed.
541
542
                             When insertion fails due to key collision (ie.
543
                             another user structure is already in the tree that
544
                             compares equal to UserStruct), with return value
545
                             RETURN_ALREADY_STARTED, then Node is set on output
546
                             to the node that links the colliding user
547
                             structure. This enables "find-or-insert" in one
548
                             function call, or helps with later removal of the
549
                             colliding element.
550
551
  @param[in]     UserStruct  The user structure to link into the tree.
552
                             UserStruct is ordered against in-tree user
553
                             structures with the Tree->UserStructCompare()
554
                             function.
555
556
  @retval RETURN_SUCCESS           Insertion successful. A new tree node has
557
                                   been allocated, linking UserStruct. The new
558
                                   tree node is reported back in Node (if the
559
                                   caller requested it).
560
561
                                   Existing RED_BLACK_TREE_NODE pointers into
562
                                   Tree remain valid. For example, on-going
563
                                   iterations in the caller can continue with
564
                                   OrderedCollectionNext() /
565
                                   OrderedCollectionPrev(), and they will
566
                                   return the new node at some point if user
567
                                   structure order dictates it.
568
569
  @retval RETURN_OUT_OF_RESOURCES  AllocatePool() failed to allocate memory for
570
                                   the new tree node. The tree has not been
571
                                   changed. Existing RED_BLACK_TREE_NODE
572
                                   pointers into Tree remain valid.
573
574
  @retval RETURN_ALREADY_STARTED   A user structure has been found in the tree
575
                                   that compares equal to UserStruct. The node
576
                                   linking the colliding user structure is
577
                                   reported back in Node (if the caller
578
                                   requested it). The tree has not been
579
                                   changed. Existing RED_BLACK_TREE_NODE
580
                                   pointers into Tree remain valid.
581
**/
582
RETURN_STATUS
583
EFIAPI
584
OrderedCollectionInsert (
585
  IN OUT RED_BLACK_TREE       *Tree,
586
  OUT    RED_BLACK_TREE_NODE  **Node      OPTIONAL,
587
  IN     VOID                 *UserStruct
588
  )
589
44.7k
{
590
44.7k
  RED_BLACK_TREE_NODE  *Tmp;
591
44.7k
  RED_BLACK_TREE_NODE  *Parent;
592
44.7k
  INTN                 Result;
593
44.7k
  RETURN_STATUS        Status;
594
44.7k
  RED_BLACK_TREE_NODE  *NewRoot;
595
596
44.7k
  Tmp    = Tree->Root;
597
44.7k
  Parent = NULL;
598
44.7k
  Result = 0;
599
600
  //
601
  // First look for a collision, saving the last examined node for the case
602
  // when there's no collision.
603
  //
604
261k
  while (Tmp != NULL) {
605
221k
    Result = Tree->UserStructCompare (UserStruct, Tmp->UserStruct);
606
221k
    if (Result == 0) {
607
4.59k
      break;
608
4.59k
    }
609
610
216k
    Parent = Tmp;
611
216k
    Tmp    = (Result < 0) ? Tmp->Left : Tmp->Right;
612
216k
  }
613
614
44.7k
  if (Tmp != NULL) {
615
4.59k
    if (Node != NULL) {
616
4.48k
      *Node = Tmp;
617
4.48k
    }
618
619
4.59k
    Status = RETURN_ALREADY_STARTED;
620
4.59k
    goto Done;
621
4.59k
  }
622
623
  //
624
  // no collision, allocate a new node
625
  //
626
40.1k
  Tmp = AllocatePool (sizeof *Tmp);
627
40.1k
  if (Tmp == NULL) {
628
0
    Status = RETURN_OUT_OF_RESOURCES;
629
0
    goto Done;
630
0
  }
631
632
40.1k
  if (Node != NULL) {
633
20.1k
    *Node = Tmp;
634
20.1k
  }
635
636
  //
637
  // reference the user structure from the node
638
  //
639
40.1k
  Tmp->UserStruct = UserStruct;
640
641
  //
642
  // Link the node as a child to the correct side of the parent.
643
  // If there's no parent, the new node is the root node in the tree.
644
  //
645
40.1k
  Tmp->Parent = Parent;
646
40.1k
  Tmp->Left   = NULL;
647
40.1k
  Tmp->Right  = NULL;
648
40.1k
  if (Parent == NULL) {
649
1.55k
    Tree->Root = Tmp;
650
1.55k
    Tmp->Color = RedBlackTreeBlack;
651
1.55k
    Status     = RETURN_SUCCESS;
652
1.55k
    goto Done;
653
1.55k
  }
654
655
38.5k
  if (Result < 0) {
656
17.6k
    Parent->Left = Tmp;
657
20.9k
  } else {
658
20.9k
    Parent->Right = Tmp;
659
20.9k
  }
660
661
38.5k
  Tmp->Color = RedBlackTreeRed;
662
663
  //
664
  // Red-black tree properties:
665
  //
666
  // #1 Each node is either red or black (RED_BLACK_TREE_NODE.Color).
667
  //
668
  // #2 Each leaf (ie. a pseudo-node pointed-to by a NULL valued
669
  //    RED_BLACK_TREE_NODE.Left or RED_BLACK_TREE_NODE.Right field) is black.
670
  //
671
  // #3 Each red node has two black children.
672
  //
673
  // #4 For any node N, and for any leaves L1 and L2 reachable from N, the
674
  //    paths N..L1 and N..L2 contain the same number of black nodes.
675
  //
676
  // #5 The root node is black.
677
  //
678
  // By replacing a leaf with a red node above, only property #3 may have been
679
  // broken. (Note that this is the only edge across which property #3 might
680
  // not hold in the entire tree.) Restore property #3.
681
  //
682
683
38.5k
  NewRoot = Tree->Root;
684
74.2k
  while (Tmp != NewRoot && Parent->Color == RedBlackTreeRed) {
685
35.6k
    RED_BLACK_TREE_NODE  *GrandParent;
686
35.6k
    RED_BLACK_TREE_NODE  *Uncle;
687
688
    //
689
    // Tmp is not the root node. Tmp is red. Tmp's parent is red. (Breaking
690
    // property #3.)
691
    //
692
    // Due to property #5, Tmp's parent cannot be the root node, hence Tmp's
693
    // grandparent exists.
694
    //
695
    // Tmp's grandparent is black, because property #3 is only broken between
696
    // Tmp and Tmp's parent.
697
    //
698
35.6k
    GrandParent = Parent->Parent;
699
700
35.6k
    if (Parent == GrandParent->Left) {
701
15.5k
      Uncle = GrandParent->Right;
702
15.5k
      if ((Uncle != NULL) && (Uncle->Color == RedBlackTreeRed)) {
703
        //
704
        //             GrandParent (black)
705
        //            /                   \_
706
        // Parent (red)                    Uncle (red)
707
        //      |
708
        //  Tmp (red)
709
        //
710
711
8.26k
        Parent->Color      = RedBlackTreeBlack;
712
8.26k
        Uncle->Color       = RedBlackTreeBlack;
713
8.26k
        GrandParent->Color = RedBlackTreeRed;
714
715
        //
716
        //                GrandParent (red)
717
        //               /                 \_
718
        // Parent (black)                   Uncle (black)
719
        //       |
720
        //   Tmp (red)
721
        //
722
        // We restored property #3 between Tmp and Tmp's parent, without
723
        // breaking property #4. However, we may have broken property #3
724
        // between Tmp's grandparent and Tmp's great-grandparent (if any), so
725
        // repeat the loop for Tmp's grandparent.
726
        //
727
        // If Tmp's grandparent has no parent, then the loop will terminate,
728
        // and we will have broken property #5, by coloring the root red. We'll
729
        // restore property #5 after the loop, without breaking any others.
730
        //
731
8.26k
        Tmp    = GrandParent;
732
8.26k
        Parent = Tmp->Parent;
733
8.26k
      } else {
734
        //
735
        // Tmp's uncle is black (satisfied by the case too when Tmp's uncle is
736
        // NULL, see property #2).
737
        //
738
739
7.29k
        if (Tmp == Parent->Right) {
740
          //
741
          //                 GrandParent (black): D
742
          //                /                      \_
743
          // Parent (red): A                        Uncle (black): E
744
          //      \_
745
          //       Tmp (red): B
746
          //            \_
747
          //             black: C
748
          //
749
          // Rotate left, pivoting on node A. This keeps the breakage of
750
          // property #3 in the same spot, and keeps other properties intact
751
          // (because both Tmp and its parent are red).
752
          //
753
3.88k
          Tmp = Parent;
754
3.88k
          RedBlackTreeRotateLeft (Tmp, &NewRoot);
755
3.88k
          Parent = Tmp->Parent;
756
757
          //
758
          // With the rotation we reached the same configuration as if Tmp had
759
          // been a left child to begin with.
760
          //
761
          //                       GrandParent (black): D
762
          //                      /                      \_
763
          //       Parent (red): B                        Uncle (black): E
764
          //             / \_
765
          // Tmp (red): A   black: C
766
          //
767
3.88k
          ASSERT (GrandParent == Parent->Parent);
768
3.88k
        }
769
770
7.29k
        Parent->Color      = RedBlackTreeBlack;
771
7.29k
        GrandParent->Color = RedBlackTreeRed;
772
773
        //
774
        // Property #3 is now restored, but we've broken property #4. Namely,
775
        // paths going through node E now see a decrease in black count, while
776
        // paths going through node B don't.
777
        //
778
        //                        GrandParent (red): D
779
        //                       /                    \_
780
        //      Parent (black): B                      Uncle (black): E
781
        //             / \_
782
        // Tmp (red): A   black: C
783
        //
784
785
7.29k
        RedBlackTreeRotateRight (GrandParent, &NewRoot);
786
787
        //
788
        // Property #4 has been restored for node E, and preserved for others.
789
        //
790
        //              Parent (black): B
791
        //             /                 \_
792
        // Tmp (red): A                   [GrandParent] (red): D
793
        //                                         / \_
794
        //                                 black: C   [Uncle] (black): E
795
        //
796
        // This configuration terminates the loop because Tmp's parent is now
797
        // black.
798
        //
799
7.29k
      }
800
20.1k
    } else {
801
      //
802
      // Symmetrical to the other branch.
803
      //
804
20.1k
      Uncle = GrandParent->Left;
805
20.1k
      if ((Uncle != NULL) && (Uncle->Color == RedBlackTreeRed)) {
806
10.4k
        Parent->Color      = RedBlackTreeBlack;
807
10.4k
        Uncle->Color       = RedBlackTreeBlack;
808
10.4k
        GrandParent->Color = RedBlackTreeRed;
809
10.4k
        Tmp                = GrandParent;
810
10.4k
        Parent             = Tmp->Parent;
811
10.4k
      } else {
812
9.65k
        if (Tmp == Parent->Left) {
813
4.05k
          Tmp = Parent;
814
4.05k
          RedBlackTreeRotateRight (Tmp, &NewRoot);
815
4.05k
          Parent = Tmp->Parent;
816
4.05k
          ASSERT (GrandParent == Parent->Parent);
817
4.05k
        }
818
819
9.65k
        Parent->Color      = RedBlackTreeBlack;
820
9.65k
        GrandParent->Color = RedBlackTreeRed;
821
9.65k
        RedBlackTreeRotateLeft (GrandParent, &NewRoot);
822
9.65k
      }
823
20.1k
    }
824
35.6k
  }
825
826
38.5k
  NewRoot->Color = RedBlackTreeBlack;
827
38.5k
  Tree->Root     = NewRoot;
828
38.5k
  Status         = RETURN_SUCCESS;
829
830
44.7k
Done:
831
44.7k
  if (FeaturePcdGet (PcdValidateOrderedCollection)) {
832
0
    RedBlackTreeValidate (Tree);
833
0
  }
834
835
44.7k
  return Status;
836
38.5k
}
837
838
/**
839
  Check if a node is black, allowing for leaf nodes (see property #2).
840
841
  This is a convenience shorthand.
842
843
  param[in] Node  The node to check. Node may be NULL, corresponding to a leaf.
844
845
  @return  If Node is NULL or colored black.
846
**/
847
BOOLEAN
848
NodeIsNullOrBlack (
849
  IN CONST RED_BLACK_TREE_NODE  *Node
850
  )
851
116k
{
852
116k
  return (BOOLEAN)(Node == NULL || Node->Color == RedBlackTreeBlack);
853
116k
}
854
855
/**
856
  Delete a node from the tree, unlinking the associated user structure.
857
858
  Read-write operation.
859
860
  @param[in,out] Tree        The tree to delete Node from.
861
862
  @param[in]     Node        The tree node to delete from Tree. The caller is
863
                             responsible for ensuring that Node belongs to
864
                             Tree, and that Node is non-NULL and valid. Node is
865
                             typically an earlier return value, or output
866
                             parameter, of:
867
868
                             - OrderedCollectionFind(), for deleting a node by
869
                               user structure key,
870
871
                             - OrderedCollectionMin() / OrderedCollectionMax(),
872
                               for deleting the minimum / maximum node,
873
874
                             - OrderedCollectionNext() /
875
                               OrderedCollectionPrev(), for deleting a node
876
                               found during an iteration,
877
878
                             - OrderedCollectionInsert() with return value
879
                               RETURN_ALREADY_STARTED, for deleting a node
880
                               whose linked user structure caused collision
881
                               during insertion.
882
883
                             Given a non-empty Tree, Tree->Root is also a valid
884
                             Node argument (typically used for simplicity in
885
                             loops that empty the tree completely).
886
887
                             Node is released with MemoryAllocationLib's
888
                             FreePool() function.
889
890
                             Existing RED_BLACK_TREE_NODE pointers (ie.
891
                             iterators) *different* from Node remain valid. For
892
                             example:
893
894
                             - OrderedCollectionNext() /
895
                               OrderedCollectionPrev() iterations in the caller
896
                               can be continued from Node, if
897
                               OrderedCollectionNext() or
898
                               OrderedCollectionPrev() is called on Node
899
                               *before* OrderedCollectionDelete() is. That is,
900
                               fetch the successor / predecessor node first,
901
                               then delete Node.
902
903
                             - On-going iterations in the caller that would
904
                               have otherwise returned Node at some point, as
905
                               dictated by user structure order, will correctly
906
                               reflect the absence of Node after
907
                               OrderedCollectionDelete() is called
908
                               mid-iteration.
909
910
  @param[out]    UserStruct  If the caller provides this optional output-only
911
                             parameter, then on output it is set to the user
912
                             structure originally linked by Node (which is now
913
                             freed).
914
915
                             This is a convenience that may save the caller a
916
                             OrderedCollectionUserStruct() invocation before
917
                             calling OrderedCollectionDelete(), in order to
918
                             retrieve the user structure being unlinked.
919
**/
920
VOID
921
EFIAPI
922
OrderedCollectionDelete (
923
  IN OUT RED_BLACK_TREE       *Tree,
924
  IN     RED_BLACK_TREE_NODE  *Node,
925
  OUT    VOID                 **UserStruct OPTIONAL
926
  )
927
40.1k
{
928
40.1k
  RED_BLACK_TREE_NODE   *NewRoot;
929
40.1k
  RED_BLACK_TREE_NODE   *OrigLeftChild;
930
40.1k
  RED_BLACK_TREE_NODE   *OrigRightChild;
931
40.1k
  RED_BLACK_TREE_NODE   *OrigParent;
932
40.1k
  RED_BLACK_TREE_NODE   *Child;
933
40.1k
  RED_BLACK_TREE_NODE   *Parent;
934
40.1k
  RED_BLACK_TREE_COLOR  ColorOfUnlinked;
935
936
40.1k
  NewRoot        = Tree->Root;
937
40.1k
  OrigLeftChild  = Node->Left,
938
40.1k
  OrigRightChild = Node->Right,
939
40.1k
  OrigParent     = Node->Parent;
940
941
40.1k
  if (UserStruct != NULL) {
942
39.9k
    *UserStruct = Node->UserStruct;
943
39.9k
  }
944
945
  //
946
  // After this block, no matter which branch we take:
947
  // - Child will point to the unique (or NULL) original child of the node that
948
  //   we will have unlinked,
949
  // - Parent will point to the *position* of the original parent of the node
950
  //   that we will have unlinked.
951
  //
952
40.1k
  if ((OrigLeftChild == NULL) || (OrigRightChild == NULL)) {
953
    //
954
    // Node has at most one child. We can connect that child (if any) with
955
    // Node's parent (if any), unlinking Node. This will preserve ordering
956
    // because the subtree rooted in Node's child (if any) remains on the same
957
    // side of Node's parent (if any) that Node was before.
958
    //
959
40.0k
    Parent          = OrigParent;
960
40.0k
    Child           = (OrigLeftChild != NULL) ? OrigLeftChild : OrigRightChild;
961
40.0k
    ColorOfUnlinked = Node->Color;
962
963
40.0k
    if (Child != NULL) {
964
16.6k
      Child->Parent = Parent;
965
16.6k
    }
966
967
40.0k
    if (OrigParent == NULL) {
968
3.05k
      NewRoot = Child;
969
37.0k
    } else {
970
37.0k
      if (Node == OrigParent->Left) {
971
36.9k
        OrigParent->Left = Child;
972
36.9k
      } else {
973
60
        OrigParent->Right = Child;
974
60
      }
975
37.0k
    }
976
40.0k
  } else {
977
    //
978
    // Node has two children. We unlink Node's successor, and then link it into
979
    // Node's place, keeping Node's original color. This preserves ordering
980
    // because:
981
    // - Node's left subtree is less than Node, hence less than Node's
982
    //   successor.
983
    // - Node's right subtree is greater than Node. Node's successor is the
984
    //   minimum of that subtree, hence Node's successor is less than Node's
985
    //   right subtree with its minimum removed.
986
    // - Node's successor is in Node's subtree, hence it falls on the same side
987
    //   of Node's parent as Node itself. The relinking doesn't change this
988
    //   relation.
989
    //
990
26
    RED_BLACK_TREE_NODE  *ToRelink;
991
992
26
    ToRelink = OrigRightChild;
993
26
    if (ToRelink->Left == NULL) {
994
      //
995
      // OrigRightChild itself is Node's successor, it has no left child:
996
      //
997
      //                OrigParent
998
      //                    |
999
      //                  Node: B
1000
      //                 /       \_
1001
      // OrigLeftChild: A         OrigRightChild: E <--- Parent, ToRelink
1002
      //                                           \_
1003
      //                                            F <--- Child
1004
      //
1005
26
      Parent = OrigRightChild;
1006
26
      Child  = OrigRightChild->Right;
1007
26
    } else {
1008
0
      do {
1009
0
        ToRelink = ToRelink->Left;
1010
0
      } while (ToRelink->Left != NULL);
1011
1012
      //
1013
      // Node's successor is the minimum of OrigRightChild's proper subtree:
1014
      //
1015
      //                OrigParent
1016
      //                    |
1017
      //                  Node: B
1018
      //                 /       \_
1019
      // OrigLeftChild: A         OrigRightChild: E <--- Parent
1020
      //                                  /
1021
      //                                 C <--- ToRelink
1022
      //                                  \_
1023
      //                                   D <--- Child
1024
0
      Parent = ToRelink->Parent;
1025
0
      Child  = ToRelink->Right;
1026
1027
      //
1028
      // Unlink Node's successor (ie. ToRelink):
1029
      //
1030
      //                OrigParent
1031
      //                    |
1032
      //                  Node: B
1033
      //                 /       \_
1034
      // OrigLeftChild: A         OrigRightChild: E <--- Parent
1035
      //                                  /
1036
      //                                 D <--- Child
1037
      //
1038
      //                                 C <--- ToRelink
1039
      //
1040
0
      Parent->Left = Child;
1041
0
      if (Child != NULL) {
1042
0
        Child->Parent = Parent;
1043
0
      }
1044
1045
      //
1046
      // We start to link Node's unlinked successor into Node's place:
1047
      //
1048
      //                OrigParent
1049
      //                    |
1050
      //                  Node: B     C <--- ToRelink
1051
      //                 /             \_
1052
      // OrigLeftChild: A               OrigRightChild: E <--- Parent
1053
      //                                        /
1054
      //                                       D <--- Child
1055
      //
1056
      //
1057
      //
1058
0
      ToRelink->Right        = OrigRightChild;
1059
0
      OrigRightChild->Parent = ToRelink;
1060
0
    }
1061
1062
    //
1063
    // The rest handles both cases, attaching ToRelink (Node's original
1064
    // successor) to OrigLeftChild and OrigParent.
1065
    //
1066
    //                           Parent,
1067
    //              OrigParent   ToRelink             OrigParent
1068
    //                  |        |                        |
1069
    //                Node: B    |                      Node: B          Parent
1070
    //                           v                                          |
1071
    //           OrigRightChild: E                        C <--- ToRelink   |
1072
    //                 / \                               / \                v
1073
    // OrigLeftChild: A   F              OrigLeftChild: A   OrigRightChild: E
1074
    //                    ^                                         /
1075
    //                    |                                        D <--- Child
1076
    //                  Child
1077
    //
1078
26
    ToRelink->Left        = OrigLeftChild;
1079
26
    OrigLeftChild->Parent = ToRelink;
1080
1081
    //
1082
    // Node's color must be preserved in Node's original place.
1083
    //
1084
26
    ColorOfUnlinked = ToRelink->Color;
1085
26
    ToRelink->Color = Node->Color;
1086
1087
    //
1088
    // Finish linking Node's unlinked successor into Node's place.
1089
    //
1090
    //                           Parent,
1091
    //                Node: B    ToRelink               Node: B
1092
    //                           |
1093
    //              OrigParent   |                    OrigParent         Parent
1094
    //                  |        v                        |                 |
1095
    //           OrigRightChild: E                        C <--- ToRelink   |
1096
    //                 / \                               / \                v
1097
    // OrigLeftChild: A   F              OrigLeftChild: A   OrigRightChild: E
1098
    //                    ^                                         /
1099
    //                    |                                        D <--- Child
1100
    //                  Child
1101
    //
1102
26
    ToRelink->Parent = OrigParent;
1103
26
    if (OrigParent == NULL) {
1104
2
      NewRoot = ToRelink;
1105
24
    } else {
1106
24
      if (Node == OrigParent->Left) {
1107
4
        OrigParent->Left = ToRelink;
1108
20
      } else {
1109
20
        OrigParent->Right = ToRelink;
1110
20
      }
1111
24
    }
1112
26
  }
1113
1114
40.1k
  FreePool (Node);
1115
1116
  //
1117
  // If the node that we unlinked from its original spot (ie. Node itself, or
1118
  // Node's successor), was red, then we broke neither property #3 nor property
1119
  // #4: we didn't create any red-red edge between Child and Parent, and we
1120
  // didn't change the black count on any path.
1121
  //
1122
40.1k
  if (ColorOfUnlinked == RedBlackTreeBlack) {
1123
    //
1124
    // However, if the unlinked node was black, then we have to transfer its
1125
    // "black-increment" to its unique child (pointed-to by Child), lest we
1126
    // break property #4 for its ancestors.
1127
    //
1128
    // If Child is red, we can simply color it black. If Child is black
1129
    // already, we can't technically transfer a black-increment to it, due to
1130
    // property #1.
1131
    //
1132
    // In the following loop we ascend searching for a red node to color black,
1133
    // or until we reach the root (in which case we can drop the
1134
    // black-increment). Inside the loop body, Child has a black value of 2,
1135
    // transitorily breaking property #1 locally, but maintaining property #4
1136
    // globally.
1137
    //
1138
    // Rotations in the loop preserve property #4.
1139
    //
1140
69.3k
    while (Child != NewRoot && NodeIsNullOrBlack (Child)) {
1141
29.8k
      RED_BLACK_TREE_NODE  *Sibling;
1142
29.8k
      RED_BLACK_TREE_NODE  *LeftNephew;
1143
29.8k
      RED_BLACK_TREE_NODE  *RightNephew;
1144
1145
29.8k
      if (Child == Parent->Left) {
1146
29.8k
        Sibling = Parent->Right;
1147
        //
1148
        // Sibling can never be NULL (ie. a leaf).
1149
        //
1150
        // If Sibling was NULL, then the black count on the path from Parent to
1151
        // Sibling would equal Parent's black value, plus 1 (due to property
1152
        // #2). Whereas the black count on the path from Parent to any leaf via
1153
        // Child would be at least Parent's black value, plus 2 (due to Child's
1154
        // black value of 2). This would clash with property #4.
1155
        //
1156
        // (Sibling can be black of course, but it has to be an internal node.
1157
        // Internality allows Sibling to have children, bumping the black
1158
        // counts of paths that go through it.)
1159
        //
1160
29.8k
        ASSERT (Sibling != NULL);
1161
29.8k
        if (Sibling->Color == RedBlackTreeRed) {
1162
          //
1163
          // Sibling's red color implies its children (if any), node C and node
1164
          // E, are black (property #3). It also implies that Parent is black.
1165
          //
1166
          //           grandparent                                 grandparent
1167
          //                |                                           |
1168
          //            Parent,b:B                                     b:D
1169
          //           /          \                                   /   \_
1170
          // Child,2b:A            Sibling,r:D  --->        Parent,r:B     b:E
1171
          //                           /\                       /\_
1172
          //                        b:C  b:E          Child,2b:A  Sibling,b:C
1173
          //
1174
7.17k
          Sibling->Color = RedBlackTreeBlack;
1175
7.17k
          Parent->Color  = RedBlackTreeRed;
1176
7.17k
          RedBlackTreeRotateLeft (Parent, &NewRoot);
1177
7.17k
          Sibling = Parent->Right;
1178
          //
1179
          // Same reasoning as above.
1180
          //
1181
7.17k
          ASSERT (Sibling != NULL);
1182
7.17k
        }
1183
1184
        //
1185
        // Sibling is black, and not NULL. (Ie. Sibling is a black internal
1186
        // node.)
1187
        //
1188
29.8k
        ASSERT (Sibling->Color == RedBlackTreeBlack);
1189
29.8k
        LeftNephew  = Sibling->Left;
1190
29.8k
        RightNephew = Sibling->Right;
1191
29.8k
        if (NodeIsNullOrBlack (LeftNephew) &&
1192
22.7k
            NodeIsNullOrBlack (RightNephew))
1193
18.7k
        {
1194
          //
1195
          // In this case we can "steal" one black value from Child and Sibling
1196
          // each, and pass it to Parent. "Stealing" means that Sibling (black
1197
          // value 1) becomes red, Child (black value 2) becomes singly-black,
1198
          // and Parent will have to be examined if it can eat the
1199
          // black-increment.
1200
          //
1201
          // Sibling is allowed to become red because both of its children are
1202
          // black (property #3).
1203
          //
1204
          //           grandparent                             Parent
1205
          //                |                                     |
1206
          //            Parent,x:B                            Child,x:B
1207
          //           /          \                          /         \_
1208
          // Child,2b:A            Sibling,b:D    --->    b:A           r:D
1209
          //                           /\                                /\_
1210
          //             LeftNephew,b:C  RightNephew,b:E              b:C  b:E
1211
          //
1212
18.7k
          Sibling->Color = RedBlackTreeRed;
1213
18.7k
          Child          = Parent;
1214
18.7k
          Parent         = Parent->Parent;
1215
          //
1216
          // Continue ascending.
1217
          //
1218
18.7k
        } else {
1219
          //
1220
          // At least one nephew is red.
1221
          //
1222
11.1k
          if (NodeIsNullOrBlack (RightNephew)) {
1223
            //
1224
            // Since the right nephew is black, the left nephew is red. Due to
1225
            // property #3, LeftNephew has two black children, hence node E is
1226
            // black.
1227
            //
1228
            // Together with the rotation, this enables us to color node F red
1229
            // (because property #3 will be satisfied). We flip node D to black
1230
            // to maintain property #4.
1231
            //
1232
            //      grandparent                         grandparent
1233
            //           |                                   |
1234
            //       Parent,x:B                          Parent,x:B
1235
            //           /\                                  /\_
1236
            // Child,2b:A  Sibling,b:F     --->    Child,2b:A  Sibling,b:D
1237
            //                  /\                            /   \_
1238
            //    LeftNephew,r:D  RightNephew,b:G          b:C  RightNephew,r:F
1239
            //               /\                                       /\_
1240
            //            b:C  b:E                                 b:E  b:G
1241
            //
1242
3.51k
            LeftNephew->Color = RedBlackTreeBlack;
1243
3.51k
            Sibling->Color    = RedBlackTreeRed;
1244
3.51k
            RedBlackTreeRotateRight (Sibling, &NewRoot);
1245
3.51k
            Sibling     = Parent->Right;
1246
3.51k
            RightNephew = Sibling->Right;
1247
            //
1248
            // These operations ensure that...
1249
            //
1250
3.51k
          }
1251
1252
          //
1253
          // ... RightNephew is definitely red here, plus Sibling is (still)
1254
          // black and non-NULL.
1255
          //
1256
11.1k
          ASSERT (RightNephew != NULL);
1257
11.1k
          ASSERT (RightNephew->Color == RedBlackTreeRed);
1258
11.1k
          ASSERT (Sibling != NULL);
1259
11.1k
          ASSERT (Sibling->Color == RedBlackTreeBlack);
1260
          //
1261
          // In this case we can flush the extra black-increment immediately,
1262
          // restoring property #1 for Child (node A): we color RightNephew
1263
          // (node E) from red to black.
1264
          //
1265
          // In order to maintain property #4, we exchange colors between
1266
          // Parent and Sibling (nodes B and D), and rotate left around Parent
1267
          // (node B). The transformation doesn't change the black count
1268
          // increase incurred by each partial path, eg.
1269
          // - ascending from node A: 2 + x     == 1 + 1 + x
1270
          // - ascending from node C: y + 1 + x == y + 1 + x
1271
          // - ascending from node E: 0 + 1 + x == 1 + x
1272
          //
1273
          // The color exchange is valid, because even if x stands for red,
1274
          // both children of node D are black after the transformation
1275
          // (preserving property #3).
1276
          //
1277
          //           grandparent                                  grandparent
1278
          //                |                                            |
1279
          //            Parent,x:B                                      x:D
1280
          //           /          \                                    /   \_
1281
          // Child,2b:A            Sibling,b:D              --->    b:B     b:E
1282
          //                         /     \                       /   \_
1283
          //                      y:C       RightNephew,r:E     b:A     y:C
1284
          //
1285
          //
1286
11.1k
          Sibling->Color     = Parent->Color;
1287
11.1k
          Parent->Color      = RedBlackTreeBlack;
1288
11.1k
          RightNephew->Color = RedBlackTreeBlack;
1289
11.1k
          RedBlackTreeRotateLeft (Parent, &NewRoot);
1290
11.1k
          Child = NewRoot;
1291
          //
1292
          // This terminates the loop.
1293
          //
1294
11.1k
        }
1295
29.8k
      } else {
1296
        //
1297
        // Mirrors the other branch.
1298
        //
1299
0
        Sibling = Parent->Left;
1300
0
        ASSERT (Sibling != NULL);
1301
0
        if (Sibling->Color == RedBlackTreeRed) {
1302
0
          Sibling->Color = RedBlackTreeBlack;
1303
0
          Parent->Color  = RedBlackTreeRed;
1304
0
          RedBlackTreeRotateRight (Parent, &NewRoot);
1305
0
          Sibling = Parent->Left;
1306
0
          ASSERT (Sibling != NULL);
1307
0
        }
1308
1309
0
        ASSERT (Sibling->Color == RedBlackTreeBlack);
1310
0
        RightNephew = Sibling->Right;
1311
0
        LeftNephew  = Sibling->Left;
1312
0
        if (NodeIsNullOrBlack (RightNephew) &&
1313
0
            NodeIsNullOrBlack (LeftNephew))
1314
0
        {
1315
0
          Sibling->Color = RedBlackTreeRed;
1316
0
          Child          = Parent;
1317
0
          Parent         = Parent->Parent;
1318
0
        } else {
1319
0
          if (NodeIsNullOrBlack (LeftNephew)) {
1320
0
            RightNephew->Color = RedBlackTreeBlack;
1321
0
            Sibling->Color     = RedBlackTreeRed;
1322
0
            RedBlackTreeRotateLeft (Sibling, &NewRoot);
1323
0
            Sibling    = Parent->Left;
1324
0
            LeftNephew = Sibling->Left;
1325
0
          }
1326
1327
0
          ASSERT (LeftNephew != NULL);
1328
0
          ASSERT (LeftNephew->Color == RedBlackTreeRed);
1329
0
          ASSERT (Sibling != NULL);
1330
0
          ASSERT (Sibling->Color == RedBlackTreeBlack);
1331
0
          Sibling->Color    = Parent->Color;
1332
0
          Parent->Color     = RedBlackTreeBlack;
1333
0
          LeftNephew->Color = RedBlackTreeBlack;
1334
0
          RedBlackTreeRotateRight (Parent, &NewRoot);
1335
0
          Child = NewRoot;
1336
0
        }
1337
0
      }
1338
29.8k
    }
1339
1340
39.5k
    if (Child != NULL) {
1341
37.9k
      Child->Color = RedBlackTreeBlack;
1342
37.9k
    }
1343
39.5k
  }
1344
1345
40.1k
  Tree->Root = NewRoot;
1346
1347
40.1k
  if (FeaturePcdGet (PcdValidateOrderedCollection)) {
1348
0
    RedBlackTreeValidate (Tree);
1349
0
  }
1350
40.1k
}
1351
1352
/**
1353
  Recursively check the red-black tree properties #1 to #4 on a node.
1354
1355
  @param[in] Node  The root of the subtree to validate.
1356
1357
  @retval  The black-height of Node's parent.
1358
**/
1359
UINT32
1360
RedBlackTreeRecursiveCheck (
1361
  IN CONST RED_BLACK_TREE_NODE  *Node
1362
  )
1363
0
{
1364
0
  UINT32  LeftHeight;
1365
0
  UINT32  RightHeight;
1366
1367
  //
1368
  // property #2
1369
  //
1370
0
  if (Node == NULL) {
1371
0
    return 1;
1372
0
  }
1373
1374
  //
1375
  // property #1
1376
  //
1377
0
  ASSERT (Node->Color == RedBlackTreeRed || Node->Color == RedBlackTreeBlack);
1378
1379
  //
1380
  // property #3
1381
  //
1382
0
  if (Node->Color == RedBlackTreeRed) {
1383
0
    ASSERT (NodeIsNullOrBlack (Node->Left));
1384
0
    ASSERT (NodeIsNullOrBlack (Node->Right));
1385
0
  }
1386
1387
  //
1388
  // property #4
1389
  //
1390
0
  LeftHeight  = RedBlackTreeRecursiveCheck (Node->Left);
1391
0
  RightHeight = RedBlackTreeRecursiveCheck (Node->Right);
1392
0
  ASSERT (LeftHeight == RightHeight);
1393
1394
0
  return (Node->Color == RedBlackTreeBlack) + LeftHeight;
1395
0
}
1396
1397
/**
1398
  A slow function that asserts that the tree is a valid red-black tree, and
1399
  that it orders user structures correctly.
1400
1401
  Read-only operation.
1402
1403
  This function uses the stack for recursion and is not recommended for
1404
  "production use".
1405
1406
  @param[in] Tree  The tree to validate.
1407
**/
1408
VOID
1409
RedBlackTreeValidate (
1410
  IN CONST RED_BLACK_TREE  *Tree
1411
  )
1412
0
{
1413
0
  UINT32                     BlackHeight;
1414
0
  UINT32                     ForwardCount;
1415
0
  UINT32                     BackwardCount;
1416
0
  CONST RED_BLACK_TREE_NODE  *Last;
1417
0
  CONST RED_BLACK_TREE_NODE  *Node;
1418
1419
0
  DEBUG ((DEBUG_VERBOSE, "%a: Tree=%p\n", __func__, Tree));
1420
1421
  //
1422
  // property #5
1423
  //
1424
0
  ASSERT (NodeIsNullOrBlack (Tree->Root));
1425
1426
  //
1427
  // check the other properties
1428
  //
1429
0
  BlackHeight = RedBlackTreeRecursiveCheck (Tree->Root) - 1;
1430
1431
  //
1432
  // forward ordering
1433
  //
1434
0
  Last         = OrderedCollectionMin (Tree);
1435
0
  ForwardCount = (Last != NULL);
1436
0
  for (Node = OrderedCollectionNext (Last); Node != NULL;
1437
0
       Node = OrderedCollectionNext (Last))
1438
0
  {
1439
0
    ASSERT (Tree->UserStructCompare (Last->UserStruct, Node->UserStruct) < 0);
1440
0
    Last = Node;
1441
0
    ++ForwardCount;
1442
0
  }
1443
1444
  //
1445
  // backward ordering
1446
  //
1447
0
  Last          = OrderedCollectionMax (Tree);
1448
0
  BackwardCount = (Last != NULL);
1449
0
  for (Node = OrderedCollectionPrev (Last); Node != NULL;
1450
0
       Node = OrderedCollectionPrev (Last))
1451
0
  {
1452
0
    ASSERT (Tree->UserStructCompare (Last->UserStruct, Node->UserStruct) > 0);
1453
0
    Last = Node;
1454
0
    ++BackwardCount;
1455
0
  }
1456
1457
0
  ASSERT (ForwardCount == BackwardCount);
1458
1459
0
  DEBUG ((
1460
0
    DEBUG_VERBOSE,
1461
0
    "%a: Tree=%p BlackHeight=%Ld Count=%Ld\n",
1462
0
    __func__,
1463
0
    Tree,
1464
0
    (INT64)BlackHeight,
1465
0
    (INT64)ForwardCount
1466
0
    ));
1467
0
}