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.

297 lines
7.3 KiB

  1. /***************************************************************************\
  2. *
  3. * File: TreeNode.inl
  4. *
  5. * History:
  6. * 1/05/2000: JStall: Created
  7. *
  8. * Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
  9. *
  10. \***************************************************************************/
  11. #if !defined(BASE__TreeNode_inl__INCLUDED)
  12. #define BASE__TreeNode_inl__INCLUDED
  13. #pragma once
  14. /***************************************************************************\
  15. *****************************************************************************
  16. *
  17. * class TreeNode
  18. *
  19. *****************************************************************************
  20. \***************************************************************************/
  21. //------------------------------------------------------------------------------
  22. template <class T>
  23. inline
  24. TreeNodeT<T>::TreeNodeT()
  25. {
  26. }
  27. //------------------------------------------------------------------------------
  28. template <class T>
  29. inline
  30. TreeNodeT<T>::~TreeNodeT()
  31. {
  32. }
  33. //------------------------------------------------------------------------------
  34. template <class T>
  35. inline T *
  36. TreeNodeT<T>::GetTopSibling() const
  37. {
  38. T * pTreeNode = const_cast<T *> (this);
  39. while (pTreeNode->m_ptnPrev != NULL) {
  40. pTreeNode = pTreeNode->m_ptnPrev;
  41. }
  42. return pTreeNode;
  43. }
  44. //------------------------------------------------------------------------------
  45. template <class T>
  46. inline T *
  47. TreeNodeT<T>::GetBottomSibling() const
  48. {
  49. TreeNodeT<T> * pTreeNode = const_cast<TreeNodeT<T> *> (this);
  50. while (pTreeNode->m_ptnNext != NULL) {
  51. pTreeNode = pTreeNode->m_ptnNext;
  52. }
  53. return (T *) pTreeNode;
  54. }
  55. //------------------------------------------------------------------------------
  56. template <class T>
  57. inline T *
  58. TreeNodeT<T>::GetParent() const
  59. {
  60. return (T *) m_ptnParent;
  61. }
  62. //------------------------------------------------------------------------------
  63. template <class T>
  64. inline T *
  65. TreeNodeT<T>::GetPrev() const
  66. {
  67. return (T *) m_ptnPrev;
  68. }
  69. //------------------------------------------------------------------------------
  70. template <class T>
  71. inline T *
  72. TreeNodeT<T>::GetNext() const
  73. {
  74. return (T *) m_ptnNext;
  75. }
  76. //------------------------------------------------------------------------------
  77. template <class T>
  78. inline T *
  79. TreeNodeT<T>::GetTopChild() const
  80. {
  81. return (T *) m_ptnChild;
  82. }
  83. //------------------------------------------------------------------------------
  84. template <class T>
  85. inline T *
  86. TreeNodeT<T>::GetBottomChild() const
  87. {
  88. if (m_ptnChild != NULL) {
  89. return GetTopChild()->GetBottomSibling();
  90. } else {
  91. return NULL;
  92. }
  93. }
  94. /***************************************************************************\
  95. *
  96. * TreeNodeT::DoLink
  97. *
  98. * DoLink chains _this_ node into the tree. A sibling and a parent (may) be
  99. * given as reference, depending on the situation. This node (the one
  100. * being linked) _must_ have already been unlinked previously.
  101. *
  102. \***************************************************************************/
  103. template <class T>
  104. void
  105. TreeNodeT<T>::DoLink(
  106. IN T * ptnParent, // New parent
  107. IN T * ptnSibling, // Node to link to this (unlinked) Node
  108. IN ELinkType lt) // Position of ptn relative to this
  109. {
  110. // Check parameters
  111. AssertWritePtr(ptnParent);
  112. // Verify the TreeNode is unlinked
  113. Assert((m_ptnNext == NULL) && (m_ptnPrev == NULL) && (m_ptnParent == NULL));
  114. //
  115. // Link this TreeNode to the parent.
  116. //
  117. m_ptnParent = ptnParent;
  118. TreeNodeT<T> * ptnOldChild = ptnParent->m_ptnChild;
  119. if (ptnOldChild == NULL) {
  120. //
  121. // Simple case, no siblings so just do it.
  122. //
  123. AssertMsg(ptnSibling == NULL, "Parent doesn't have any children");
  124. ptnParent->m_ptnChild = this;
  125. } else {
  126. //
  127. // Uggh- complex case, so need to Link this TreeNode to its new siblings
  128. //
  129. switch (lt) {
  130. case ltBefore:
  131. AssertWritePtr(ptnSibling);
  132. m_ptnNext = ptnSibling;
  133. m_ptnPrev = ptnSibling->m_ptnPrev;
  134. ptnSibling->m_ptnPrev = this;
  135. if (m_ptnPrev != NULL) {
  136. m_ptnPrev->m_ptnNext = this;
  137. }
  138. break;
  139. case ltBehind:
  140. AssertWritePtr(ptnSibling);
  141. m_ptnPrev = ptnSibling;
  142. m_ptnNext = ptnSibling->m_ptnNext;
  143. ptnSibling->m_ptnNext = this;
  144. if (m_ptnNext != NULL) {
  145. m_ptnNext->m_ptnPrev = this;
  146. }
  147. break;
  148. case ltAny:
  149. case ltTop:
  150. ptnParent->m_ptnChild = this;
  151. m_ptnNext = ptnOldChild;
  152. if (ptnOldChild != NULL) {
  153. ptnOldChild->m_ptnPrev = this;
  154. }
  155. break;
  156. case ltBottom:
  157. ptnOldChild = ptnOldChild->GetBottomSibling();
  158. ptnOldChild->m_ptnNext = this;
  159. m_ptnPrev = ptnOldChild;
  160. break;
  161. default:
  162. AssertMsg(0, "Unknown link type");
  163. }
  164. }
  165. }
  166. /***************************************************************************\
  167. *
  168. * TreeNode::DoUnlink
  169. *
  170. * DoUnlink() removes this TreeNode from the TreeNode tree. The parents and
  171. * siblings of the TreeNode are properly modified.
  172. *
  173. \***************************************************************************/
  174. template <class T>
  175. void
  176. TreeNodeT<T>::DoUnlink()
  177. {
  178. //
  179. // Unlink from the parent
  180. //
  181. if (m_ptnParent != NULL) {
  182. if (m_ptnParent->m_ptnChild == this) {
  183. m_ptnParent->m_ptnChild = m_ptnNext;
  184. }
  185. }
  186. //
  187. // Unlink from siblings
  188. //
  189. if (m_ptnNext != NULL) {
  190. m_ptnNext->m_ptnPrev = m_ptnPrev;
  191. }
  192. if (m_ptnPrev != NULL) {
  193. m_ptnPrev->m_ptnNext = m_ptnNext;
  194. }
  195. m_ptnParent = NULL;
  196. m_ptnNext = NULL;
  197. m_ptnPrev = NULL;
  198. }
  199. #if DBG
  200. template <class T>
  201. inline BOOL
  202. TreeNodeT<T>::DEBUG_IsChild(const TreeNodeT<T> * pChild) const
  203. {
  204. TreeNodeT<T> * pCur = m_ptnChild;
  205. while (pCur != NULL) {
  206. if (pCur == pChild) {
  207. return TRUE;
  208. }
  209. pCur = pCur->m_ptnNext;
  210. }
  211. return FALSE;
  212. }
  213. /***************************************************************************\
  214. *
  215. * TreeNodeT<T>::DEBUG_AssertValid
  216. *
  217. * DEBUG_AssertValid() provides a DEBUG-only mechanism to perform rich
  218. * validation of an object to attempt to determine if the object is still
  219. * valid. This is used during debugging to help track damaged objects
  220. *
  221. \***************************************************************************/
  222. template <class T>
  223. void
  224. TreeNodeT<T>::DEBUG_AssertValid() const
  225. {
  226. if (m_ptnParent != NULL) {
  227. Assert(m_ptnParent->DEBUG_IsChild(this));
  228. }
  229. if (m_ptnNext != NULL) {
  230. Assert(m_ptnNext->m_ptnPrev == this);
  231. }
  232. if (m_ptnPrev != NULL) {
  233. Assert(m_ptnPrev->m_ptnNext == this);
  234. }
  235. if (m_ptnChild != NULL) {
  236. Assert(m_ptnChild->m_ptnParent == this);
  237. }
  238. }
  239. #endif // DBG
  240. #endif // BASE__TreeNode_inl__INCLUDED