REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1468 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1468 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  An OrderedCollectionLib instance that provides a red-black tree
 | 
						|
  implementation, and allocates and releases tree nodes with
 | 
						|
  MemoryAllocationLib.
 | 
						|
 | 
						|
  This library instance is useful when a fast associative container is needed.
 | 
						|
  Worst case time complexity is O(log n) for Find(), Next(), Prev(), Min(),
 | 
						|
  Max(), Insert(), and Delete(), where "n" is the number of elements in the
 | 
						|
  tree. Complete ordered traversal takes O(n) time.
 | 
						|
 | 
						|
  The implementation is also useful as a fast priority queue.
 | 
						|
 | 
						|
  Copyright (C) 2014, Red Hat, Inc.
 | 
						|
  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
**/
 | 
						|
 | 
						|
#include <Library/OrderedCollectionLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  RedBlackTreeRed,
 | 
						|
  RedBlackTreeBlack
 | 
						|
} RED_BLACK_TREE_COLOR;
 | 
						|
 | 
						|
//
 | 
						|
// Incomplete types and convenience typedefs are present in the library class
 | 
						|
// header. Beside completing the types, we introduce typedefs here that reflect
 | 
						|
// the implementation closely.
 | 
						|
//
 | 
						|
typedef ORDERED_COLLECTION               RED_BLACK_TREE;
 | 
						|
typedef ORDERED_COLLECTION_ENTRY         RED_BLACK_TREE_NODE;
 | 
						|
typedef ORDERED_COLLECTION_USER_COMPARE  RED_BLACK_TREE_USER_COMPARE;
 | 
						|
typedef ORDERED_COLLECTION_KEY_COMPARE   RED_BLACK_TREE_KEY_COMPARE;
 | 
						|
 | 
						|
struct ORDERED_COLLECTION {
 | 
						|
  RED_BLACK_TREE_NODE            *Root;
 | 
						|
  RED_BLACK_TREE_USER_COMPARE    UserStructCompare;
 | 
						|
  RED_BLACK_TREE_KEY_COMPARE     KeyCompare;
 | 
						|
};
 | 
						|
 | 
						|
