From 9002ac8b5cb589376ba6c86a68b2bc0cf39b94de Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 21 May 2026 14:56:44 +0200 Subject: [PATCH] Implement red-black tree algorithm --- sdk/xtdk/rtltypes.h | 114 +++-- sdk/xtdk/xtstruct.h | 3 + xtoskrnl/CMakeLists.txt | 1 + xtoskrnl/includes/rtl.hh | 1 + xtoskrnl/includes/rtl/rbtree.hh | 45 ++ xtoskrnl/rtl/rbtree.cc | 723 ++++++++++++++++++++++++++++++++ 6 files changed, 849 insertions(+), 38 deletions(-) create mode 100644 xtoskrnl/includes/rtl/rbtree.hh create mode 100644 xtoskrnl/rtl/rbtree.cc diff --git a/sdk/xtdk/rtltypes.h b/sdk/xtdk/rtltypes.h index c8d8817..166c303 100644 --- a/sdk/xtdk/rtltypes.h +++ b/sdk/xtdk/rtltypes.h @@ -14,51 +14,55 @@ /* UUID string lengths */ -#define GUID_STRING_LENGTH 38 -#define PARTUUID_STRING_LENGTH 13 +#define GUID_STRING_LENGTH 38 +#define PARTUUID_STRING_LENGTH 13 /* Maximum double/integer value string length */ -#define MAX_DOUBLE_STRING_SIZE 15 -#define MAX_INTEGER_STRING_SIZE 25 +#define MAX_DOUBLE_STRING_SIZE 15 +#define MAX_INTEGER_STRING_SIZE 25 /* Floating point definitions */ -#define DOUBLE_EXPONENT_MASK 0x7FF0000000000000ULL -#define DOUBLE_EXPONENT_SHIFT 0x34 -#define DOUBLE_EXPONENT_BIAS 0x3FF -#define DOUBLE_HIGH_VALUE_MASK 0x000FFFFF -#define DOUBLE_HIGH_VALUE_SHIFT 0x20 -#define DOUBLE_PRECISION 6 -#define DOUBLE_HEX_PRECISION 13 -#define DOUBLE_SCIENTIFIC_PRECISION -4 -#define DOUBLE_SIGN_BIT 0x8000000000000000ULL +#define DOUBLE_EXPONENT_MASK 0x7FF0000000000000ULL +#define DOUBLE_EXPONENT_SHIFT 0x34 +#define DOUBLE_EXPONENT_BIAS 0x3FF +#define DOUBLE_HIGH_VALUE_MASK 0x000FFFFF +#define DOUBLE_HIGH_VALUE_SHIFT 0x20 +#define DOUBLE_PRECISION 6 +#define DOUBLE_HEX_PRECISION 13 +#define DOUBLE_SCIENTIFIC_PRECISION -4 +#define DOUBLE_SIGN_BIT 0x8000000000000000ULL /* Print flag definitions */ -#define PFL_ALWAYS_PRINT_SIGN 0x00000001 -#define PFL_SPACE_FOR_PLUS 0x00000002 -#define PFL_LEFT_JUSTIFIED 0x00000004 -#define PFL_LEADING_ZEROES 0x00000008 -#define PFL_LONG_INTEGER 0x00000010 -#define PFL_LONG_DOUBLE 0x00000020 -#define PFL_WIDE_CHARACTER 0x00000040 -#define PFL_SHORT_VALUE 0x00000080 -#define PFL_UNSIGNED 0x00000100 -#define PFL_UPPERCASE 0x00000200 -#define PFL_PRINT_RADIX 0x00000400 -#define PFL_FLOAT_FORMAT 0x00000800 -#define PFL_SCI_FORMAT 0x00001000 -#define PFL_DIGIT_PRECISION 0x00002000 -#define PFL_THOUSANDS_GROUPING 0x00004000 +#define PFL_ALWAYS_PRINT_SIGN 0x00000001 +#define PFL_SPACE_FOR_PLUS 0x00000002 +#define PFL_LEFT_JUSTIFIED 0x00000004 +#define PFL_LEADING_ZEROES 0x00000008 +#define PFL_LONG_INTEGER 0x00000010 +#define PFL_LONG_DOUBLE 0x00000020 +#define PFL_WIDE_CHARACTER 0x00000040 +#define PFL_SHORT_VALUE 0x00000080 +#define PFL_UNSIGNED 0x00000100 +#define PFL_UPPERCASE 0x00000200 +#define PFL_PRINT_RADIX 0x00000400 +#define PFL_FLOAT_FORMAT 0x00000800 +#define PFL_SCI_FORMAT 0x00001000 +#define PFL_DIGIT_PRECISION 0x00002000 +#define PFL_THOUSANDS_GROUPING 0x00004000 + +/* Red-black tree definitions */ +#define RTL_BALANCED_NODE_RESERVED_PARENT_MASK 3 +#define RTL_BALANCED_NODE_COLOR_MASK 1 /* Cryptographic related definitions */ -#define SHA1_BLOCK_SIZE 64 -#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 +#define SHA1_DIGEST_SIZE 20 /* Time related definitions */ -#define TIME_SECONDS_PER_MINUTE 60 -#define TIME_SECONDS_PER_HOUR 3600 -#define TIME_SECONDS_PER_DAY 86400 -#define TIME_TICKS_PER_SECOND 10000000 -#define TIME_TICKS_PER_MILLISECOND 10000 +#define TIME_SECONDS_PER_MINUTE 60 +#define TIME_SECONDS_PER_HOUR 3600 +#define TIME_SECONDS_PER_DAY 86400 +#define TIME_TICKS_PER_SECOND 10000000 +#define TIME_TICKS_PER_MILLISECOND 10000 /* C/C++ specific code */ @@ -68,6 +72,13 @@ typedef XTSTATUS (*PWRITE_CHARACTER)(IN CHAR Character); typedef XTSTATUS (*PWRITE_WIDE_CHARACTER)(IN WCHAR Character); +/* Red-black tree node color enumeration list */ +typedef enum _RTL_BALANCED_NODE_COLOR +{ + NodeBlack, + NodeRed +} RTL_BALANCED_NODE_COLOR, *PRTL_BALANCED_NODE_COLOR; + /* Variable types enumeration list */ typedef enum _RTL_VARIABLE_TYPE { @@ -84,6 +95,26 @@ typedef enum _RTL_VARIABLE_TYPE TypeWideString } RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; +/* Runtime Library red-black tree balanced node structure definition */ +typedef struct _RTL_BALANCED_NODE +{ + union + { + PRTL_BALANCED_NODE Children[2]; + struct + { + PRTL_BALANCED_NODE Left; + PRTL_BALANCED_NODE Right; + }; + }; + union + { + UCHAR Red:1; + UCHAR Balance:2; + ULONG_PTR ParentValue; + }; +} RTL_BALANCED_NODE, *PRTL_BALANCED_NODE; + /* Bit Map structure definition */ typedef struct _RTL_BITMAP { @@ -110,12 +141,19 @@ typedef struct _RTL_PRINT_FORMAT_PROPERTIES LONG Flags; } RTL_PRINT_FORMAT_PROPERTIES, *PRTL_PRINT_FORMAT_PROPERTIES; +/* Runtime Library red-black tree structure definition */ +typedef struct _RTL_RB_TREE +{ + PRTL_BALANCED_NODE Root; + PRTL_BALANCED_NODE Min; +} RTL_RB_TREE, *PRTL_RB_TREE; + /* Runtime Library SHA-1 context structure definition */ typedef struct _RTL_SHA1_CONTEXT { - ULONG State[5]; - ULONG Count[2]; - UCHAR Buffer[SHA1_BLOCK_SIZE]; + ULONG State[5]; + ULONG Count[2]; + UCHAR Buffer[SHA1_BLOCK_SIZE]; } RTL_SHA1_CONTEXT, *PRTL_SHA1_CONTEXT; /* Runtime time fields structure definition */ diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index ff591e7..712c240 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -57,6 +57,7 @@ typedef enum _MMPFN_CACHE_ATTRIBUTE MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBU typedef enum _MMPOOL_TYPE MMPOOL_TYPE, *PMMPOOL_TYPE; typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE; typedef enum _MODE MODE, *PMODE; +typedef enum _RTL_BALANCED_NODE_COLOR RTL_BALANCED_NODE_COLOR, *PRTL_BALANCED_NODE_COLOR; typedef enum _RTL_VARIABLE_TYPE RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; typedef enum _SYSTEM_FIRMWARE_TYPE SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_TYPE; typedef enum _SYSTEM_RESOURCE_TYPE SYSTEM_RESOURCE_TYPE, *PSYSTEM_RESOURCE_TYPE; @@ -327,9 +328,11 @@ typedef struct _POOL_TRACKING_BIG_ALLOCATIONS POOL_TRACKING_BIG_ALLOCATIONS, *PP typedef struct _POOL_TRACKING_TABLE POOL_TRACKING_TABLE, *PPOOL_TRACKING_TABLE; typedef struct _PROCESSOR_IDENTITY PROCESSOR_IDENTITY, *PPROCESSOR_IDENTITY; typedef struct _PROCESSOR_POWER_STATE PROCESSOR_POWER_STATE, *PPROCESSOR_POWER_STATE; +typedef struct _RTL_BALANCED_NODE RTL_BALANCED_NODE, *PRTL_BALANCED_NODE; typedef struct _RTL_BITMAP RTL_BITMAP, *PRTL_BITMAP; typedef struct _RTL_PRINT_CONTEXT RTL_PRINT_CONTEXT, *PRTL_PRINT_CONTEXT; typedef struct _RTL_PRINT_FORMAT_PROPERTIES RTL_PRINT_FORMAT_PROPERTIES, *PRTL_PRINT_FORMAT_PROPERTIES; +typedef struct _RTL_RB_TREE RTL_RB_TREE, *PRTL_RB_TREE; typedef struct _SINGLE_LIST_ENTRY SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; typedef struct _SMBIOS_TABLE_HEADER SMBIOS_TABLE_HEADER, *PSMBIOS_TABLE_HEADER; typedef struct _SMBIOS3_TABLE_HEADER SMBIOS3_TABLE_HEADER, *PSMBIOS3_TABLE_HEADER; diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 472400b..6851e26 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -88,6 +88,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/rtl/llist.cc ${XTOSKRNL_SOURCE_DIR}/rtl/math.cc ${XTOSKRNL_SOURCE_DIR}/rtl/memory.cc + ${XTOSKRNL_SOURCE_DIR}/rtl/rbtree.cc ${XTOSKRNL_SOURCE_DIR}/rtl/sha1.cc ${XTOSKRNL_SOURCE_DIR}/rtl/slist.cc ${XTOSKRNL_SOURCE_DIR}/rtl/string.cc diff --git a/xtoskrnl/includes/rtl.hh b/xtoskrnl/includes/rtl.hh index 37fb705..939ee8c 100644 --- a/xtoskrnl/includes/rtl.hh +++ b/xtoskrnl/includes/rtl.hh @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/xtoskrnl/includes/rtl/rbtree.hh b/xtoskrnl/includes/rtl/rbtree.hh new file mode 100644 index 0000000..a5c3117 --- /dev/null +++ b/xtoskrnl/includes/rtl/rbtree.hh @@ -0,0 +1,45 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/rtl/rbtree.hh + * DESCRIPTION: Red-Black Tree implementation + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_RTL_RBTREE_HH +#define __XTOSKRNL_RTL_RBTREE_HH + +#include + + +/* Runtime Library */ +namespace RTL +{ + class RedBlackTree + { + public: + STATIC XTAPI VOID InitializeTree(OUT PRTL_RB_TREE Tree); + STATIC XTAPI VOID InsertNode(IN PRTL_RB_TREE Tree, + IN PRTL_BALANCED_NODE Parent, + IN PRTL_BALANCED_NODE Node, + IN BOOLEAN RightChild); + STATIC XTAPI VOID RemoveNode(IN PRTL_RB_TREE Tree, + IN PRTL_BALANCED_NODE Node); + + private: + STATIC XTAPI VOID CopyNodeColor(OUT PRTL_BALANCED_NODE Destination, + IN PRTL_BALANCED_NODE Source); + STATIC XTAPI RTL_BALANCED_NODE_COLOR GetNodeColor(IN PRTL_BALANCED_NODE Node); + STATIC XTAPI PRTL_BALANCED_NODE GetParentNode(PRTL_BALANCED_NODE Node); + STATIC XTAPI VOID RotateLeft(IN PRTL_RB_TREE Tree, + IN PRTL_BALANCED_NODE Node); + STATIC XTAPI VOID RotateRight(IN PRTL_RB_TREE Tree, + IN PRTL_BALANCED_NODE Node); + STATIC XTAPI VOID SetNodeColor(OUT PRTL_BALANCED_NODE Node, + IN RTL_BALANCED_NODE_COLOR Color); + STATIC XTAPI VOID SetParentNode(OUT PRTL_BALANCED_NODE Node, + IN PRTL_BALANCED_NODE Parent); + }; +} + +#endif /* __XTOSKRNL_RTL_RBTREE_HH */ diff --git a/xtoskrnl/rtl/rbtree.cc b/xtoskrnl/rtl/rbtree.cc new file mode 100644 index 0000000..22c436a --- /dev/null +++ b/xtoskrnl/rtl/rbtree.cc @@ -0,0 +1,723 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/rtl/rbtree.cc + * DESCRIPTION: Red-Black Tree implementation + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** + * Copies the color from the Source node to the Dest node without modifying the destination node's parent pointer. + * + * @param Destination + * Supplies a pointer to the balanced node for which to set the color. + * + * @param Source + * Supplies a pointer to the balanced node from which to copy the color. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +RTL::RedBlackTree::CopyNodeColor(OUT PRTL_BALANCED_NODE Destination, + IN PRTL_BALANCED_NODE Source) +{ + /* Copy the color from the source node to the destination node */ + Destination->ParentValue = (Destination->ParentValue & ~RTL_BALANCED_NODE_COLOR_MASK) | GetNodeColor(Source); +} + +/** + * Extracts the color bit from the node's ParentValue. + * + * @param Node + * Supplies a pointer to the balanced node from which to extract the color. + * + * @return This routine returns the color of the given node, either NodeRed or NodeBlack. + * + * @since XT 1.0 + */ +XTAPI +RTL_BALANCED_NODE_COLOR +RTL::RedBlackTree::GetNodeColor(IN PRTL_BALANCED_NODE Node) +{ + /* Return the node color */ + return (RTL_BALANCED_NODE_COLOR)(Node->ParentValue & RTL_BALANCED_NODE_COLOR_MASK); +} + +/** + * Retrieves the parent node pointer by masking out the reserved bits. + * + * @param Node + * Supplies a pointer to the balanced node from which to extract the parent pointer. + * + * @return This routine returns a pointer to the parent node of the given node. + * + * @since XT 1.0 + */ +XTAPI +PRTL_BALANCED_NODE +RTL::RedBlackTree::GetParentNode(IN PRTL_BALANCED_NODE Node) +{ + /* Return the parent node pointer by masking out the reserved bits */ + return (PRTL_BALANCED_NODE)(Node->ParentValue & ~RTL_BALANCED_NODE_RESERVED_PARENT_MASK); +} + +/** + * Initializes a red-black tree by setting its root and minimum pointers to NULLPTR. + * + * @param Tree + * Supplies a pointer to the RTL_RB_TREE structure to initialize. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +RTL::RedBlackTree::InitializeTree(OUT PRTL_RB_TREE Tree) +{ + /* Initialize the tree */ + Tree->Root = NULLPTR; + Tree->Min = NULLPTR; +} + +/** + * Inserts a new node into the red-black tree at the specified position and rebalances the tree. + * + * @param Tree + * Supplies a pointer to the RTL_RB_TREE structure into which the node is inserted. + * + * @param Parent + * Supplies a pointer to the parent node under which the new node will be inserted. + * If the tree is empty, this must be NULLPTR. + * + * @param Node + * Supplies a pointer to the uninitialized balanced node to insert into the tree. + * + * @param RightChild + * Specifies whether the new node should be inserted as the right child (TRUE) + * or the left child (FALSE) of the parent node. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +RTL::RedBlackTree::InsertNode(IN PRTL_RB_TREE Tree, + IN PRTL_BALANCED_NODE Parent, + IN PRTL_BALANCED_NODE Node, + IN BOOLEAN RightChild) +{ + PRTL_BALANCED_NODE CurrentNode, CurrentParent, GrandParent, Uncle; + + /* Initialize the new node with no children and default its color to red */ + Node->Left = NULLPTR; + Node->Right = NULLPTR; + Node->ParentValue = (ULONG_PTR)Parent | NodeRed; + + /* Check if the tree is not empty */ + if(Parent != NULLPTR) + { + /* Determine whether to attach the node as a right or left child */ + if(RightChild) + { + /* Attach the new node to the right side of the parent */ + Parent->Right = Node; + } + else + { + /* Attach the new node to the left side of the parent */ + Parent->Left = Node; + + /* Check if the new node is placed left of the current minimum */ + if(Parent == Tree->Min) + { + /* Update the cached minimum pointer for the tree */ + Tree->Min = Node; + } + } + } + else + { + /* The tree was empty, so the new node becomes both the root and the minimum */ + Tree->Root = Node; + Tree->Min = Node; + } + + /* Begin fixing up the red-black tree properties */ + CurrentNode = Node; + while(CurrentNode != Tree->Root && GetNodeColor(GetParentNode(CurrentNode)) == NodeRed) + { + /* Retrieve the parent and grandparent nodes to determine rotation and recoloring cases */ + CurrentParent = GetParentNode(CurrentNode); + GrandParent = GetParentNode(CurrentParent); + + /* Check if the parent is a left child of the grandparent */ + if(CurrentParent == GrandParent->Left) + { + /* Determine the uncle node */ + Uncle = GrandParent->Right; + if(Uncle != NULLPTR && GetNodeColor(Uncle) == NodeRed) + { + /* Recolor parent, uncle, and grandparent */ + SetNodeColor(CurrentParent, NodeBlack); + SetNodeColor(Uncle, NodeBlack); + SetNodeColor(GrandParent, NodeRed); + + /* Move the current node pointer up to the grandparent */ + CurrentNode = GrandParent; + } + else + { + /* Check if current node is a right child */ + if(CurrentNode == CurrentParent->Right) + { + /* Move the current pointer to the parent and perform a left rotation */ + CurrentNode = CurrentParent; + RotateLeft(Tree, CurrentNode); + + /* Update parent and grandparent pointers after the rotation */ + CurrentParent = GetParentNode(CurrentNode); + GrandParent = GetParentNode(CurrentParent); + } + + /* Recolor parent and grandparent */ + SetNodeColor(CurrentParent, NodeBlack); + SetNodeColor(GrandParent, NodeRed); + + /* Perform a right rotation around the grandparent to restore tree balance */ + RotateRight(Tree, GrandParent); + } + } + else + { + /* Determine the uncle node */ + Uncle = GrandParent->Left; + if(Uncle != NULLPTR && GetNodeColor(Uncle) == NodeRed) + { + /* Recolor parent, uncle, and grandparent */ + SetNodeColor(CurrentParent, NodeBlack); + SetNodeColor(Uncle, NodeBlack); + SetNodeColor(GrandParent, NodeRed); + + /* Move the current node pointer up to the grandparent */ + CurrentNode = GrandParent; + } + else + { + /* Check if current node is a left child */ + if(CurrentNode == CurrentParent->Left) + { + /* Move the current pointer to the parent and perform a right rotation */ + CurrentNode = CurrentParent; + RotateRight(Tree, CurrentNode); + + /* Update parent and grandparent pointers after the rotation */ + CurrentParent = GetParentNode(CurrentNode); + GrandParent = GetParentNode(CurrentParent); + } + + /* Recolor parent and grandparent */ + SetNodeColor(CurrentParent, NodeBlack); + SetNodeColor(GrandParent, NodeRed); + + /* Perform a left rotation around the grandparent to restore tree balance */ + RotateLeft(Tree, GrandParent); + } + } + } + + /* Ensure the root node is always colored black */ + SetNodeColor(Tree->Root, NodeBlack); +} + +/** + * Removes the specified node from the red-black tree and rebalances the tree to maintain its properties. + * + * @param Tree + * Supplies a pointer to the RTL_RB_TREE structure from which the node is removed. + * + * @param Node + * Supplies a pointer to the balanced node to remove from the tree. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +RTL::RedBlackTree::RemoveNode(IN PRTL_RB_TREE Tree, + IN PRTL_BALANCED_NODE Node) +{ + PRTL_BALANCED_NODE CurrentNode, NextMinNode, NodeToRemove, ParentNode, Replacement, ReplacementParent, SiblingNode; + ULONG_PTR RemoveNodeColor; + + /* Initialize variables to track the node */ + NodeToRemove = Node; + RemoveNodeColor = GetNodeColor(NodeToRemove); + Replacement = NULLPTR; + ReplacementParent = NULLPTR; + + /* Check if the node being removed is the cached minimum node */ + if(Tree->Min == Node) + { + /* Find the next minimum node */ + NextMinNode = Node->Right; + if(NextMinNode != NULLPTR) + { + /* Traverse to the leftmost descendant of the right child */ + while(NextMinNode->Left != NULLPTR) + { + /* Move down to the left child */ + NextMinNode = NextMinNode->Left; + } + + /* Update the tree's minimum pointer to the found successor */ + Tree->Min = NextMinNode; + } + else + { + /* The parent becomes the new minimum */ + Tree->Min = GetParentNode(Node); + } + } + + /* Check if the node to remove has no left child */ + if(Node->Left == NULLPTR) + { + /* Use the right child as the replacement node */ + Replacement = Node->Right; + ReplacementParent = GetParentNode(Node); + + /* Check if the removed node was the root of the tree */ + if(ReplacementParent == NULLPTR) + { + /* The replacement node becomes the new root */ + Tree->Root = Replacement; + } + else if(Node == ReplacementParent->Left) + { + /* Link the replacement to the parent's left side */ + ReplacementParent->Left = Replacement; + } + else + { + /* Link the replacement to the parent's right side */ + ReplacementParent->Right = Replacement; + } + + /* Check if replacement exists */ + if(Replacement != NULLPTR) + { + /* Link the replacement back to its new parent */ + SetParentNode(Replacement, ReplacementParent); + } + } + else if(Node->Right == NULLPTR) + { + /* Use the left child as the replacement node */ + Replacement = Node->Left; + ReplacementParent = GetParentNode(Node); + + /* Check if the removed node was the root of the tree */ + if(ReplacementParent == NULLPTR) + { + /* The replacement node becomes the new root */ + Tree->Root = Replacement; + } + else if(Node == ReplacementParent->Left) + { + /* Link the replacement to the parent's left side */ + ReplacementParent->Left = Replacement; + } + else + { + /* Link the replacement to the parent's right side */ + ReplacementParent->Right = Replacement; + } + + /* Check if replacement exists */ + if(Replacement != NULLPTR) + { + /* Link the replacement back to its new parent */ + SetParentNode(Replacement, ReplacementParent); + } + } + else + { + /* Find the in-order successor to replace it */ + NodeToRemove = Node->Right; + while(NodeToRemove->Left != NULLPTR) + { + /* Traverse to the leftmost node in the right subtree */ + NodeToRemove = NodeToRemove->Left; + } + + /* Cache the original color of the successor node */ + RemoveNodeColor = GetNodeColor(NodeToRemove); + Replacement = NodeToRemove->Right; + ReplacementParent = GetParentNode(NodeToRemove); + + /* Check fif the successor is not the direct right child of the node being removed */ + if(NodeToRemove != Node->Right) + { + /* Detach the successor from its original parent and link its right child */ + ReplacementParent->Left = Replacement; + if(Replacement != NULLPTR) + { + /* Link the successor's right child to the successor's parent */ + SetParentNode(Replacement, ReplacementParent); + } + + /* Attach the original node's right subtree to the successor */ + NodeToRemove->Right = Node->Right; + SetParentNode(NodeToRemove->Right, NodeToRemove); + } + else + { + /* Set the replacement parent as the successor itself */ + ReplacementParent = NodeToRemove; + } + + /* Retrieve the parent of the node being removed to link it to the successor */ + ParentNode = GetParentNode(Node); + if(ParentNode == NULLPTR) + { + /* The successor becomes the new root */ + Tree->Root = NodeToRemove; + } + else if(Node == ParentNode->Left) + { + /* Link the successor to the left side of the original parent */ + ParentNode->Left = NodeToRemove; + } + else + { + /* Link the successor to the right side of the original parent */ + ParentNode->Right = NodeToRemove; + } + + /* Update the parent pointer of the successor to its new parent */ + SetParentNode(NodeToRemove, ParentNode); + NodeToRemove->Left = Node->Left; + + /* Update the parent pointer of the left child and copy the original node's color */ + SetParentNode(NodeToRemove->Left, NodeToRemove); + CopyNodeColor(NodeToRemove, Node); + } + + /* Check if the physically removed node was black */ + if(RemoveNodeColor == NodeBlack && Tree->Root != NULLPTR) + { + /* Fix up the tree properties */ + CurrentNode = Replacement; + ParentNode = ReplacementParent; + + /* Traverse up the tree */ + while(CurrentNode != Tree->Root && + (CurrentNode == NULLPTR || GetNodeColor(CurrentNode) == NodeBlack)) + { + /* Check if the current node is a left child */ + if(CurrentNode == ParentNode->Left) + { + /* Identify the sibling node on the right */ + SiblingNode = ParentNode->Right; + + /* Check if the sibling is red */ + if(GetNodeColor(SiblingNode) == NodeRed) + { + /* Recolor the sibling to black */ + SetNodeColor(SiblingNode, NodeBlack); + SetNodeColor(ParentNode, NodeRed); + + /* Perform a left rotation around the parent */ + RotateLeft(Tree, ParentNode); + SiblingNode = ParentNode->Right; + } + + /* Check if both children of the sibling are black */ + if((SiblingNode->Left == NULLPTR || GetNodeColor(SiblingNode->Left) == NodeBlack) && + (SiblingNode->Right == NULLPTR || GetNodeColor(SiblingNode->Right) == NodeBlack)) + { + /* Set the sibling color to red to restore black-height */ + SetNodeColor(SiblingNode, NodeRed); + + /* Move the current pointer up to the parent and continue checking */ + CurrentNode = ParentNode; + ParentNode = GetParentNode(CurrentNode); + } + else + { + /* Check if the sibling's right child is black */ + if(SiblingNode->Right == NULLPTR || GetNodeColor(SiblingNode->Right) == NodeBlack) + { + /* Check if the left child needs updating */ + if(SiblingNode->Left != NULLPTR) + { + /* Recolor the sibling's left child */ + SetNodeColor(SiblingNode->Left, NodeBlack); + } + + /* Set the sibling to red and perform the right rotation */ + SetNodeColor(SiblingNode, NodeRed); + RotateRight(Tree, SiblingNode); + SiblingNode = ParentNode->Right; + } + + /* Swap colors between sibling and parent and recolor right child to black */ + CopyNodeColor(SiblingNode, ParentNode); + SetNodeColor(ParentNode, NodeBlack); + + /* Check if the right child needs updating */ + if(SiblingNode->Right != NULLPTR) + { + /* Recolor the sibling's right child */ + SetNodeColor(SiblingNode->Right, NodeBlack); + } + + /* Perform a left rotation around the parent to restore balance */ + RotateLeft(Tree, ParentNode); + CurrentNode = Tree->Root; + + /* The tree properties are restored, terminate the loop */ + break; + } + } + else + { + /* Process the case where the current node is a right child */ + SiblingNode = ParentNode->Left; + + /* Check if the sibling is red */ + if(GetNodeColor(SiblingNode) == NodeRed) + { + /* Recolor the sibling to black */ + SetNodeColor(SiblingNode, NodeBlack); + SetNodeColor(ParentNode, NodeRed); + + /* Perform a right rotation around the parent */ + RotateRight(Tree, ParentNode); + SiblingNode = ParentNode->Left; + } + + /* Check if both children of the sibling are black */ + if((SiblingNode->Right == NULLPTR || GetNodeColor(SiblingNode->Right) == NodeBlack) && + (SiblingNode->Left == NULLPTR || GetNodeColor(SiblingNode->Left) == NodeBlack)) + { + /* Set the sibling color to red to restore black-height */ + SetNodeColor(SiblingNode, NodeRed); + CurrentNode = ParentNode; + ParentNode = GetParentNode(CurrentNode); + } + else + { + /* Check if the sibling's left child is black */ + if(SiblingNode->Left == NULLPTR || GetNodeColor(SiblingNode->Left) == NodeBlack) + { + /* Check if the right child needs updating */ + if(SiblingNode->Right != NULLPTR) + { + /* Recolor the sibling's right child */ + SetNodeColor(SiblingNode->Right, NodeBlack); + } + + /* Set the sibling to red and perform the right rotation */ + SetNodeColor(SiblingNode, NodeRed); + RotateLeft(Tree, SiblingNode); + SiblingNode = ParentNode->Left; + } + + /* Swap colors between sibling and parent and recolor right child to black */ + CopyNodeColor(SiblingNode, ParentNode); + SetNodeColor(ParentNode, NodeBlack); + + /* Check if the left child needs updating */ + if(SiblingNode->Left != NULLPTR) + { + /* Recolor the sibling's left child */ + SetNodeColor(SiblingNode->Left, NodeBlack); + } + + /* Perform a right rotation around the parent */ + RotateRight(Tree, ParentNode); + CurrentNode = Tree->Root; + + /* The tree properties are restored, terminate the loop */ + break; + } + } + } + + /* Check if the current node is not null */ + if(CurrentNode != NULLPTR) + { + /* Force the current node to be black to satisfy the red-black rules */ + SetNodeColor(CurrentNode, NodeBlack); + } + } +} + +/** + * Performs a left rotation around the specified node to maintain red-black tree balance. + * + * @param Tree + * Supplies a pointer to the RTL_RB_TREE structure containing the node. + * + * @param Node + * Supplies a pointer to the balanced node around which to perform the left rotation. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +RTL::RedBlackTree::RotateLeft(IN PRTL_RB_TREE Tree, + IN PRTL_BALANCED_NODE Node) +{ + PRTL_BALANCED_NODE ParentNode, RightNode; + + /* Establish the right child as the pivot node for the rotation */ + RightNode = Node->Right; + Node->Right = RightNode->Left; + + /* Transfer the left subtree of the pivot to the right subtree of the node */ + if(RightNode->Left != NULLPTR) + { + /* Update the parent pointer */ + SetParentNode(RightNode->Left, Node); + } + + /* Update the parent */ + ParentNode = GetParentNode(Node); + SetParentNode(RightNode, ParentNode); + + /* Link the parent of the original node to the new pivot node */ + if(ParentNode == NULLPTR) + { + /* Set the pivot new root */ + Tree->Root = RightNode; + } + else if(Node == ParentNode->Left) + { + /* Update the left child pointer of the parent */ + ParentNode->Left = RightNode; + } + else + { + /* Update the right child pointer of the parent */ + ParentNode->Right = RightNode; + } + + /* Place the original node as the left child of the pivot */ + RightNode->Left = Node; + SetParentNode(Node, RightNode); +} + +/** + * Performs a right rotation around the specified node to maintain red-black tree balance. + * + * @param Tree + * Supplies a pointer to the RTL_RB_TREE structure containing the node. + * + * @param Node + * Supplies a pointer to the balanced node around which to perform the right rotation. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +RTL::RedBlackTree::RotateRight(IN PRTL_RB_TREE Tree, + IN PRTL_BALANCED_NODE Node) +{ + PRTL_BALANCED_NODE LeftNode, ParentNode; + + /* Establish the left child as the pivot node for the rotation */ + LeftNode = Node->Left; + Node->Left = LeftNode->Right; + + /* Transfer the right subtree of the pivot to the left subtree of the node */ + if(LeftNode->Right != NULLPTR) + { + /* Update the parent pointer */ + SetParentNode(LeftNode->Right, Node); + } + + /* Update the parent */ + ParentNode = GetParentNode(Node); + SetParentNode(LeftNode, ParentNode); + + /* Link the parent of the original node to the new pivot node */ + if(ParentNode == NULLPTR) + { + /* Set the pivot new root */ + Tree->Root = LeftNode; + } + else if(Node == ParentNode->Right) + { + /* Update the right child pointer of the parent */ + ParentNode->Right = LeftNode; + } + else + { + /* Update the left child pointer of the parent */ + ParentNode->Left = LeftNode; + } + + /* Place the original node as the right child of the pivot */ + LeftNode->Right = Node; + SetParentNode(Node, LeftNode); +} + +/** + * Sets the node's color. Clears the color bit first, then applies the new color. + * + * @param Node + * Supplies a pointer to the balanced node for which to set the color. + * + * @param Color + * Specifies the new color to set for the node, either NodeRed or NodeBlack. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +RTL::RedBlackTree::SetNodeColor(OUT PRTL_BALANCED_NODE Node, + IN RTL_BALANCED_NODE_COLOR Color) +{ + /* Set the node color */ + Node->ParentValue = (Node->ParentValue & ~RTL_BALANCED_NODE_COLOR_MASK) | Color; +} + +/** + * Sets the parent node pointer while preserving the current color bits. + * + * @param Node + * Supplies a pointer to the balanced node for which to set the parent pointer. + * + * @param Parent + * Supplies a pointer to the new parent node to be set for the given node. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +RTL::RedBlackTree::SetParentNode(OUT PRTL_BALANCED_NODE Node, + IN PRTL_BALANCED_NODE Parent) +{ + /* Set the parent node pointer */ + Node->ParentValue = ((ULONG_PTR)Parent & ~RTL_BALANCED_NODE_RESERVED_PARENT_MASK) | + (Node->ParentValue & RTL_BALANCED_NODE_RESERVED_PARENT_MASK); +}