windows-nt/Source/XPSP1/NT/base/ntos/rtl/triangle.h

326 lines
9.9 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// Define the two pointer triangle splay links and the associated
// manipuliation macros and routines. Note that the tri_splay_links should
// be an opaque type. Routine are provided to traverse and manipulate the
// structure.
//
// The structure of a tri_splay_links record is really
//
// typedef struct _TRI_SPLAY_LINKS {
// ULONG ParSib; // struct _TRI_SPLAY_LINKS *ParSib;
// ULONG Child; // struct _TRI_SPLAY_LINKS *Child;
// } TRI_SPLAY_LINKS;
//
// However to aid in debugging (and without extra cost) we declare the
// structure to be a union so we can also reference the links as pointers
// in the debugger.
//
typedef union _TRI_SPLAY_LINKS {
struct {
ULONG ParSib;
ULONG Child;
} Refs;
struct {
union _TRI_SPLAY_LINKS *ParSibPtr;
union _TRI_SPLAY_LINKS *ChildPtr;
} Ptrs;
} TRI_SPLAY_LINKS;
typedef TRI_SPLAY_LINKS *PTRI_SPLAY_LINKS;
//
// The macro procedure InitializeSplayLinks takes as input a pointer to
// splay link and initializes its substructure. All splay link nodes must
// be initialized before they are used in the different splay routines and
// macros.
//
// VOID
// TriInitializeSplayLinks (
// IN PTRI_SPLAY_LINKS Links
// );
//
#define TriInitializeSplayLinks(Links) { \
(Links)->Refs.ParSib = MakeIntoParentRef(Links); \
(Links)->Refs.Child = 0; \
}
//
// The macro function Parent takes as input a pointer to a splay link in a
// tree and returns a pointer to the splay link of the parent of the input
// node. If the input node is the root of the tree the return value is
// equal to the input value.
//
// PTRI_SPLAY_LINKS
// TriParent (
// IN PTRI_SPLAY_LINKS Links
// );
//
#define TriParent(Links) ( \
(IsParentRef((Links)->Refs.ParSib)) ? \
MakeIntoPointer((Links)->Refs.ParSib) \
: \
MakeIntoPointer(MakeIntoPointer((Links)->Refs.ParSib)->Refs.ParSib) \
)
//
// The macro function LeftChild takes as input a pointer to a splay link in
// a tree and returns a pointer to the splay link of the left child of the
// input node. If the left child does not exist, the return value is NULL.
//
// PTRI_SPLAY_LINKS
// TriLeftChild (
// IN PTRI_SPLAY_LINKS Links
// );
//
#define TriLeftChild(Links) ( \
(IsLeftChildRef((Links)->Refs.Child)) ? \
MakeIntoPointer((Links)->Refs.Child) \
: \
0 \
)
//
// The macro function RightChild takes as input a pointer to a splay link
// in a tree and returns a pointer to the splay link of the right child of
// the input node. If the right child does not exist, the return value is
// NULL.
//
// PTRI_SPLAY_LINKS
// TriRightChild (
// IN PTRI_SPLAY_LINKS Links
// );
//
#define TriRightChild(Links) ( \
(IsRightChildRef((Links)->Refs.Child)) ? \
MakeIntoPointer((Links)->Refs.Child) \
: ( \
(IsLeftChildRef((Links)->Refs.Child) && \
IsSiblingRef(MakeIntoPointer((Links)->Refs.Child)->Refs.ParSib)) ? \
MakeIntoPointer(MakeIntoPointer((Links)->Refs.Child)->Refs.ParSib) \
: \
0 \
) \
)
//
// The macro function IsRoot takes as input a pointer to a splay link
// in a tree and returns TRUE if the input node is the root of the tree,
// otherwise it returns FALSE.
//
// BOOLEAN
// TriIsRoot (
// IN PTRI_SPLAY_LINKS Links
// );
//
#define TriIsRoot(Links) ( \
(IsParentRef((Links)->Refs.ParSib) && MakeIntoPointer((Links)->Refs.ParSib) == (Links)) ? \
TRUE \
: \
FALSE \
)
//
// The macro function IsLeftChild takes as input a pointer to a splay link
// in a tree and returns TRUE if the input node is the left child of its
// parent, otherwise it returns FALSE. Note that if the input link is the
// root node this function returns FALSE.
//
// BOOLEAN
// TriIsLeftChild (
// IN PTRI_SPLAY_LINKS Links
// );
//
#define TriIsLeftChild(Links) ( \
(TriLeftChild(TriParent(Links)) == (Links)) ? \
TRUE \
: \
FALSE \
)
//
// The macro function IsRightChild takes as input a pointer to a splay link
// in a tree and returns TRUE if the input node is the right child of its
// parent, otherwise it returns FALSE. Note that if the input link is the
// root node this function returns FALSE.
//
// BOOLEAN
// TriIsRightChild (
// IN PTRI_SPLAY_LINKS Links
// );
//
#define TriIsRightChild(Links) ( \
(TriRightChild(TriParent(Links)) == (Links)) ? \
TRUE \
: \
FALSE \
)
//
// The macro procedure InsertAsLeftChild takes as input a pointer to a splay
// link in a tree and a pointer to a node not in a tree. It inserts the
// second node as the left child of the first node. The first node must not
// already have a left child, and the second node must not already have a
// parent.
//
// VOID
// TriInsertAsLeftChild (
// IN PTRI_SPLAY_LINKS ParentLinks,
// IN PTRI_SPLAY_LINKS ChildLinks
// );
//
#define TriInsertAsLeftChild(ParentLinks,ChildLinks) { \
PTRI_SPLAY_LINKS RightChild; \
if ((ParentLinks)->Refs.Child == 0) { \
(ParentLinks)->Refs.Child = MakeIntoLeftChildRef(ChildLinks); \
(ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
} else { \
RightChild = TriRightChild(ParentLinks); \
(ParentLinks)->Refs.Child = MakeIntoLeftChildRef(ChildLinks); \
(ChildLinks)->Refs.ParSib = MakeIntoSiblingRef(RightChild); \
} \
}
//
// The macro procedure InsertAsRightChild takes as input a pointer to a splay
// link in a tree and a pointer to a node not in a tree. It inserts the
// second node as the right child of the first node. The first node must not
// already have a right child, and the second node must not already have a
// parent.
//
// VOID
// TriInsertAsRightChild (
// IN PTRI_SPLAY_LINKS ParentLinks,
// IN PTRI_SPLAY_LINKS ChildLinks
// );
//
#define TriInsertAsRightChild(ParentLinks,ChildLinks) { \
PTRI_SPLAY_LINKS LeftChild; \
if ((ParentLinks)->Refs.Child == 0) { \
(ParentLinks)->Refs.Child = MakeIntoRightChildRef(ChildLinks); \
(ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
} else { \
LeftChild = TriLeftChild(ParentLinks); \
LeftChild->Refs.ParSib = MakeIntoSiblingRef(ChildLinks); \
(ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
} \
}
//
// The Splay function takes as input a pointer to a splay link in a tree
// and splays the tree. Its function return value is a pointer to the
// root of the splayed tree.
//
PTRI_SPLAY_LINKS
TriSplay (
IN PTRI_SPLAY_LINKS Links
);
//
// The Delete function takes as input a pointer to a splay link in a tree
// and deletes that node from the tree. Its function return value is a
// pointer to the root of the tree. If the tree is now empty, the return
// value is NULL.
//
PTRI_SPLAY_LINKS
TriDelete (
IN PTRI_SPLAY_LINKS Links
);
//
// The SubtreeSuccessor function takes as input a pointer to a splay link
// in a tree and returns a pointer to the successor of the input node of
// the substree rooted at the input node. If there is not a successor, the
// return value is NULL.
//
PTRI_SPLAY_LINKS
TriSubtreeSuccessor (
IN PTRI_SPLAY_LINKS Links
);
//
// The SubtreePredecessor function takes as input a pointer to a splay link
// in a tree and returns a pointer to the predecessor of the input node of
// the substree rooted at the input node. If there is not a predecessor,
// the return value is NULL.
//
PTRI_SPLAY_LINKS
TriSubtreePredecessor (
IN PTRI_SPLAY_LINKS Links
);
//
// The RealSuccessor function takes as input a pointer to a splay link
// in a tree and returns a pointer to the successor of the input node within
// the entire tree. If there is not a successor, the return value is NULL.
//
PTRI_SPLAY_LINKS
TriRealSuccessor (
IN PTRI_SPLAY_LINKS Links
);
//
// The RealPredecessor function takes as input a pointer to a splay link
// in a tree and returns a pointer to the predecessor of the input node
// within the entire tree. If there is not a predecessor, the return value
// is NULL.
//
PTRI_SPLAY_LINKS
TriRealPredecessor (
IN PTRI_SPLAY_LINKS Links
);
//
// The remainder of this module really belong in triangle.c None of
// the macros or routines are (logically) exported for use by the programmer
// however they need to appear in this module to allow the earlier macros
// to function properly.
//
// In the splay record (declared earlier) the low order bit of the
// ParSib field indicates whether the link is to a Parent or a Sibling, and
// the low order bit of the Child field is used to indicate if the link
// is to a left child or a right child. The values are:
//
// A parent field has the lower bit set to 0
// A sibling field has the lower bit set to 1
// A left child field has the lower bit set to 0
// A right child field has the lower bit set to 1
//
// The comments and code in triangle.c use the term "Ref" to indicate a
// ParSib field or a Child field with the low order bit to indicate its type.
// A ref cannot be directly used as a pointer. The following macros help
// in deciding the type of a ref and making refs from pointers. There is
// also a macro (MakeIntoPointer) that takes a ref and returns a pointer.
//
#define IsParentRef(Ulong) (((((ULONG)Ulong) & 1) == 0) && ((Ulong) != 0) ? TRUE : FALSE)
#define MakeIntoParentRef(Ulong) (((ULONG)Ulong) & 0xfffffffc)
#define IsSiblingRef(Ulong) ((((ULONG)Ulong) & 1) == 1 ? TRUE : FALSE)
#define MakeIntoSiblingRef(Ulong) (((ULONG)Ulong) | 1)
#define IsLeftChildRef(Ulong) (((((ULONG)Ulong) & 1) == 0) && ((Ulong) != 0) ? TRUE : FALSE)
#define MakeIntoLeftChildRef(Ulong) (((ULONG)Ulong) & 0xfffffffc)
#define IsRightChildRef(Ulong) ((((ULONG)Ulong) & 1) == 1 ? TRUE : FALSE)
#define MakeIntoRightChildRef(Ulong) (((ULONG)Ulong) | 1)
#define MakeIntoPointer(Ulong) ((PTRI_SPLAY_LINKS)((Ulong) & 0xfffffffc))