Source code of Windows XP (NT5)
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.

451 lines
11 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. svsutil.cxx
  5. Abstract:
  6. Miscellaneous useful utilities
  7. Author:
  8. Sergey Solyanik (SergeyS)
  9. --*/
  10. #include "pch.h"
  11. #pragma hdrstop
  12. #include <svsutil.hxx>
  13. //
  14. // Tree support, C-style interface
  15. //
  16. SVSTree *svsutil_GetTree (unsigned int uiChunkSize) {
  17. SVSTree *pTree = new SVSTree(uiChunkSize > 0 ? uiChunkSize : SVSUTIL_TREE_INITIAL);
  18. SVSUTIL_ASSERT(pTree);
  19. return pTree;
  20. }
  21. void svsutil_EmptyTree (SVSTree *pTree) {
  22. SVSUTIL_ASSERT (pTree);
  23. pTree->Empty ();
  24. }
  25. void svsutil_EmptyTreeWithCallback (SVSTree *pTree, void (*pfuncFree)(void *pvData, void *pvArg), void *a_pvArg) {
  26. SVSUTIL_ASSERT (pTree && pfuncFree);
  27. pTree->Empty (pfuncFree, a_pvArg);
  28. }
  29. void svsutil_DestroyTree (SVSTree *pTree) {
  30. SVSUTIL_ASSERT (pTree);
  31. delete pTree;
  32. }
  33. SVSTNode *svsutil_NextTreeNode (SVSTree *pTree, SVSTNode *pNode) {
  34. SVSUTIL_ASSERT (pTree && pNode);
  35. return pTree->Next (pNode);
  36. }
  37. SVSTNode *svsutil_PrevTreeNode (SVSTree *pTree, SVSTNode *pNode) {
  38. SVSUTIL_ASSERT (pTree && pNode);
  39. return pTree->Prev (pNode);
  40. }
  41. SVSTNode *svsutil_MinTreeNode (SVSTree *pTree) {
  42. SVSUTIL_ASSERT (pTree);
  43. return pTree->Min();
  44. }
  45. SVSTNode *svsutil_MaxTreeNode (SVSTree *pTree) {
  46. SVSUTIL_ASSERT (pTree);
  47. return pTree->Max ();
  48. }
  49. SVSTNode *svsutil_LocateTreeNode (SVSTree *pTree, SVSCKey cKey) {
  50. SVSUTIL_ASSERT (pTree);
  51. return pTree->Locate (cKey);
  52. }
  53. SVSTNode *svsutil_LocateLeftNeighborNode (SVSTree *pTree, SVSCKey cKey) {
  54. SVSUTIL_ASSERT (pTree);
  55. return pTree->LocateLeftNeighbor (cKey);
  56. }
  57. SVSTNode *svsutil_LocateRightNeighborNode (SVSTree *pTree, SVSCKey cKey) {
  58. SVSUTIL_ASSERT (pTree);
  59. return pTree->LocateRightNeighbor (cKey);
  60. }
  61. unsigned int svsutil_TreeToArray (SVSTree *pTree, void **appv) {
  62. SVSUTIL_ASSERT (pTree);
  63. return pTree->ToArray(appv);
  64. }
  65. unsigned int svsutil_GetTreeSize (SVSTree *pTree) {
  66. SVSUTIL_ASSERT (pTree);
  67. return pTree->Size();
  68. }
  69. SVSTNode *svsutil_InsertTreeNode (SVSTree *pTree, SVSCKey cKey, void *pvData) {
  70. SVSUTIL_ASSERT (pTree);
  71. return pTree->Insert (cKey, pvData);
  72. }
  73. void *svsutil_DeleteTreeNode (SVSTree *pTree, SVSTNode *pNode) {
  74. SVSUTIL_ASSERT (pTree && pNode);
  75. return pTree->Delete (pNode);
  76. }
  77. void *svsutil_GetTreeNodeData (SVSTNode *pNode) {
  78. SVSUTIL_ASSERT (pNode);
  79. return SVSTree::GetData (pNode);
  80. }
  81. SVSCKey svsutil_GetTreeNodeKey (SVSTNode *pNode) {
  82. SVSUTIL_ASSERT (pNode);
  83. return SVSTree::GetKey (pNode);
  84. }
  85. void svsutil_CompactTree (SVSTree *pTree) {
  86. SVSUTIL_ASSERT (pTree);
  87. pTree->Compact ();
  88. }
  89. //
  90. // Tree support, class
  91. //
  92. SVSTNode *SVSTree::Insert (SVSCKey cKey, void *pvData) {
  93. #if defined (SVSUTIL_DEBUG_TREE)
  94. RBTreeIntegrity();
  95. #endif
  96. SVSTNode *x = (SVSTNode *)svsutil_GetFixed (pNodeMem);
  97. SVSTNode *pNode = x;
  98. if (! x)
  99. {
  100. SVSUTIL_ASSERT (0);
  101. return NULL;
  102. }
  103. x->pLeft = x->pRight
  104. = x->pParent = pNil;
  105. x->cKey = cKey;
  106. x->pvData = pvData;
  107. x->iColor = SVSUTIL_COLOR_RED;
  108. TreeInsert (x);
  109. while ((x != pRoot) && (x->pParent->iColor == SVSUTIL_COLOR_RED))
  110. {
  111. if (x->pParent == x->pParent->pParent->pLeft)
  112. {
  113. SVSTNode *y = x->pParent->pParent->pRight;
  114. if (y->iColor == SVSUTIL_COLOR_RED)
  115. {
  116. x->pParent->iColor = SVSUTIL_COLOR_BLACK;
  117. y->iColor = SVSUTIL_COLOR_BLACK;
  118. x = x->pParent->pParent;
  119. x->iColor = SVSUTIL_COLOR_RED;
  120. }
  121. else
  122. {
  123. if (x == x->pParent->pRight)
  124. {
  125. x = x->pParent;
  126. LeftRotate (x);
  127. }
  128. x->pParent->iColor = SVSUTIL_COLOR_BLACK;
  129. x->pParent->pParent->iColor = SVSUTIL_COLOR_RED;
  130. RightRotate (x->pParent->pParent);
  131. }
  132. }
  133. else
  134. {
  135. SVSTNode *y = x->pParent->pParent->pLeft;
  136. if (y->iColor == SVSUTIL_COLOR_RED)
  137. {
  138. x->pParent->iColor = SVSUTIL_COLOR_BLACK;
  139. y->iColor = SVSUTIL_COLOR_BLACK;
  140. x = x->pParent->pParent;
  141. x->iColor = SVSUTIL_COLOR_RED;
  142. }
  143. else
  144. {
  145. if (x == x->pParent->pLeft)
  146. {
  147. x = x->pParent;
  148. RightRotate (x);
  149. }
  150. x->pParent->iColor = SVSUTIL_COLOR_BLACK;
  151. x->pParent->pParent->iColor = SVSUTIL_COLOR_RED;
  152. LeftRotate (x->pParent->pParent);
  153. }
  154. }
  155. }
  156. pRoot->iColor = SVSUTIL_COLOR_BLACK;
  157. #if defined (SVSUTIL_DEBUG_TREE)
  158. RBTreeIntegrity();
  159. #endif
  160. return pNode;
  161. }
  162. void SVSTree::DeleteFixup (SVSTNode *x) {
  163. while ((x != pRoot) && (x->iColor == SVSUTIL_COLOR_BLACK))
  164. {
  165. if (x == x->pParent->pLeft)
  166. {
  167. SVSTNode *w = x->pParent->pRight;
  168. if (w->iColor == SVSUTIL_COLOR_RED)
  169. {
  170. w->iColor = SVSUTIL_COLOR_BLACK;
  171. x->pParent->iColor = SVSUTIL_COLOR_RED;
  172. LeftRotate (x->pParent);
  173. w = x->pParent->pRight;
  174. }
  175. if ((w->pLeft->iColor == SVSUTIL_COLOR_BLACK) && (w->pRight->iColor == SVSUTIL_COLOR_BLACK))
  176. {
  177. w->iColor = SVSUTIL_COLOR_RED;
  178. x = x->pParent;
  179. }
  180. else
  181. {
  182. if (w->pRight->iColor == SVSUTIL_COLOR_BLACK)
  183. {
  184. w->pLeft->iColor = SVSUTIL_COLOR_BLACK;
  185. w->iColor = SVSUTIL_COLOR_RED;
  186. RightRotate (w);
  187. w = x->pParent->pRight;
  188. }
  189. w->iColor = x->pParent->iColor;
  190. x->pParent->iColor = SVSUTIL_COLOR_BLACK;
  191. w->pRight->iColor = SVSUTIL_COLOR_BLACK;
  192. LeftRotate (x->pParent);
  193. x = pRoot;
  194. }
  195. }
  196. else
  197. {
  198. SVSTNode *w = x->pParent->pLeft;
  199. if (w->iColor == SVSUTIL_COLOR_RED)
  200. {
  201. w->iColor = SVSUTIL_COLOR_BLACK;
  202. x->pParent->iColor = SVSUTIL_COLOR_RED;
  203. RightRotate (x->pParent);
  204. w = x->pParent->pLeft;
  205. }
  206. if ((w->pLeft->iColor == SVSUTIL_COLOR_BLACK) && (w->pRight->iColor == SVSUTIL_COLOR_BLACK))
  207. {
  208. w->iColor = SVSUTIL_COLOR_RED;
  209. x = x->pParent;
  210. }
  211. else
  212. {
  213. if (w->pLeft->iColor == SVSUTIL_COLOR_BLACK)
  214. {
  215. w->pRight->iColor = SVSUTIL_COLOR_BLACK;
  216. w->iColor = SVSUTIL_COLOR_RED;
  217. LeftRotate (w);
  218. w = x->pParent->pLeft;
  219. }
  220. w->iColor = x->pParent->iColor;
  221. x->pParent->iColor = SVSUTIL_COLOR_BLACK;
  222. w->pLeft->iColor = SVSUTIL_COLOR_BLACK;
  223. RightRotate (x->pParent);
  224. x = pRoot;
  225. }
  226. }
  227. }
  228. x->iColor = SVSUTIL_COLOR_BLACK;
  229. }
  230. void *SVSTree::Delete (SVSTNode *z) {
  231. #if defined (SVSUTIL_DEBUG_TREE)
  232. RBTreeIntegrity();
  233. SVSUTIL_ASSERT (InTree(z));
  234. #endif
  235. void *pvData = z->pvData;
  236. SVSTNode *y = ((z->pLeft == pNil) || (z->pRight == pNil)) ? z : Next(z);
  237. SVSTNode *x = (y->pLeft != pNil) ? y->pLeft : y->pRight;
  238. x->pParent = y->pParent;
  239. if (y->pParent == pNil)
  240. pRoot = x;
  241. else if (y == y->pParent->pLeft)
  242. y->pParent->pLeft = x;
  243. else
  244. y->pParent->pRight = x;
  245. int iColor = y->iColor;
  246. if (y != z)
  247. {
  248. // Insert y in z's place in the tree.
  249. // Note: this is longer than the standard data
  250. // exchange
  251. // z->cKey = y->cKey;
  252. // z->pvData = y->pvData;
  253. // but preserves pointer stability, so that
  254. // pointers to node can be kept outside...
  255. //
  256. if (z->pParent != pNil)
  257. {
  258. if (z == z->pParent->pRight)
  259. z->pParent->pRight = y;
  260. else
  261. z->pParent->pLeft = y;
  262. }
  263. y->pParent = z->pParent;
  264. if (z->pLeft != pNil)
  265. z->pLeft->pParent = y;
  266. y->pLeft = z->pLeft;
  267. if (z->pRight != pNil)
  268. z->pRight->pParent = y;
  269. y->pRight = z->pRight;
  270. y->iColor = z->iColor;
  271. if (x->pParent == z)
  272. x->pParent = y;
  273. if (pRoot == z)
  274. pRoot = y;
  275. }
  276. svsutil_FreeFixed (z, pNodeMem);
  277. if (iColor == SVSUTIL_COLOR_BLACK)
  278. DeleteFixup (x);
  279. pNil->pParent = pNil;
  280. iSize -= 1;
  281. #if defined (SVSUTIL_DEBUG_TREE)
  282. RBTreeIntegrity();
  283. #endif
  284. return pvData;
  285. }
  286. #if defined (SVSUTIL_DEBUG_TREE)
  287. //
  288. // This is only debug check for the tree
  289. //
  290. void SVSTree::RBTreeIntegrity (void) {
  291. SVSUTIL_ASSERT (iSize >= 0);
  292. SVSUTIL_ASSERT (pRoot && pNil && pNodeMem);
  293. SVSUTIL_ASSERT (pNil->pParent == pNil);
  294. SVSUTIL_ASSERT (pNil->pLeft == pNil);
  295. SVSUTIL_ASSERT (pNil->pRight == pNil);
  296. SVSUTIL_ASSERT (pNil->cKey == 0);
  297. SVSUTIL_ASSERT (pNil->pvData == NULL);
  298. SVSUTIL_ASSERT (pNil->iColor == SVSUTIL_COLOR_BLACK);
  299. static HANDLE s_hCurrentThread;
  300. HANDLE hCurrentThread = GetCurrentThread();
  301. SVSTNode *pMin = Min();
  302. if (! pMin)
  303. SVSUTIL_ASSERT ((pRoot == pNil) && (iSize == 0));
  304. else
  305. {
  306. unsigned int iCompSize = 0;
  307. while (pMin)
  308. {
  309. ++iCompSize;
  310. pMin = Next(pMin);
  311. }
  312. SVSUTIL_ASSERT (iCompSize == iSize);
  313. }
  314. if (pRoot != pNil)
  315. {
  316. SVSUTIL_ASSERT (pRoot->pParent == pNil);
  317. SVSUTIL_ASSERT (pRoot->iColor == SVSUTIL_COLOR_BLACK);
  318. CheckBlackHeight (pRoot);
  319. }
  320. s_hCurrentThread = hCurrentThread;
  321. }
  322. int SVSTree::CheckBlackHeight (SVSTNode *pNode) {
  323. if (pNode == pNil)
  324. return 1;
  325. int iBlackHeightLeft = CheckBlackHeight (pNode->pLeft);
  326. int iBlackHeightRight = CheckBlackHeight (pNode->pRight);
  327. SVSUTIL_ASSERT (iBlackHeightLeft == iBlackHeightRight);
  328. if (pNode->iColor == SVSUTIL_COLOR_RED)
  329. {
  330. SVSUTIL_ASSERT (pNode->pLeft->iColor == SVSUTIL_COLOR_BLACK);
  331. SVSUTIL_ASSERT (pNode->pRight->iColor == SVSUTIL_COLOR_BLACK);
  332. }
  333. if (pNode->pLeft != pNil)
  334. SVSUTIL_ASSERT (pNode->pLeft->pParent == pNode);
  335. if (pNode->pRight != pNil)
  336. SVSUTIL_ASSERT (pNode->pRight->pParent == pNode);
  337. return pNode->iColor == SVSUTIL_COLOR_BLACK ? iBlackHeightRight + 1 : iBlackHeightRight;
  338. }
  339. int SVSTree::InTree (SVSTNode *pNode) {
  340. SVSTNode *pMin = Min();
  341. if (! pMin)
  342. return FALSE;
  343. while (pMin)
  344. {
  345. if (pMin == pNode)
  346. return TRUE;
  347. pMin = Next(pMin);
  348. }
  349. return FALSE;
  350. }
  351. #endif /* SVSUTIL_DEBUG_TREE */