Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

325 lines
10 KiB

  1. //
  2. // Define the two pointer triangle splay links and the associated
  3. // manipuliation macros and routines. Note that the tri_splay_links should
  4. // be an opaque type. Routine are provided to traverse and manipulate the
  5. // structure.
  6. //
  7. // The structure of a tri_splay_links record is really
  8. //
  9. // typedef struct _TRI_SPLAY_LINKS {
  10. // ULONG ParSib; // struct _TRI_SPLAY_LINKS *ParSib;
  11. // ULONG Child; // struct _TRI_SPLAY_LINKS *Child;
  12. // } TRI_SPLAY_LINKS;
  13. //
  14. // However to aid in debugging (and without extra cost) we declare the
  15. // structure to be a union so we can also reference the links as pointers
  16. // in the debugger.
  17. //
  18. typedef union _TRI_SPLAY_LINKS {
  19. struct {
  20. ULONG ParSib;
  21. ULONG Child;
  22. } Refs;
  23. struct {
  24. union _TRI_SPLAY_LINKS *ParSibPtr;
  25. union _TRI_SPLAY_LINKS *ChildPtr;
  26. } Ptrs;
  27. } TRI_SPLAY_LINKS;
  28. typedef TRI_SPLAY_LINKS *PTRI_SPLAY_LINKS;
  29. //
  30. // The macro procedure InitializeSplayLinks takes as input a pointer to
  31. // splay link and initializes its substructure. All splay link nodes must
  32. // be initialized before they are used in the different splay routines and
  33. // macros.
  34. //
  35. // VOID
  36. // TriInitializeSplayLinks (
  37. // IN PTRI_SPLAY_LINKS Links
  38. // );
  39. //
  40. #define TriInitializeSplayLinks(Links) { \
  41. (Links)->Refs.ParSib = MakeIntoParentRef(Links); \
  42. (Links)->Refs.Child = 0; \
  43. }
  44. //
  45. // The macro function Parent takes as input a pointer to a splay link in a
  46. // tree and returns a pointer to the splay link of the parent of the input
  47. // node. If the input node is the root of the tree the return value is
  48. // equal to the input value.
  49. //
  50. // PTRI_SPLAY_LINKS
  51. // TriParent (
  52. // IN PTRI_SPLAY_LINKS Links
  53. // );
  54. //
  55. #define TriParent(Links) ( \
  56. (IsParentRef((Links)->Refs.ParSib)) ? \
  57. MakeIntoPointer((Links)->Refs.ParSib) \
  58. : \
  59. MakeIntoPointer(MakeIntoPointer((Links)->Refs.ParSib)->Refs.ParSib) \
  60. )
  61. //
  62. // The macro function LeftChild takes as input a pointer to a splay link in
  63. // a tree and returns a pointer to the splay link of the left child of the
  64. // input node. If the left child does not exist, the return value is NULL.
  65. //
  66. // PTRI_SPLAY_LINKS
  67. // TriLeftChild (
  68. // IN PTRI_SPLAY_LINKS Links
  69. // );
  70. //
  71. #define TriLeftChild(Links) ( \
  72. (IsLeftChildRef((Links)->Refs.Child)) ? \
  73. MakeIntoPointer((Links)->Refs.Child) \
  74. : \
  75. 0 \
  76. )
  77. //
  78. // The macro function RightChild takes as input a pointer to a splay link
  79. // in a tree and returns a pointer to the splay link of the right child of
  80. // the input node. If the right child does not exist, the return value is
  81. // NULL.
  82. //
  83. // PTRI_SPLAY_LINKS
  84. // TriRightChild (
  85. // IN PTRI_SPLAY_LINKS Links
  86. // );
  87. //
  88. #define TriRightChild(Links) ( \
  89. (IsRightChildRef((Links)->Refs.Child)) ? \
  90. MakeIntoPointer((Links)->Refs.Child) \
  91. : ( \
  92. (IsLeftChildRef((Links)->Refs.Child) && \
  93. IsSiblingRef(MakeIntoPointer((Links)->Refs.Child)->Refs.ParSib)) ? \
  94. MakeIntoPointer(MakeIntoPointer((Links)->Refs.Child)->Refs.ParSib) \
  95. : \
  96. 0 \
  97. ) \
  98. )
  99. //
  100. // The macro function IsRoot takes as input a pointer to a splay link
  101. // in a tree and returns TRUE if the input node is the root of the tree,
  102. // otherwise it returns FALSE.
  103. //
  104. // BOOLEAN
  105. // TriIsRoot (
  106. // IN PTRI_SPLAY_LINKS Links
  107. // );
  108. //
  109. #define TriIsRoot(Links) ( \
  110. (IsParentRef((Links)->Refs.ParSib) && MakeIntoPointer((Links)->Refs.ParSib) == (Links)) ? \
  111. TRUE \
  112. : \
  113. FALSE \
  114. )
  115. //
  116. // The macro function IsLeftChild takes as input a pointer to a splay link
  117. // in a tree and returns TRUE if the input node is the left child of its
  118. // parent, otherwise it returns FALSE. Note that if the input link is the
  119. // root node this function returns FALSE.
  120. //
  121. // BOOLEAN
  122. // TriIsLeftChild (
  123. // IN PTRI_SPLAY_LINKS Links
  124. // );
  125. //
  126. #define TriIsLeftChild(Links) ( \
  127. (TriLeftChild(TriParent(Links)) == (Links)) ? \
  128. TRUE \
  129. : \
  130. FALSE \
  131. )
  132. //
  133. // The macro function IsRightChild takes as input a pointer to a splay link
  134. // in a tree and returns TRUE if the input node is the right child of its
  135. // parent, otherwise it returns FALSE. Note that if the input link is the
  136. // root node this function returns FALSE.
  137. //
  138. // BOOLEAN
  139. // TriIsRightChild (
  140. // IN PTRI_SPLAY_LINKS Links
  141. // );
  142. //
  143. #define TriIsRightChild(Links) ( \
  144. (TriRightChild(TriParent(Links)) == (Links)) ? \
  145. TRUE \
  146. : \
  147. FALSE \
  148. )
  149. //
  150. // The macro procedure InsertAsLeftChild takes as input a pointer to a splay
  151. // link in a tree and a pointer to a node not in a tree. It inserts the
  152. // second node as the left child of the first node. The first node must not
  153. // already have a left child, and the second node must not already have a
  154. // parent.
  155. //
  156. // VOID
  157. // TriInsertAsLeftChild (
  158. // IN PTRI_SPLAY_LINKS ParentLinks,
  159. // IN PTRI_SPLAY_LINKS ChildLinks
  160. // );
  161. //
  162. #define TriInsertAsLeftChild(ParentLinks,ChildLinks) { \
  163. PTRI_SPLAY_LINKS RightChild; \
  164. if ((ParentLinks)->Refs.Child == 0) { \
  165. (ParentLinks)->Refs.Child = MakeIntoLeftChildRef(ChildLinks); \
  166. (ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
  167. } else { \
  168. RightChild = TriRightChild(ParentLinks); \
  169. (ParentLinks)->Refs.Child = MakeIntoLeftChildRef(ChildLinks); \
  170. (ChildLinks)->Refs.ParSib = MakeIntoSiblingRef(RightChild); \
  171. } \
  172. }
  173. //
  174. // The macro procedure InsertAsRightChild takes as input a pointer to a splay
  175. // link in a tree and a pointer to a node not in a tree. It inserts the
  176. // second node as the right child of the first node. The first node must not
  177. // already have a right child, and the second node must not already have a
  178. // parent.
  179. //
  180. // VOID
  181. // TriInsertAsRightChild (
  182. // IN PTRI_SPLAY_LINKS ParentLinks,
  183. // IN PTRI_SPLAY_LINKS ChildLinks
  184. // );
  185. //
  186. #define TriInsertAsRightChild(ParentLinks,ChildLinks) { \
  187. PTRI_SPLAY_LINKS LeftChild; \
  188. if ((ParentLinks)->Refs.Child == 0) { \
  189. (ParentLinks)->Refs.Child = MakeIntoRightChildRef(ChildLinks); \
  190. (ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
  191. } else { \
  192. LeftChild = TriLeftChild(ParentLinks); \
  193. LeftChild->Refs.ParSib = MakeIntoSiblingRef(ChildLinks); \
  194. (ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
  195. } \
  196. }
  197. //
  198. // The Splay function takes as input a pointer to a splay link in a tree
  199. // and splays the tree. Its function return value is a pointer to the
  200. // root of the splayed tree.
  201. //
  202. PTRI_SPLAY_LINKS
  203. TriSplay (
  204. IN PTRI_SPLAY_LINKS Links
  205. );
  206. //
  207. // The Delete function takes as input a pointer to a splay link in a tree
  208. // and deletes that node from the tree. Its function return value is a
  209. // pointer to the root of the tree. If the tree is now empty, the return
  210. // value is NULL.
  211. //
  212. PTRI_SPLAY_LINKS
  213. TriDelete (
  214. IN PTRI_SPLAY_LINKS Links
  215. );
  216. //
  217. // The SubtreeSuccessor function takes as input a pointer to a splay link
  218. // in a tree and returns a pointer to the successor of the input node of
  219. // the substree rooted at the input node. If there is not a successor, the
  220. // return value is NULL.
  221. //
  222. PTRI_SPLAY_LINKS
  223. TriSubtreeSuccessor (
  224. IN PTRI_SPLAY_LINKS Links
  225. );
  226. //
  227. // The SubtreePredecessor function takes as input a pointer to a splay link
  228. // in a tree and returns a pointer to the predecessor of the input node of
  229. // the substree rooted at the input node. If there is not a predecessor,
  230. // the return value is NULL.
  231. //
  232. PTRI_SPLAY_LINKS
  233. TriSubtreePredecessor (
  234. IN PTRI_SPLAY_LINKS Links
  235. );
  236. //
  237. // The RealSuccessor function takes as input a pointer to a splay link
  238. // in a tree and returns a pointer to the successor of the input node within
  239. // the entire tree. If there is not a successor, the return value is NULL.
  240. //
  241. PTRI_SPLAY_LINKS
  242. TriRealSuccessor (
  243. IN PTRI_SPLAY_LINKS Links
  244. );
  245. //
  246. // The RealPredecessor function takes as input a pointer to a splay link
  247. // in a tree and returns a pointer to the predecessor of the input node
  248. // within the entire tree. If there is not a predecessor, the return value
  249. // is NULL.
  250. //
  251. PTRI_SPLAY_LINKS
  252. TriRealPredecessor (
  253. IN PTRI_SPLAY_LINKS Links
  254. );
  255. //
  256. // The remainder of this module really belong in triangle.c None of
  257. // the macros or routines are (logically) exported for use by the programmer
  258. // however they need to appear in this module to allow the earlier macros
  259. // to function properly.
  260. //
  261. // In the splay record (declared earlier) the low order bit of the
  262. // ParSib field indicates whether the link is to a Parent or a Sibling, and
  263. // the low order bit of the Child field is used to indicate if the link
  264. // is to a left child or a right child. The values are:
  265. //
  266. // A parent field has the lower bit set to 0
  267. // A sibling field has the lower bit set to 1
  268. // A left child field has the lower bit set to 0
  269. // A right child field has the lower bit set to 1
  270. //
  271. // The comments and code in triangle.c use the term "Ref" to indicate a
  272. // ParSib field or a Child field with the low order bit to indicate its type.
  273. // A ref cannot be directly used as a pointer. The following macros help
  274. // in deciding the type of a ref and making refs from pointers. There is
  275. // also a macro (MakeIntoPointer) that takes a ref and returns a pointer.
  276. //
  277. #define IsParentRef(Ulong) (((((ULONG)Ulong) & 1) == 0) && ((Ulong) != 0) ? TRUE : FALSE)
  278. #define MakeIntoParentRef(Ulong) (((ULONG)Ulong) & 0xfffffffc)
  279. #define IsSiblingRef(Ulong) ((((ULONG)Ulong) & 1) == 1 ? TRUE : FALSE)
  280. #define MakeIntoSiblingRef(Ulong) (((ULONG)Ulong) | 1)
  281. #define IsLeftChildRef(Ulong) (((((ULONG)Ulong) & 1) == 0) && ((Ulong) != 0) ? TRUE : FALSE)
  282. #define MakeIntoLeftChildRef(Ulong) (((ULONG)Ulong) & 0xfffffffc)
  283. #define IsRightChildRef(Ulong) ((((ULONG)Ulong) & 1) == 1 ? TRUE : FALSE)
  284. #define MakeIntoRightChildRef(Ulong) (((ULONG)Ulong) | 1)
  285. #define MakeIntoPointer(Ulong) ((PTRI_SPLAY_LINKS)((Ulong) & 0xfffffffc))