struct ORDERED_COLLECTION_ENTRY {
 | 
						|
  VOID                    *UserStruct;
 | 
						|
  RED_BLACK_TREE_NODE     *Parent;
 | 
						|
  RED_BLACK_TREE_NODE     *Left;
 | 
						|
  RED_BLACK_TREE_NODE     *Right;
 | 
						|
  RED_BLACK_TREE_COLOR    Color;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieve the user structure linked by the specified tree node.
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  @param[in] Node  Pointer to the tree node whose associated user structure we
 | 
						|
                   want to retrieve. The caller is responsible for passing a
 | 
						|
                   non-NULL argument.
 | 
						|
 | 
						|
  @return  Pointer to user structure linked by Node.
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionUserStruct (
 | 
						|
  IN CONST RED_BLACK_TREE_NODE  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  return Node->UserStruct;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  A slow function that asserts that the tree is a valid red-black tree, and
 | 
						|
  that it orders user structures correctly.
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  This function uses the stack for recursion and is not recommended for
 | 
						|
  "production use".
 | 
						|
 | 
						|
  @param[in] Tree  The tree to validate.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RedBlackTreeValidate (
 | 
						|
  IN CONST RED_BLACK_TREE  *Tree
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Allocate and initialize the RED_BLACK_TREE structure.
 | 
						|
 | 
						|
  Allocation occurs via MemoryAllocationLib's AllocatePool() function.
 | 
						|
 | 
						|
  @param[in]  UserStructCompare  This caller-provided function will be used to
 | 
						|
                                 order two user structures linked into the
 | 
						|
                                 tree, during the insertion procedure.
 | 
						|
 | 
						|
  @param[in]  KeyCompare         This caller-provided function will be used to
 | 
						|
                                 order the standalone search key against user
 | 
						|
                                 structures linked into the tree, during the
 | 
						|
                                 lookup procedure.
 | 
						|
 | 
						|
  @retval NULL  If allocation failed.
 | 
						|
 | 
						|
  @return       Pointer to the allocated, initialized RED_BLACK_TREE structure,
 | 
						|
                otherwise.
 | 
						|
**/
 | 
						|
RED_BLACK_TREE *
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionInit (
 | 
						|
  IN RED_BLACK_TREE_USER_COMPARE  UserStructCompare,
 | 
						|
  IN RED_BLACK_TREE_KEY_COMPARE   KeyCompare
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE  *Tree;
 | 
						|
 | 
						|
  Tree = AllocatePool (sizeof *Tree);
 | 
						|
  if (Tree == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Tree->Root              = NULL;
 | 
						|
  Tree->UserStructCompare = UserStructCompare;
 | 
						|
  Tree->KeyCompare        = KeyCompare;
 | 
						|
 | 
						|
  if (FeaturePcdGet (PcdValidateOrderedCollection)) {
 | 
						|
    RedBlackTreeValidate (Tree);
 | 
						|
  }
 | 
						|
 | 
						|
  return Tree;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether the tree is empty (has no nodes).
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  @param[in] Tree  The tree to check for emptiness.
 | 
						|
 | 
						|
  @retval TRUE   The tree is empty.
 | 
						|
 | 
						|
  @retval FALSE  The tree is not empty.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionIsEmpty (
 | 
						|
  IN CONST RED_BLACK_TREE  *Tree
 | 
						|
  )
 | 
						|
{
 | 
						|
  return (BOOLEAN)(Tree->Root == NULL);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Uninitialize and release an empty RED_BLACK_TREE structure.
 | 
						|
 | 
						|
  Read-write operation.
 | 
						|
 | 
						|
  Release occurs via MemoryAllocationLib's FreePool() function.
 | 
						|
 | 
						|
  It is the caller's responsibility to delete all nodes from the tree before
 | 
						|
  calling this function.
 | 
						|
 | 
						|
  @param[in] Tree  The empty tree to uninitialize and release.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionUninit (
 | 
						|
  IN RED_BLACK_TREE  *Tree
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT (OrderedCollectionIsEmpty (Tree));
 | 
						|
  FreePool (Tree);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Look up the tree node that links the user structure that matches the
 | 
						|
  specified standalone key.
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  @param[in] Tree           The tree to search for StandaloneKey.
 | 
						|
 | 
						|
  @param[in] StandaloneKey  The key to locate among the user structures linked
 | 
						|
                            into Tree. StandaloneKey will be passed to
 | 
						|
                            Tree->KeyCompare().
 | 
						|
 | 
						|
  @retval NULL  StandaloneKey could not be found.
 | 
						|
 | 
						|
  @return       The tree node that links to the user structure matching
 | 
						|
                StandaloneKey, otherwise.
 | 
						|
**/
 | 
						|
RED_BLACK_TREE_NODE *
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionFind (
 | 
						|
  IN CONST RED_BLACK_TREE  *Tree,
 | 
						|
  IN CONST VOID            *StandaloneKey
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE  *Node;
 | 
						|
 | 
						|
  Node = Tree->Root;
 | 
						|
  while (Node != NULL) {
 | 
						|
    INTN  Result;
 | 
						|
 | 
						|
    Result = Tree->KeyCompare (StandaloneKey, Node->UserStruct);
 | 
						|
    if (Result == 0) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Node = (Result < 0) ? Node->Left : Node->Right;
 | 
						|
  }
 | 
						|
 | 
						|
  return Node;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find the tree node of the minimum user structure stored in the tree.
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  @param[in] Tree  The tree to return the minimum node of. The user structure
 | 
						|
                   linked by the minimum node compares less than all other user
 | 
						|
                   structures in the tree.
 | 
						|
 | 
						|
  @retval NULL  If Tree is empty.
 | 
						|
 | 
						|
  @return       The tree node that links the minimum user structure, otherwise.
 | 
						|
**/
 | 
						|
RED_BLACK_TREE_NODE *
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionMin (
 | 
						|
  IN CONST RED_BLACK_TREE  *Tree
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE  *Node;
 | 
						|
 | 
						|
  Node = Tree->Root;
 | 
						|
  if (Node == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  while (Node->Left != NULL) {
 | 
						|
    Node = Node->Left;
 | 
						|
  }
 | 
						|
 | 
						|
  return Node;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find the tree node of the maximum user structure stored in the tree.
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  @param[in] Tree  The tree to return the maximum node of. The user structure
 | 
						|
                   linked by the maximum node compares greater than all other
 | 
						|
                   user structures in the tree.
 | 
						|
 | 
						|
  @retval NULL  If Tree is empty.
 | 
						|
 | 
						|
  @return       The tree node that links the maximum user structure, otherwise.
 | 
						|
**/
 | 
						|
RED_BLACK_TREE_NODE *
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionMax (
 | 
						|
  IN CONST RED_BLACK_TREE  *Tree
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE  *Node;
 | 
						|
 | 
						|
  Node = Tree->Root;
 | 
						|
  if (Node == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  while (Node->Right != NULL) {
 | 
						|
    Node = Node->Right;
 | 
						|
  }
 | 
						|
 | 
						|
  return Node;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the tree node of the least user structure that is greater than the one
 | 
						|
  linked by Node.
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  @param[in] Node  The node to get the successor node of.
 | 
						|
 | 
						|
  @retval NULL  If Node is NULL, or Node is the maximum node of its containing
 | 
						|
                tree (ie. Node has no successor node).
 | 
						|
 | 
						|
  @return       The tree node linking the least user structure that is greater
 | 
						|
                than the one linked by Node, otherwise.
 | 
						|
**/
 | 
						|
RED_BLACK_TREE_NODE *
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionNext (
 | 
						|
  IN CONST RED_BLACK_TREE_NODE  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE        *Walk;
 | 
						|
  CONST RED_BLACK_TREE_NODE  *Child;
 | 
						|
 | 
						|
  if (Node == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If Node has a right subtree, then the successor is the minimum node of
 | 
						|
  // that subtree.
 | 
						|
  //
 | 
						|
  Walk = Node->Right;
 | 
						|
  if (Walk != NULL) {
 | 
						|
    while (Walk->Left != NULL) {
 | 
						|
      Walk = Walk->Left;
 | 
						|
    }
 | 
						|
 | 
						|
    return Walk;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Otherwise we have to ascend as long as we're our parent's right child (ie.
 | 
						|
  // ascending to the left).
 | 
						|
  //
 | 
						|
  Child = Node;
 | 
						|
  Walk  = Child->Parent;
 | 
						|
  while (Walk != NULL && Child == Walk->Right) {
 | 
						|
    Child = Walk;
 | 
						|
    Walk  = Child->Parent;
 | 
						|
  }
 | 
						|
 | 
						|
  return Walk;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the tree node of the greatest user structure that is less than the one
 | 
						|
  linked by Node.
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  @param[in] Node  The node to get the predecessor node of.
 | 
						|
 | 
						|
  @retval NULL  If Node is NULL, or Node is the minimum node of its containing
 | 
						|
                tree (ie. Node has no predecessor node).
 | 
						|
 | 
						|
  @return       The tree node linking the greatest user structure that is less
 | 
						|
                than the one linked by Node, otherwise.
 | 
						|
**/
 | 
						|
RED_BLACK_TREE_NODE *
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionPrev (
 | 
						|
  IN CONST RED_BLACK_TREE_NODE  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE        *Walk;
 | 
						|
  CONST RED_BLACK_TREE_NODE  *Child;
 | 
						|
 | 
						|
  if (Node == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If Node has a left subtree, then the predecessor is the maximum node of
 | 
						|
  // that subtree.
 | 
						|
  //
 | 
						|
  Walk = Node->Left;
 | 
						|
  if (Walk != NULL) {
 | 
						|
    while (Walk->Right != NULL) {
 | 
						|
      Walk = Walk->Right;
 | 
						|
    }
 | 
						|
 | 
						|
    return Walk;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Otherwise we have to ascend as long as we're our parent's left child (ie.
 | 
						|
  // ascending to the right).
 | 
						|
  //
 | 
						|
  Child = Node;
 | 
						|
  Walk  = Child->Parent;
 | 
						|
  while (Walk != NULL && Child == Walk->Left) {
 | 
						|
    Child = Walk;
 | 
						|
    Walk  = Child->Parent;
 | 
						|
  }
 | 
						|
 | 
						|
  return Walk;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Rotate tree nodes around Pivot to the right.
 | 
						|
 | 
						|
                Parent                       Parent
 | 
						|
                  |                            |
 | 
						|
                Pivot                      LeftChild
 | 
						|
               /     .                    .         \_
 | 
						|
      LeftChild       Node1   --->   Node2           Pivot
 | 
						|
         . \                                          / .
 | 
						|
    Node2   LeftRightChild              LeftRightChild   Node1
 | 
						|
 | 
						|
  The ordering Node2 < LeftChild < LeftRightChild < Pivot < Node1 is kept
 | 
						|
  intact. Parent (if any) is either at the left extreme or the right extreme of
 | 
						|
  this ordering, and that relation is also kept intact.
 | 
						|
 | 
						|
  Edges marked with a dot (".") don't change during rotation.
 | 
						|
 | 
						|
  Internal read-write operation.
 | 
						|
 | 
						|
  @param[in,out] Pivot    The tree node to rotate other nodes right around. It
 | 
						|
                          is the caller's responsibility to ensure that
 | 
						|
                          Pivot->Left is not NULL.
 | 
						|
 | 
						|
  @param[out]    NewRoot  If Pivot has a parent node on input, then the
 | 
						|
                          function updates Pivot's original parent on output
 | 
						|
                          according to the rotation, and NewRoot is not
 | 
						|
                          accessed.
 | 
						|
 | 
						|
                          If Pivot has no parent node on input (ie. Pivot is
 | 
						|
                          the root of the tree), then the function stores the
 | 
						|
                          new root node of the tree in NewRoot.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RedBlackTreeRotateRight (
 | 
						|
  IN OUT RED_BLACK_TREE_NODE  *Pivot,
 | 
						|
  OUT    RED_BLACK_TREE_NODE  **NewRoot
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE  *Parent;
 | 
						|
  RED_BLACK_TREE_NODE  *LeftChild;
 | 
						|
  RED_BLACK_TREE_NODE  *LeftRightChild;
 | 
						|
 | 
						|
  Parent         = Pivot->Parent;
 | 
						|
  LeftChild      = Pivot->Left;
 | 
						|
  LeftRightChild = LeftChild->Right;
 | 
						|
 | 
						|
  Pivot->Left = LeftRightChild;
 | 
						|
  if (LeftRightChild != NULL) {
 | 
						|
    LeftRightChild->Parent = Pivot;
 | 
						|
  }
 | 
						|
 | 
						|
  LeftChild->Parent = Parent;
 | 
						|
  if (Parent == NULL) {
 | 
						|
    *NewRoot = LeftChild;
 | 
						|
  } else {
 | 
						|
    if (Pivot == Parent->Left) {
 | 
						|
      Parent->Left = LeftChild;
 | 
						|
    } else {
 | 
						|
      Parent->Right = LeftChild;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  LeftChild->Right = Pivot;
 | 
						|
  Pivot->Parent    = LeftChild;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Rotate tree nodes around Pivot to the left.
 | 
						|
 | 
						|
          Parent                                 Parent
 | 
						|
            |                                      |
 | 
						|
          Pivot                                RightChild
 | 
						|
         .     \                              /          .
 | 
						|
    Node1       RightChild    --->       Pivot            Node2
 | 
						|
                    /.                    . \_
 | 
						|
      RightLeftChild  Node2          Node1   RightLeftChild
 | 
						|
 | 
						|
  The ordering Node1 < Pivot < RightLeftChild < RightChild < Node2 is kept
 | 
						|
  intact. Parent (if any) is either at the left extreme or the right extreme of
 | 
						|
  this ordering, and that relation is also kept intact.
 | 
						|
 | 
						|
  Edges marked with a dot (".") don't change during rotation.
 | 
						|
 | 
						|
  Internal read-write operation.
 | 
						|
 | 
						|
  @param[in,out] Pivot    The tree node to rotate other nodes left around. It
 | 
						|
                          is the caller's responsibility to ensure that
 | 
						|
                          Pivot->Right is not NULL.
 | 
						|
 | 
						|
  @param[out]    NewRoot  If Pivot has a parent node on input, then the
 | 
						|
                          function updates Pivot's original parent on output
 | 
						|
                          according to the rotation, and NewRoot is not
 | 
						|
                          accessed.
 | 
						|
 | 
						|
                          If Pivot has no parent node on input (ie. Pivot is
 | 
						|
                          the root of the tree), then the function stores the
 | 
						|
                          new root node of the tree in NewRoot.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RedBlackTreeRotateLeft (
 | 
						|
  IN OUT RED_BLACK_TREE_NODE  *Pivot,
 | 
						|
  OUT    RED_BLACK_TREE_NODE  **NewRoot
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE  *Parent;
 | 
						|
  RED_BLACK_TREE_NODE  *RightChild;
 | 
						|
  RED_BLACK_TREE_NODE  *RightLeftChild;
 | 
						|
 | 
						|
  Parent         = Pivot->Parent;
 | 
						|
  RightChild     = Pivot->Right;
 | 
						|
  RightLeftChild = RightChild->Left;
 | 
						|
 | 
						|
  Pivot->Right = RightLeftChild;
 | 
						|
  if (RightLeftChild != NULL) {
 | 
						|
    RightLeftChild->Parent = Pivot;
 | 
						|
  }
 | 
						|
 | 
						|
  RightChild->Parent = Parent;
 | 
						|
  if (Parent == NULL) {
 | 
						|
    *NewRoot = RightChild;
 | 
						|
  } else {
 | 
						|
    if (Pivot == Parent->Left) {
 | 
						|
      Parent->Left = RightChild;
 | 
						|
    } else {
 | 
						|
      Parent->Right = RightChild;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  RightChild->Left = Pivot;
 | 
						|
  Pivot->Parent    = RightChild;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert (link) a user structure into the tree.
 | 
						|
 | 
						|
  Read-write operation.
 | 
						|
 | 
						|
  This function allocates the new tree node with MemoryAllocationLib's
 | 
						|
  AllocatePool() function.
 | 
						|
 | 
						|
  @param[in,out] Tree        The tree to insert UserStruct into.
 | 
						|
 | 
						|
  @param[out]    Node        The meaning of this optional, output-only
 | 
						|
                             parameter depends on the return value of the
 | 
						|
                             function.
 | 
						|
 | 
						|
                             When insertion is successful (RETURN_SUCCESS),
 | 
						|
                             Node is set on output to the new tree node that
 | 
						|
                             now links UserStruct.
 | 
						|
 | 
						|
                             When insertion fails due to lack of memory
 | 
						|
                             (RETURN_OUT_OF_RESOURCES), Node is not changed.
 | 
						|
 | 
						|
                             When insertion fails due to key collision (ie.
 | 
						|
                             another user structure is already in the tree that
 | 
						|
                             compares equal to UserStruct), with return value
 | 
						|
                             RETURN_ALREADY_STARTED, then Node is set on output
 | 
						|
                             to the node that links the colliding user
 | 
						|
                             structure. This enables "find-or-insert" in one
 | 
						|
                             function call, or helps with later removal of the
 | 
						|
                             colliding element.
 | 
						|
 | 
						|
  @param[in]     UserStruct  The user structure to link into the tree.
 | 
						|
                             UserStruct is ordered against in-tree user
 | 
						|
                             structures with the Tree->UserStructCompare()
 | 
						|
                             function.
 | 
						|
 | 
						|
  @retval RETURN_SUCCESS           Insertion successful. A new tree node has
 | 
						|
                                   been allocated, linking UserStruct. The new
 | 
						|
                                   tree node is reported back in Node (if the
 | 
						|
                                   caller requested it).
 | 
						|
 | 
						|
                                   Existing RED_BLACK_TREE_NODE pointers into
 | 
						|
                                   Tree remain valid. For example, on-going
 | 
						|
                                   iterations in the caller can continue with
 | 
						|
                                   OrderedCollectionNext() /
 | 
						|
                                   OrderedCollectionPrev(), and they will
 | 
						|
                                   return the new node at some point if user
 | 
						|
                                   structure order dictates it.
 | 
						|
 | 
						|
  @retval RETURN_OUT_OF_RESOURCES  AllocatePool() failed to allocate memory for
 | 
						|
                                   the new tree node. The tree has not been
 | 
						|
                                   changed. Existing RED_BLACK_TREE_NODE
 | 
						|
                                   pointers into Tree remain valid.
 | 
						|
 | 
						|
  @retval RETURN_ALREADY_STARTED   A user structure has been found in the tree
 | 
						|
                                   that compares equal to UserStruct. The node
 | 
						|
                                   linking the colliding user structure is
 | 
						|
                                   reported back in Node (if the caller
 | 
						|
                                   requested it). The tree has not been
 | 
						|
                                   changed. Existing RED_BLACK_TREE_NODE
 | 
						|
                                   pointers into Tree remain valid.
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionInsert (
 | 
						|
  IN OUT RED_BLACK_TREE       *Tree,
 | 
						|
  OUT    RED_BLACK_TREE_NODE  **Node      OPTIONAL,
 | 
						|
  IN     VOID                 *UserStruct
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE  *Tmp;
 | 
						|
  RED_BLACK_TREE_NODE  *Parent;
 | 
						|
  INTN                 Result;
 | 
						|
  RETURN_STATUS        Status;
 | 
						|
  RED_BLACK_TREE_NODE  *NewRoot;
 | 
						|
 | 
						|
  Tmp    = Tree->Root;
 | 
						|
  Parent = NULL;
 | 
						|
  Result = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // First look for a collision, saving the last examined node for the case
 | 
						|
  // when there's no collision.
 | 
						|
  //
 | 
						|
  while (Tmp != NULL) {
 | 
						|
    Result = Tree->UserStructCompare (UserStruct, Tmp->UserStruct);
 | 
						|
    if (Result == 0) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Parent = Tmp;
 | 
						|
    Tmp    = (Result < 0) ? Tmp->Left : Tmp->Right;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Tmp != NULL) {
 | 
						|
    if (Node != NULL) {
 | 
						|
      *Node = Tmp;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = RETURN_ALREADY_STARTED;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // no collision, allocate a new node
 | 
						|
  //
 | 
						|
  Tmp = AllocatePool (sizeof *Tmp);
 | 
						|
  if (Tmp == NULL) {
 | 
						|
    Status = RETURN_OUT_OF_RESOURCES;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Node != NULL) {
 | 
						|
    *Node = Tmp;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // reference the user structure from the node
 | 
						|
  //
 | 
						|
  Tmp->UserStruct = UserStruct;
 | 
						|
 | 
						|
  //
 | 
						|
  // Link the node as a child to the correct side of the parent.
 | 
						|
  // If there's no parent, the new node is the root node in the tree.
 | 
						|
  //
 | 
						|
  Tmp->Parent = Parent;
 | 
						|
  Tmp->Left   = NULL;
 | 
						|
  Tmp->Right  = NULL;
 | 
						|
  if (Parent == NULL) {
 | 
						|
    Tree->Root = Tmp;
 | 
						|
    Tmp->Color = RedBlackTreeBlack;
 | 
						|
    Status     = RETURN_SUCCESS;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Result < 0) {
 | 
						|
    Parent->Left = Tmp;
 | 
						|
  } else {
 | 
						|
    Parent->Right = Tmp;
 | 
						|
  }
 | 
						|
 | 
						|
  Tmp->Color = RedBlackTreeRed;
 | 
						|
 | 
						|
  //
 | 
						|
  // Red-black tree properties:
 | 
						|
  //
 | 
						|
  // #1 Each node is either red or black (RED_BLACK_TREE_NODE.Color).
 | 
						|
  //
 | 
						|
  // #2 Each leaf (ie. a pseudo-node pointed-to by a NULL valued
 | 
						|
  //    RED_BLACK_TREE_NODE.Left or RED_BLACK_TREE_NODE.Right field) is black.
 | 
						|
  //
 | 
						|
  // #3 Each red node has two black children.
 | 
						|
  //
 | 
						|
  // #4 For any node N, and for any leaves L1 and L2 reachable from N, the
 | 
						|
  //    paths N..L1 and N..L2 contain the same number of black nodes.
 | 
						|
  //
 | 
						|
  // #5 The root node is black.
 | 
						|
  //
 | 
						|
  // By replacing a leaf with a red node above, only property #3 may have been
 | 
						|
  // broken. (Note that this is the only edge across which property #3 might
 | 
						|
  // not hold in the entire tree.) Restore property #3.
 | 
						|
  //
 | 
						|
 | 
						|
  NewRoot = Tree->Root;
 | 
						|
  while (Tmp != NewRoot && Parent->Color == RedBlackTreeRed) {
 | 
						|
    RED_BLACK_TREE_NODE  *GrandParent;
 | 
						|
    RED_BLACK_TREE_NODE  *Uncle;
 | 
						|
 | 
						|
    //
 | 
						|
    // Tmp is not the root node. Tmp is red. Tmp's parent is red. (Breaking
 | 
						|
    // property #3.)
 | 
						|
    //
 | 
						|
    // Due to property #5, Tmp's parent cannot be the root node, hence Tmp's
 | 
						|
    // grandparent exists.
 | 
						|
    //
 | 
						|
    // Tmp's grandparent is black, because property #3 is only broken between
 | 
						|
    // Tmp and Tmp's parent.
 | 
						|
    //
 | 
						|
    GrandParent = Parent->Parent;
 | 
						|
 | 
						|
    if (Parent == GrandParent->Left) {
 | 
						|
      Uncle = GrandParent->Right;
 | 
						|
      if ((Uncle != NULL) && (Uncle->Color == RedBlackTreeRed)) {
 | 
						|
        //
 | 
						|
        //             GrandParent (black)
 | 
						|
        //            /                   \_
 | 
						|
        // Parent (red)                    Uncle (red)
 | 
						|
        //      |
 | 
						|
        //  Tmp (red)
 | 
						|
        //
 | 
						|
 | 
						|
        Parent->Color      = RedBlackTreeBlack;
 | 
						|
        Uncle->Color       = RedBlackTreeBlack;
 | 
						|
        GrandParent->Color = RedBlackTreeRed;
 | 
						|
 | 
						|
        //
 | 
						|
        //                GrandParent (red)
 | 
						|
        //               /                 \_
 | 
						|
        // Parent (black)                   Uncle (black)
 | 
						|
        //       |
 | 
						|
        //   Tmp (red)
 | 
						|
        //
 | 
						|
        // We restored property #3 between Tmp and Tmp's parent, without
 | 
						|
        // breaking property #4. However, we may have broken property #3
 | 
						|
        // between Tmp's grandparent and Tmp's great-grandparent (if any), so
 | 
						|
        // repeat the loop for Tmp's grandparent.
 | 
						|
        //
 | 
						|
        // If Tmp's grandparent has no parent, then the loop will terminate,
 | 
						|
        // and we will have broken property #5, by coloring the root red. We'll
 | 
						|
        // restore property #5 after the loop, without breaking any others.
 | 
						|
        //
 | 
						|
        Tmp    = GrandParent;
 | 
						|
        Parent = Tmp->Parent;
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Tmp's uncle is black (satisfied by the case too when Tmp's uncle is
 | 
						|
        // NULL, see property #2).
 | 
						|
        //
 | 
						|
 | 
						|
        if (Tmp == Parent->Right) {
 | 
						|
          //
 | 
						|
          //                 GrandParent (black): D
 | 
						|
          //                /                      \_
 | 
						|
          // Parent (red): A                        Uncle (black): E
 | 
						|
          //      \_
 | 
						|
          //       Tmp (red): B
 | 
						|
          //            \_
 | 
						|
          //             black: C
 | 
						|
          //
 | 
						|
          // Rotate left, pivoting on node A. This keeps the breakage of
 | 
						|
          // property #3 in the same spot, and keeps other properties intact
 | 
						|
          // (because both Tmp and its parent are red).
 | 
						|
          //
 | 
						|
          Tmp = Parent;
 | 
						|
          RedBlackTreeRotateLeft (Tmp, &NewRoot);
 | 
						|
          Parent = Tmp->Parent;
 | 
						|
 | 
						|
          //
 | 
						|
          // With the rotation we reached the same configuration as if Tmp had
 | 
						|
          // been a left child to begin with.
 | 
						|
          //
 | 
						|
          //                       GrandParent (black): D
 | 
						|
          //                      /                      \_
 | 
						|
          //       Parent (red): B                        Uncle (black): E
 | 
						|
          //             / \_
 | 
						|
          // Tmp (red): A   black: C
 | 
						|
          //
 | 
						|
          ASSERT (GrandParent == Parent->Parent);
 | 
						|
        }
 | 
						|
 | 
						|
        Parent->Color      = RedBlackTreeBlack;
 | 
						|
        GrandParent->Color = RedBlackTreeRed;
 | 
						|
 | 
						|
        //
 | 
						|
        // Property #3 is now restored, but we've broken property #4. Namely,
 | 
						|
        // paths going through node E now see a decrease in black count, while
 | 
						|
        // paths going through node B don't.
 | 
						|
        //
 | 
						|
        //                        GrandParent (red): D
 | 
						|
        //                       /                    \_
 | 
						|
        //      Parent (black): B                      Uncle (black): E
 | 
						|
        //             / \_
 | 
						|
        // Tmp (red): A   black: C
 | 
						|
        //
 | 
						|
 | 
						|
        RedBlackTreeRotateRight (GrandParent, &NewRoot);
 | 
						|
 | 
						|
        //
 | 
						|
        // Property #4 has been restored for node E, and preserved for others.
 | 
						|
        //
 | 
						|
        //              Parent (black): B
 | 
						|
        //             /                 \_
 | 
						|
        // Tmp (red): A                   [GrandParent] (red): D
 | 
						|
        //                                         / \_
 | 
						|
        //                                 black: C   [Uncle] (black): E
 | 
						|
        //
 | 
						|
        // This configuration terminates the loop because Tmp's parent is now
 | 
						|
        // black.
 | 
						|
        //
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Symmetrical to the other branch.
 | 
						|
      //
 | 
						|
      Uncle = GrandParent->Left;
 | 
						|
      if ((Uncle != NULL) && (Uncle->Color == RedBlackTreeRed)) {
 | 
						|
        Parent->Color      = RedBlackTreeBlack;
 | 
						|
        Uncle->Color       = RedBlackTreeBlack;
 | 
						|
        GrandParent->Color = RedBlackTreeRed;
 | 
						|
        Tmp                = GrandParent;
 | 
						|
        Parent             = Tmp->Parent;
 | 
						|
      } else {
 | 
						|
        if (Tmp == Parent->Left) {
 | 
						|
          Tmp = Parent;
 | 
						|
          RedBlackTreeRotateRight (Tmp, &NewRoot);
 | 
						|
          Parent = Tmp->Parent;
 | 
						|
          ASSERT (GrandParent == Parent->Parent);
 | 
						|
        }
 | 
						|
 | 
						|
        Parent->Color      = RedBlackTreeBlack;
 | 
						|
        GrandParent->Color = RedBlackTreeRed;
 | 
						|
        RedBlackTreeRotateLeft (GrandParent, &NewRoot);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  NewRoot->Color = RedBlackTreeBlack;
 | 
						|
  Tree->Root     = NewRoot;
 | 
						|
  Status         = RETURN_SUCCESS;
 | 
						|
 | 
						|
Done:
 | 
						|
  if (FeaturePcdGet (PcdValidateOrderedCollection)) {
 | 
						|
    RedBlackTreeValidate (Tree);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if a node is black, allowing for leaf nodes (see property #2).
 | 
						|
 | 
						|
  This is a convenience shorthand.
 | 
						|
 | 
						|
  param[in] Node  The node to check. Node may be NULL, corresponding to a leaf.
 | 
						|
 | 
						|
  @return  If Node is NULL or colored black.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
NodeIsNullOrBlack (
 | 
						|
  IN CONST RED_BLACK_TREE_NODE  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  return (BOOLEAN)(Node == NULL || Node->Color == RedBlackTreeBlack);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Delete a node from the tree, unlinking the associated user structure.
 | 
						|
 | 
						|
  Read-write operation.
 | 
						|
 | 
						|
  @param[in,out] Tree        The tree to delete Node from.
 | 
						|
 | 
						|
  @param[in]     Node        The tree node to delete from Tree. The caller is
 | 
						|
                             responsible for ensuring that Node belongs to
 | 
						|
                             Tree, and that Node is non-NULL and valid. Node is
 | 
						|
                             typically an earlier return value, or output
 | 
						|
                             parameter, of:
 | 
						|
 | 
						|
                             - OrderedCollectionFind(), for deleting a node by
 | 
						|
                               user structure key,
 | 
						|
 | 
						|
                             - OrderedCollectionMin() / OrderedCollectionMax(),
 | 
						|
                               for deleting the minimum / maximum node,
 | 
						|
 | 
						|
                             - OrderedCollectionNext() /
 | 
						|
                               OrderedCollectionPrev(), for deleting a node
 | 
						|
                               found during an iteration,
 | 
						|
 | 
						|
                             - OrderedCollectionInsert() with return value
 | 
						|
                               RETURN_ALREADY_STARTED, for deleting a node
 | 
						|
                               whose linked user structure caused collision
 | 
						|
                               during insertion.
 | 
						|
 | 
						|
                             Given a non-empty Tree, Tree->Root is also a valid
 | 
						|
                             Node argument (typically used for simplicity in
 | 
						|
                             loops that empty the tree completely).
 | 
						|
 | 
						|
                             Node is released with MemoryAllocationLib's
 | 
						|
                             FreePool() function.
 | 
						|
 | 
						|
                             Existing RED_BLACK_TREE_NODE pointers (ie.
 | 
						|
                             iterators) *different* from Node remain valid. For
 | 
						|
                             example:
 | 
						|
 | 
						|
                             - OrderedCollectionNext() /
 | 
						|
                               OrderedCollectionPrev() iterations in the caller
 | 
						|
                               can be continued from Node, if
 | 
						|
                               OrderedCollectionNext() or
 | 
						|
                               OrderedCollectionPrev() is called on Node
 | 
						|
                               *before* OrderedCollectionDelete() is. That is,
 | 
						|
                               fetch the successor / predecessor node first,
 | 
						|
                               then delete Node.
 | 
						|
 | 
						|
                             - On-going iterations in the caller that would
 | 
						|
                               have otherwise returned Node at some point, as
 | 
						|
                               dictated by user structure order, will correctly
 | 
						|
                               reflect the absence of Node after
 | 
						|
                               OrderedCollectionDelete() is called
 | 
						|
                               mid-iteration.
 | 
						|
 | 
						|
  @param[out]    UserStruct  If the caller provides this optional output-only
 | 
						|
                             parameter, then on output it is set to the user
 | 
						|
                             structure originally linked by Node (which is now
 | 
						|
                             freed).
 | 
						|
 | 
						|
                             This is a convenience that may save the caller a
 | 
						|
                             OrderedCollectionUserStruct() invocation before
 | 
						|
                             calling OrderedCollectionDelete(), in order to
 | 
						|
                             retrieve the user structure being unlinked.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
OrderedCollectionDelete (
 | 
						|
  IN OUT RED_BLACK_TREE       *Tree,
 | 
						|
  IN     RED_BLACK_TREE_NODE  *Node,
 | 
						|
  OUT    VOID                 **UserStruct OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  RED_BLACK_TREE_NODE   *NewRoot;
 | 
						|
  RED_BLACK_TREE_NODE   *OrigLeftChild;
 | 
						|
  RED_BLACK_TREE_NODE   *OrigRightChild;
 | 
						|
  RED_BLACK_TREE_NODE   *OrigParent;
 | 
						|
  RED_BLACK_TREE_NODE   *Child;
 | 
						|
  RED_BLACK_TREE_NODE   *Parent;
 | 
						|
  RED_BLACK_TREE_COLOR  ColorOfUnlinked;
 | 
						|
 | 
						|
  NewRoot        = Tree->Root;
 | 
						|
  OrigLeftChild  = Node->Left,
 | 
						|
  OrigRightChild = Node->Right,
 | 
						|
  OrigParent     = Node->Parent;
 | 
						|
 | 
						|
  if (UserStruct != NULL) {
 | 
						|
    *UserStruct = Node->UserStruct;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // After this block, no matter which branch we take:
 | 
						|
  // - Child will point to the unique (or NULL) original child of the node that
 | 
						|
  //   we will have unlinked,
 | 
						|
  // - Parent will point to the *position* of the original parent of the node
 | 
						|
  //   that we will have unlinked.
 | 
						|
  //
 | 
						|
  if ((OrigLeftChild == NULL) || (OrigRightChild == NULL)) {
 | 
						|
    //
 | 
						|
    // Node has at most one child. We can connect that child (if any) with
 | 
						|
    // Node's parent (if any), unlinking Node. This will preserve ordering
 | 
						|
    // because the subtree rooted in Node's child (if any) remains on the same
 | 
						|
    // side of Node's parent (if any) that Node was before.
 | 
						|
    //
 | 
						|
    Parent          = OrigParent;
 | 
						|
    Child           = (OrigLeftChild != NULL) ? OrigLeftChild : OrigRightChild;
 | 
						|
    ColorOfUnlinked = Node->Color;
 | 
						|
 | 
						|
    if (Child != NULL) {
 | 
						|
      Child->Parent = Parent;
 | 
						|
    }
 | 
						|
 | 
						|
    if (OrigParent == NULL) {
 | 
						|
      NewRoot = Child;
 | 
						|
    } else {
 | 
						|
      if (Node == OrigParent->Left) {
 | 
						|
        OrigParent->Left = Child;
 | 
						|
      } else {
 | 
						|
        OrigParent->Right = Child;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Node has two children. We unlink Node's successor, and then link it into
 | 
						|
    // Node's place, keeping Node's original color. This preserves ordering
 | 
						|
    // because:
 | 
						|
    // - Node's left subtree is less than Node, hence less than Node's
 | 
						|
    //   successor.
 | 
						|
    // - Node's right subtree is greater than Node. Node's successor is the
 | 
						|
    //   minimum of that subtree, hence Node's successor is less than Node's
 | 
						|
    //   right subtree with its minimum removed.
 | 
						|
    // - Node's successor is in Node's subtree, hence it falls on the same side
 | 
						|
    //   of Node's parent as Node itself. The relinking doesn't change this
 | 
						|
    //   relation.
 | 
						|
    //
 | 
						|
    RED_BLACK_TREE_NODE  *ToRelink;
 | 
						|
 | 
						|
    ToRelink = OrigRightChild;
 | 
						|
    if (ToRelink->Left == NULL) {
 | 
						|
      //
 | 
						|
      // OrigRightChild itself is Node's successor, it has no left child:
 | 
						|
      //
 | 
						|
      //                OrigParent
 | 
						|
      //                    |
 | 
						|
      //                  Node: B
 | 
						|
      //                 /       \_
 | 
						|
      // OrigLeftChild: A         OrigRightChild: E <--- Parent, ToRelink
 | 
						|
      //                                           \_
 | 
						|
      //                                            F <--- Child
 | 
						|
      //
 | 
						|
      Parent = OrigRightChild;
 | 
						|
      Child  = OrigRightChild->Right;
 | 
						|
    } else {
 | 
						|
      do {
 | 
						|
        ToRelink = ToRelink->Left;
 | 
						|
      } while (ToRelink->Left != NULL);
 | 
						|
 | 
						|
      //
 | 
						|
      // Node's successor is the minimum of OrigRightChild's proper subtree:
 | 
						|
      //
 | 
						|
      //                OrigParent
 | 
						|
      //                    |
 | 
						|
      //                  Node: B
 | 
						|
      //                 /       \_
 | 
						|
      // OrigLeftChild: A         OrigRightChild: E <--- Parent
 | 
						|
      //                                  /
 | 
						|
      //                                 C <--- ToRelink
 | 
						|
      //                                  \_
 | 
						|
      //                                   D <--- Child
 | 
						|
      Parent = ToRelink->Parent;
 | 
						|
      Child  = ToRelink->Right;
 | 
						|
 | 
						|
      //
 | 
						|
      // Unlink Node's successor (ie. ToRelink):
 | 
						|
      //
 | 
						|
      //                OrigParent
 | 
						|
      //                    |
 | 
						|
      //                  Node: B
 | 
						|
      //                 /       \_
 | 
						|
      // OrigLeftChild: A         OrigRightChild: E <--- Parent
 | 
						|
      //                                  /
 | 
						|
      //                                 D <--- Child
 | 
						|
      //
 | 
						|
      //                                 C <--- ToRelink
 | 
						|
      //
 | 
						|
      Parent->Left = Child;
 | 
						|
      if (Child != NULL) {
 | 
						|
        Child->Parent = Parent;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // We start to link Node's unlinked successor into Node's place:
 | 
						|
      //
 | 
						|
      //                OrigParent
 | 
						|
      //                    |
 | 
						|
      //                  Node: B     C <--- ToRelink
 | 
						|
      //                 /             \_
 | 
						|
      // OrigLeftChild: A               OrigRightChild: E <--- Parent
 | 
						|
      //                                        /
 | 
						|
      //                                       D <--- Child
 | 
						|
      //
 | 
						|
      //
 | 
						|
      //
 | 
						|
      ToRelink->Right        = OrigRightChild;
 | 
						|
      OrigRightChild->Parent = ToRelink;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // The rest handles both cases, attaching ToRelink (Node's original
 | 
						|
    // successor) to OrigLeftChild and OrigParent.
 | 
						|
    //
 | 
						|
    //                           Parent,
 | 
						|
    //              OrigParent   ToRelink             OrigParent
 | 
						|
    //                  |        |                        |
 | 
						|
    //                Node: B    |                      Node: B          Parent
 | 
						|
    //                           v                                          |
 | 
						|
    //           OrigRightChild: E                        C <--- ToRelink   |
 | 
						|
    //                 / \                               / \                v
 | 
						|
    // OrigLeftChild: A   F              OrigLeftChild: A   OrigRightChild: E
 | 
						|
    //                    ^                                         /
 | 
						|
    //                    |                                        D <--- Child
 | 
						|
    //                  Child
 | 
						|
    //
 | 
						|
    ToRelink->Left        = OrigLeftChild;
 | 
						|
    OrigLeftChild->Parent = ToRelink;
 | 
						|
 | 
						|
    //
 | 
						|
    // Node's color must be preserved in Node's original place.
 | 
						|
    //
 | 
						|
    ColorOfUnlinked = ToRelink->Color;
 | 
						|
    ToRelink->Color = Node->Color;
 | 
						|
 | 
						|
    //
 | 
						|
    // Finish linking Node's unlinked successor into Node's place.
 | 
						|
    //
 | 
						|
    //                           Parent,
 | 
						|
    //                Node: B    ToRelink               Node: B
 | 
						|
    //                           |
 | 
						|
    //              OrigParent   |                    OrigParent         Parent
 | 
						|
    //                  |        v                        |                 |
 | 
						|
    //           OrigRightChild: E                        C <--- ToRelink   |
 | 
						|
    //                 / \                               / \                v
 | 
						|
    // OrigLeftChild: A   F              OrigLeftChild: A   OrigRightChild: E
 | 
						|
    //                    ^                                         /
 | 
						|
    //                    |                                        D <--- Child
 | 
						|
    //                  Child
 | 
						|
    //
 | 
						|
    ToRelink->Parent = OrigParent;
 | 
						|
    if (OrigParent == NULL) {
 | 
						|
      NewRoot = ToRelink;
 | 
						|
    } else {
 | 
						|
      if (Node == OrigParent->Left) {
 | 
						|
        OrigParent->Left = ToRelink;
 | 
						|
      } else {
 | 
						|
        OrigParent->Right = ToRelink;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Node);
 | 
						|
 | 
						|
  //
 | 
						|
  // If the node that we unlinked from its original spot (ie. Node itself, or
 | 
						|
  // Node's successor), was red, then we broke neither property #3 nor property
 | 
						|
  // #4: we didn't create any red-red edge between Child and Parent, and we
 | 
						|
  // didn't change the black count on any path.
 | 
						|
  //
 | 
						|
  if (ColorOfUnlinked == RedBlackTreeBlack) {
 | 
						|
    //
 | 
						|
    // However, if the unlinked node was black, then we have to transfer its
 | 
						|
    // "black-increment" to its unique child (pointed-to by Child), lest we
 | 
						|
    // break property #4 for its ancestors.
 | 
						|
    //
 | 
						|
    // If Child is red, we can simply color it black. If Child is black
 | 
						|
    // already, we can't technically transfer a black-increment to it, due to
 | 
						|
    // property #1.
 | 
						|
    //
 | 
						|
    // In the following loop we ascend searching for a red node to color black,
 | 
						|
    // or until we reach the root (in which case we can drop the
 | 
						|
    // black-increment). Inside the loop body, Child has a black value of 2,
 | 
						|
    // transitorily breaking property #1 locally, but maintaining property #4
 | 
						|
    // globally.
 | 
						|
    //
 | 
						|
    // Rotations in the loop preserve property #4.
 | 
						|
    //
 | 
						|
    while (Child != NewRoot && NodeIsNullOrBlack (Child)) {
 | 
						|
      RED_BLACK_TREE_NODE  *Sibling;
 | 
						|
      RED_BLACK_TREE_NODE  *LeftNephew;
 | 
						|
      RED_BLACK_TREE_NODE  *RightNephew;
 | 
						|
 | 
						|
      if (Child == Parent->Left) {
 | 
						|
        Sibling = Parent->Right;
 | 
						|
        //
 | 
						|
        // Sibling can never be NULL (ie. a leaf).
 | 
						|
        //
 | 
						|
        // If Sibling was NULL, then the black count on the path from Parent to
 | 
						|
        // Sibling would equal Parent's black value, plus 1 (due to property
 | 
						|
        // #2). Whereas the black count on the path from Parent to any leaf via
 | 
						|
        // Child would be at least Parent's black value, plus 2 (due to Child's
 | 
						|
        // black value of 2). This would clash with property #4.
 | 
						|
        //
 | 
						|
        // (Sibling can be black of course, but it has to be an internal node.
 | 
						|
        // Internality allows Sibling to have children, bumping the black
 | 
						|
        // counts of paths that go through it.)
 | 
						|
        //
 | 
						|
        ASSERT (Sibling != NULL);
 | 
						|
        if (Sibling->Color == RedBlackTreeRed) {
 | 
						|
          //
 | 
						|
          // Sibling's red color implies its children (if any), node C and node
 | 
						|
          // E, are black (property #3). It also implies that Parent is black.
 | 
						|
          //
 | 
						|
          //           grandparent                                 grandparent
 | 
						|
          //                |                                           |
 | 
						|
          //            Parent,b:B                                     b:D
 | 
						|
          //           /          \                                   /   \_
 | 
						|
          // Child,2b:A            Sibling,r:D  --->        Parent,r:B     b:E
 | 
						|
          //                           /\                       /\_
 | 
						|
          //                        b:C  b:E          Child,2b:A  Sibling,b:C
 | 
						|
          //
 | 
						|
          Sibling->Color = RedBlackTreeBlack;
 | 
						|
          Parent->Color  = RedBlackTreeRed;
 | 
						|
          RedBlackTreeRotateLeft (Parent, &NewRoot);
 | 
						|
          Sibling = Parent->Right;
 | 
						|
          //
 | 
						|
          // Same reasoning as above.
 | 
						|
          //
 | 
						|
          ASSERT (Sibling != NULL);
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Sibling is black, and not NULL. (Ie. Sibling is a black internal
 | 
						|
        // node.)
 | 
						|
        //
 | 
						|
        ASSERT (Sibling->Color == RedBlackTreeBlack);
 | 
						|
        LeftNephew  = Sibling->Left;
 | 
						|
        RightNephew = Sibling->Right;
 | 
						|
        if (NodeIsNullOrBlack (LeftNephew) &&
 | 
						|
            NodeIsNullOrBlack (RightNephew))
 | 
						|
        {
 | 
						|
          //
 | 
						|
          // In this case we can "steal" one black value from Child and Sibling
 | 
						|
          // each, and pass it to Parent. "Stealing" means that Sibling (black
 | 
						|
          // value 1) becomes red, Child (black value 2) becomes singly-black,
 | 
						|
          // and Parent will have to be examined if it can eat the
 | 
						|
          // black-increment.
 | 
						|
          //
 | 
						|
          // Sibling is allowed to become red because both of its children are
 | 
						|
          // black (property #3).
 | 
						|
          //
 | 
						|
          //           grandparent                             Parent
 | 
						|
          //                |                                     |
 | 
						|
          //            Parent,x:B                            Child,x:B
 | 
						|
          //           /          \                          /         \_
 | 
						|
          // Child,2b:A            Sibling,b:D    --->    b:A           r:D
 | 
						|
          //                           /\                                /\_
 | 
						|
          //             LeftNephew,b:C  RightNephew,b:E              b:C  b:E
 | 
						|
          //
 | 
						|
          Sibling->Color = RedBlackTreeRed;
 | 
						|
          Child          = Parent;
 | 
						|
          Parent         = Parent->Parent;
 | 
						|
          //
 | 
						|
          // Continue ascending.
 | 
						|
          //
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // At least one nephew is red.
 | 
						|
          //
 | 
						|
          if (NodeIsNullOrBlack (RightNephew)) {
 | 
						|
            //
 | 
						|
            // Since the right nephew is black, the left nephew is red. Due to
 | 
						|
            // property #3, LeftNephew has two black children, hence node E is
 | 
						|
            // black.
 | 
						|
            //
 | 
						|
            // Together with the rotation, this enables us to color node F red
 | 
						|
            // (because property #3 will be satisfied). We flip node D to black
 | 
						|
            // to maintain property #4.
 | 
						|
            //
 | 
						|
            //      grandparent                         grandparent
 | 
						|
            //           |                                   |
 | 
						|
            //       Parent,x:B                          Parent,x:B
 | 
						|
            //           /\                                  /\_
 | 
						|
            // Child,2b:A  Sibling,b:F     --->    Child,2b:A  Sibling,b:D
 | 
						|
            //                  /\                            /   \_
 | 
						|
            //    LeftNephew,r:D  RightNephew,b:G          b:C  RightNephew,r:F
 | 
						|
            //               /\                                       /\_
 | 
						|
            //            b:C  b:E                                 b:E  b:G
 | 
						|
            //
 | 
						|
            LeftNephew->Color = RedBlackTreeBlack;
 | 
						|
            Sibling->Color    = RedBlackTreeRed;
 | 
						|
            RedBlackTreeRotateRight (Sibling, &NewRoot);
 | 
						|
            Sibling     = Parent->Right;
 | 
						|
            RightNephew = Sibling->Right;
 | 
						|
            //
 | 
						|
            // These operations ensure that...
 | 
						|
            //
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
          // ... RightNephew is definitely red here, plus Sibling is (still)
 | 
						|
          // black and non-NULL.
 | 
						|
          //
 | 
						|
          ASSERT (RightNephew != NULL);
 | 
						|
          ASSERT (RightNephew->Color == RedBlackTreeRed);
 | 
						|
          ASSERT (Sibling != NULL);
 | 
						|
          ASSERT (Sibling->Color == RedBlackTreeBlack);
 | 
						|
          //
 | 
						|
          // In this case we can flush the extra black-increment immediately,
 | 
						|
          // restoring property #1 for Child (node A): we color RightNephew
 | 
						|
          // (node E) from red to black.
 | 
						|
          //
 | 
						|
          // In order to maintain property #4, we exchange colors between
 | 
						|
          // Parent and Sibling (nodes B and D), and rotate left around Parent
 | 
						|
          // (node B). The transformation doesn't change the black count
 | 
						|
          // increase incurred by each partial path, eg.
 | 
						|
          // - ascending from node A: 2 + x     == 1 + 1 + x
 | 
						|
          // - ascending from node C: y + 1 + x == y + 1 + x
 | 
						|
          // - ascending from node E: 0 + 1 + x == 1 + x
 | 
						|
          //
 | 
						|
          // The color exchange is valid, because even if x stands for red,
 | 
						|
          // both children of node D are black after the transformation
 | 
						|
          // (preserving property #3).
 | 
						|
          //
 | 
						|
          //           grandparent                                  grandparent
 | 
						|
          //                |                                            |
 | 
						|
          //            Parent,x:B                                      x:D
 | 
						|
          //           /          \                                    /   \_
 | 
						|
          // Child,2b:A            Sibling,b:D              --->    b:B     b:E
 | 
						|
          //                         /     \                       /   \_
 | 
						|
          //                      y:C       RightNephew,r:E     b:A     y:C
 | 
						|
          //
 | 
						|
          //
 | 
						|
          Sibling->Color     = Parent->Color;
 | 
						|
          Parent->Color      = RedBlackTreeBlack;
 | 
						|
          RightNephew->Color = RedBlackTreeBlack;
 | 
						|
          RedBlackTreeRotateLeft (Parent, &NewRoot);
 | 
						|
          Child = NewRoot;
 | 
						|
          //
 | 
						|
          // This terminates the loop.
 | 
						|
          //
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Mirrors the other branch.
 | 
						|
        //
 | 
						|
        Sibling = Parent->Left;
 | 
						|
        ASSERT (Sibling != NULL);
 | 
						|
        if (Sibling->Color == RedBlackTreeRed) {
 | 
						|
          Sibling->Color = RedBlackTreeBlack;
 | 
						|
          Parent->Color  = RedBlackTreeRed;
 | 
						|
          RedBlackTreeRotateRight (Parent, &NewRoot);
 | 
						|
          Sibling = Parent->Left;
 | 
						|
          ASSERT (Sibling != NULL);
 | 
						|
        }
 | 
						|
 | 
						|
        ASSERT (Sibling->Color == RedBlackTreeBlack);
 | 
						|
        RightNephew = Sibling->Right;
 | 
						|
        LeftNephew  = Sibling->Left;
 | 
						|
        if (NodeIsNullOrBlack (RightNephew) &&
 | 
						|
            NodeIsNullOrBlack (LeftNephew))
 | 
						|
        {
 | 
						|
          Sibling->Color = RedBlackTreeRed;
 | 
						|
          Child          = Parent;
 | 
						|
          Parent         = Parent->Parent;
 | 
						|
        } else {
 | 
						|
          if (NodeIsNullOrBlack (LeftNephew)) {
 | 
						|
            RightNephew->Color = RedBlackTreeBlack;
 | 
						|
            Sibling->Color     = RedBlackTreeRed;
 | 
						|
            RedBlackTreeRotateLeft (Sibling, &NewRoot);
 | 
						|
            Sibling    = Parent->Left;
 | 
						|
            LeftNephew = Sibling->Left;
 | 
						|
          }
 | 
						|
 | 
						|
          ASSERT (LeftNephew != NULL);
 | 
						|
          ASSERT (LeftNephew->Color == RedBlackTreeRed);
 | 
						|
          ASSERT (Sibling != NULL);
 | 
						|
          ASSERT (Sibling->Color == RedBlackTreeBlack);
 | 
						|
          Sibling->Color    = Parent->Color;
 | 
						|
          Parent->Color     = RedBlackTreeBlack;
 | 
						|
          LeftNephew->Color = RedBlackTreeBlack;
 | 
						|
          RedBlackTreeRotateRight (Parent, &NewRoot);
 | 
						|
          Child = NewRoot;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (Child != NULL) {
 | 
						|
      Child->Color = RedBlackTreeBlack;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Tree->Root = NewRoot;
 | 
						|
 | 
						|
  if (FeaturePcdGet (PcdValidateOrderedCollection)) {
 | 
						|
    RedBlackTreeValidate (Tree);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Recursively check the red-black tree properties #1 to #4 on a node.
 | 
						|
 | 
						|
  @param[in] Node  The root of the subtree to validate.
 | 
						|
 | 
						|
  @retval  The black-height of Node's parent.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
RedBlackTreeRecursiveCheck (
 | 
						|
  IN CONST RED_BLACK_TREE_NODE  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  LeftHeight;
 | 
						|
  UINT32  RightHeight;
 | 
						|
 | 
						|
  //
 | 
						|
  // property #2
 | 
						|
  //
 | 
						|
  if (Node == NULL) {
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // property #1
 | 
						|
  //
 | 
						|
  ASSERT (Node->Color == RedBlackTreeRed || Node->Color == RedBlackTreeBlack);
 | 
						|
 | 
						|
  //
 | 
						|
  // property #3
 | 
						|
  //
 | 
						|
  if (Node->Color == RedBlackTreeRed) {
 | 
						|
    ASSERT (NodeIsNullOrBlack (Node->Left));
 | 
						|
    ASSERT (NodeIsNullOrBlack (Node->Right));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // property #4
 | 
						|
  //
 | 
						|
  LeftHeight  = RedBlackTreeRecursiveCheck (Node->Left);
 | 
						|
  RightHeight = RedBlackTreeRecursiveCheck (Node->Right);
 | 
						|
  ASSERT (LeftHeight == RightHeight);
 | 
						|
 | 
						|
  return (Node->Color == RedBlackTreeBlack) + LeftHeight;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  A slow function that asserts that the tree is a valid red-black tree, and
 | 
						|
  that it orders user structures correctly.
 | 
						|
 | 
						|
  Read-only operation.
 | 
						|
 | 
						|
  This function uses the stack for recursion and is not recommended for
 | 
						|
  "production use".
 | 
						|
 | 
						|
  @param[in] Tree  The tree to validate.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RedBlackTreeValidate (
 | 
						|
  IN CONST RED_BLACK_TREE  *Tree
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32                     BlackHeight;
 | 
						|
  UINT32                     ForwardCount;
 | 
						|
  UINT32                     BackwardCount;
 | 
						|
  CONST RED_BLACK_TREE_NODE  *Last;
 | 
						|
  CONST RED_BLACK_TREE_NODE  *Node;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "%a: Tree=%p\n", __FUNCTION__, Tree));
 | 
						|
 | 
						|
  //
 | 
						|
  // property #5
 | 
						|
  //
 | 
						|
  ASSERT (NodeIsNullOrBlack (Tree->Root));
 | 
						|
 | 
						|
  //
 | 
						|
  // check the other properties
 | 
						|
  //
 | 
						|
  BlackHeight = RedBlackTreeRecursiveCheck (Tree->Root) - 1;
 | 
						|
 | 
						|
  //
 | 
						|
  // forward ordering
 | 
						|
  //
 | 
						|
  Last         = OrderedCollectionMin (Tree);
 | 
						|
  ForwardCount = (Last != NULL);
 | 
						|
  for (Node = OrderedCollectionNext (Last); Node != NULL;
 | 
						|
       Node = OrderedCollectionNext (Last))
 | 
						|
  {
 | 
						|
    ASSERT (Tree->UserStructCompare (Last->UserStruct, Node->UserStruct) < 0);
 | 
						|
    Last = Node;
 | 
						|
    ++ForwardCount;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // backward ordering
 | 
						|
  //
 | 
						|
  Last          = OrderedCollectionMax (Tree);
 | 
						|
  BackwardCount = (Last != NULL);
 | 
						|
  for (Node = OrderedCollectionPrev (Last); Node != NULL;
 | 
						|
       Node = OrderedCollectionPrev (Last))
 | 
						|
  {
 | 
						|
    ASSERT (Tree->UserStructCompare (Last->UserStruct, Node->UserStruct) > 0);
 | 
						|
    Last = Node;
 | 
						|
    ++BackwardCount;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (ForwardCount == BackwardCount);
 | 
						|
 | 
						|
  DEBUG ((
 | 
						|
    DEBUG_VERBOSE,
 | 
						|
    "%a: Tree=%p BlackHeight=%Ld Count=%Ld\n",
 | 
						|
    __FUNCTION__,
 | 
						|
    Tree,
 | 
						|
    (INT64)BlackHeight,
 | 
						|
    (INT64)ForwardCount
 | 
						|
    ));
 | 
						|
}
 |