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