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.

1420 lines
40 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. Triangle.c
  5. Abstract:
  6. This module implements the general splay utilities for a two link
  7. triangular splay structure.
  8. Author:
  9. Gary Kimura [GaryKi] 28-May-1989
  10. Environment:
  11. Pure utility routine
  12. Revision History:
  13. --*/
  14. #include <nt.h>
  15. #include "triangle.h"
  16. //
  17. // There are three type of swap macros. The first two (are really the same)
  18. // are used to swap pointer and ulongs. The last macro is used to swap refs
  19. // but it does not swap the ref type flags.
  20. //
  21. #define SwapPointers(Ptr1, Ptr2) { \
  22. PVOID _SWAP_POINTER_TEMP; \
  23. _SWAP_POINTER_TEMP = (PVOID)(Ptr1); \
  24. (Ptr1) = (Ptr2); \
  25. (Ptr2) = _SWAP_POINTER_TEMP; \
  26. }
  27. #define SwapUlongs(Ptr1, Ptr2) { \
  28. ULONG _SWAP_POINTER_TEMP; \
  29. _SWAP_POINTER_TEMP = (ULONG)(Ptr1); \
  30. (Ptr1) = (Ptr2); \
  31. (Ptr2) = _SWAP_POINTER_TEMP; \
  32. }
  33. #define SwapRefsButKeepFlags(Ref1, Ref2) { \
  34. ULONG _SWAP_ULONG_TEMP; \
  35. _SWAP_ULONG_TEMP = (ULONG)(Ref1); \
  36. (Ref1) = ((Ref2) & 0xfffffffc) | ((Ref1) & 0x00000003); \
  37. (Ref2) = (_SWAP_ULONG_TEMP & 0xfffffffc) | ((Ref2) & 0x00000003); \
  38. }
  39. //
  40. // The macro SetRefViaPointer takes a pointer to a ref and checks to see if
  41. // it is a valid pointer. If it is a valid pointer it copies in the ref
  42. // a ulong, but does not overwrite the ref flags already in the ref.
  43. //
  44. #define SetRefViaPointer(Ref, Ulong) { \
  45. if (Ref != NULL) { \
  46. (*(Ref)) = (((ULONG)(Ulong)) & 0xfffffffc) | ((ULONG)(*(Ref)) & 0x00000003); \
  47. } \
  48. }
  49. //
  50. // The following five procedures are local to triangle.c and are used to
  51. // help manipluate the splay links. The first two procedures take a pointer
  52. // to a splay link and returns the address of the ref that points back to the
  53. // input link, via either the parent or child. They return NULL if there is
  54. // not a back pointer. The result of these two procedures is often used in
  55. // the code with the SetRefViaPointer macro. The third procedure is used
  56. // to swap the position to two splay links in the tree (i.e., the links swap
  57. // position, but everyone else stays stationary). This is a general procedure
  58. // that can will swap any two nodes, irregardless of their relative positions
  59. // in the tree. The last two procedures do a single rotation about a
  60. // tree node. They either rotate left or rotate right and assume that the
  61. // appropriate child exists (i.e., for rotate left a right child exists and
  62. // for rotate right a left child exists).
  63. //
  64. PULONG
  65. TriAddressOfBackRefViaParent (
  66. IN PTRI_SPLAY_LINKS Links
  67. );
  68. PULONG
  69. TriAddressOfBackRefViaChild (
  70. IN PTRI_SPLAY_LINKS Links
  71. );
  72. VOID
  73. TriSwapSplayLinks (
  74. IN PTRI_SPLAY_LINKS Link1,
  75. IN PTRI_SPLAY_LINKS Link2
  76. );
  77. VOID
  78. TriRotateRight (
  79. IN PTRI_SPLAY_LINKS Links
  80. );
  81. VOID
  82. TriRotateLeft (
  83. IN PTRI_SPLAY_LINKS Links
  84. );
  85. PTRI_SPLAY_LINKS
  86. TriSplay (
  87. IN PTRI_SPLAY_LINKS Links
  88. )
  89. /*++
  90. Routine Description:
  91. This Splay function takes as input a pointer to a splay link in a tree
  92. and splays the tree. Its function return value is a pointer to the
  93. root of the splayed tree.
  94. Arguments:
  95. Links - Supplies the pointer to a splay link in a tree
  96. Return Values:
  97. PRTI_SPLAY_LINKS - Returns a pointer to the root of the splayed tree
  98. --*/
  99. {
  100. PTRI_SPLAY_LINKS Parent;
  101. PTRI_SPLAY_LINKS GrandParent;
  102. //
  103. // While Links is not the root we test and rotate until it is the root.
  104. //
  105. while (!TriIsRoot(Links)) {
  106. //
  107. // Get Parent and then check if we don't have a grandparent.
  108. //
  109. Parent = TriParent(Links);
  110. if (TriIsRoot(Parent)) {
  111. //
  112. // No grandparent so check for single rotation
  113. //
  114. if (TriIsLeftChild(Links)) {
  115. //
  116. // do the following single rotation
  117. //
  118. // Parent Links
  119. // / ==> \
  120. // Links Parent
  121. //
  122. TriRotateRight(Parent);
  123. } else { // TriIsRightChild(Links)
  124. //
  125. // do the following single rotation
  126. //
  127. //
  128. // Parent Links
  129. // \ ==> /
  130. // Links Parent
  131. //
  132. TriRotateLeft(Parent);
  133. }
  134. } else { // !TriIsRoot(Parent)
  135. //
  136. // Get grandparent and check for the four double rotation
  137. // cases
  138. //
  139. GrandParent = TriParent(Parent);
  140. if (TriIsLeftChild(Links)) {
  141. if (TriIsLeftChild(Parent)) {
  142. //
  143. // do the following double rotation
  144. //
  145. // GP L
  146. // / \
  147. // P ==> P
  148. // / \
  149. // L GP
  150. //
  151. TriRotateRight(GrandParent);
  152. TriRotateRight(Parent);
  153. } else { // TriIsRightChild(Parent)
  154. //
  155. // do the following double rotation
  156. //
  157. // GP L
  158. // \ / \
  159. // P ==> GP P
  160. // /
  161. // L
  162. //
  163. TriRotateRight(Parent);
  164. TriRotateLeft(GrandParent);
  165. }
  166. } else { // TriIsRightChild(Links);
  167. if (TriIsLeftChild(Parent)) {
  168. //
  169. // do the following double rotation
  170. //
  171. // GP L
  172. // / / \
  173. // P ==> P GP
  174. // \
  175. // L
  176. //
  177. TriRotateLeft(Parent);
  178. TriRotateRight(GrandParent);
  179. } else { // TriIsRightChild(Parent)
  180. //
  181. // do the following double rotation
  182. //
  183. // GP L
  184. // \ /
  185. // P ==> P
  186. // \ /
  187. // L GP
  188. //
  189. TriRotateLeft(GrandParent);
  190. TriRotateLeft(Parent);
  191. }
  192. }
  193. }
  194. }
  195. return Links;
  196. }
  197. PTRI_SPLAY_LINKS
  198. TriDelete (
  199. IN PTRI_SPLAY_LINKS Links
  200. )
  201. /*++
  202. Routine Description:
  203. This Delete function takes as input a pointer to a splay link in a tree
  204. and deletes that node from the tree. Its function return value is a
  205. pointer to the root the tree. If the tree is now empty, the return
  206. value is NULL.
  207. Arguments:
  208. Links - Supplies the pointer to a splay link in a tree
  209. Return Values:
  210. PRTI_SPLAY_LINKS - Returns a pointer to the root of the splayed tree
  211. --*/
  212. {
  213. PTRI_SPLAY_LINKS Predecessor;
  214. PTRI_SPLAY_LINKS Parent;
  215. PTRI_SPLAY_LINKS Child;
  216. PULONG ParentChildRef;
  217. //
  218. // First check to see if Links as two children. If it does then swap
  219. // Links with its subtree predecessor. Now we are guaranteed that Links
  220. // has at most one child.
  221. //
  222. if ((TriLeftChild(Links) != NULL) && (TriRightChild(Links) != NULL)) {
  223. //
  224. // get the predecessor, and swap their position in the tree
  225. //
  226. Predecessor = TriSubtreePredecessor(Links);
  227. TriSwapSplayLinks(Predecessor, Links);
  228. }
  229. //
  230. // If Links has no children then delete links by checking if it is
  231. // already the root or has a parent. If it is the root then the
  232. // tree is now empty, otherwise set the appropriate parent's child
  233. // pointer, and possibly sibling, and splay the parent.
  234. //
  235. if ((TriLeftChild(Links) == NULL) && (TriRightChild(Links) == NULL)) {
  236. //
  237. // Links has no children, if it is the root then return NULL
  238. //
  239. if (TriIsRoot(Links)) {
  240. return NULL;
  241. }
  242. //
  243. // Links has no children, check to see if links is an only child
  244. //
  245. Parent = TriParent(Links);
  246. if (MakeIntoPointer(Parent->Refs.Child) == Links &&
  247. MakeIntoPointer(Links->Refs.ParSib) == Parent) {
  248. //
  249. // Links has no children and is an only child. So simply make
  250. // our parent have no children and splay our parent.
  251. //
  252. // Parent Parent
  253. // | ==>
  254. // Links
  255. //
  256. Parent->Refs.Child = 0;
  257. return TriSplay(Parent);
  258. } else if (TriIsLeftChild(Links)) {
  259. //
  260. // Links has no children and has a right sibling. So make the
  261. // parent's child Ref be the right sibling, splay the parent.
  262. //
  263. // Parent Parent
  264. // / \ ==> \
  265. // Links Sibling Sibling
  266. //
  267. Parent->Refs.Child = MakeIntoRightChildRef(Links->Refs.ParSib);
  268. return TriSplay(Parent);
  269. } else { // TriIsRightChild(Links)
  270. //
  271. // Links has no children and has a left sibling. So make link's
  272. // back via its parent into a parent ref of link's parent, and
  273. // splay the parent.
  274. //
  275. // Parent Parent
  276. // / \ /
  277. // Sibling Links ==> Sibling
  278. //
  279. ParentChildRef = TriAddressOfBackRefViaParent(Links);
  280. *ParentChildRef = MakeIntoParentRef(Parent);
  281. return TriSplay(Parent);
  282. }
  283. }
  284. //
  285. // otherwise Links has one child. If it is the root then make the child
  286. // the new root, otherwise link together the child and parent, and splay
  287. // the parent. But first remember who our child is.
  288. //
  289. if (TriLeftChild(Links) != NULL) {
  290. Child = TriLeftChild(Links);
  291. } else {
  292. Child = TriRightChild(Links);
  293. }
  294. //
  295. // If links is the root then we make the child the root and return the
  296. // child.
  297. //
  298. if (TriIsRoot(Links)) {
  299. Child->Refs.ParSib = MakeIntoParentRef(Child);
  300. return Child;
  301. }
  302. //
  303. // Links is not the root, so set links's back ref via its parent to be
  304. // links's child and the set the child's ParSib to be link's ParSib, and
  305. // splay the parent. This will handle the case where link is an only
  306. // or has a sibling on either side.
  307. //
  308. Parent = TriParent(Links);
  309. ParentChildRef = TriAddressOfBackRefViaParent(Links);
  310. SetRefViaPointer(ParentChildRef, Child);
  311. Child->Refs.ParSib = Links->Refs.ParSib;
  312. return TriSplay(Parent);
  313. }
  314. PTRI_SPLAY_LINKS
  315. TriSubtreeSuccessor (
  316. IN PTRI_SPLAY_LINKS Links
  317. )
  318. /*++
  319. Routine Description:
  320. This SubTreeSuccessor function takes as input a pointer to a splay link
  321. in a tree and returns a pointer to the successor of the input node of
  322. the subtree rooted at the input node. If there is not a successor, the
  323. return value is NULL.
  324. Arguments:
  325. Links - Supplies the pointer to a splay link in a tree
  326. Return Values:
  327. PRTI_SPLAY_LINKS - Returns a pointer to the successor in the subtree
  328. --*/
  329. {
  330. PTRI_SPLAY_LINKS Ptr;
  331. //
  332. // check to see if there is a right subtree to the input link
  333. // if there is then the subtree successor is the left most node in
  334. // the right subtree. That is find and return P in the following diagram
  335. //
  336. // Links
  337. // \
  338. // .
  339. // .
  340. // .
  341. // /
  342. // P
  343. // \
  344. //
  345. if ((Ptr = TriRightChild(Links)) != NULL) {
  346. while (TriLeftChild(Ptr) != NULL) {
  347. Ptr = TriLeftChild(Ptr);
  348. }
  349. return Ptr;
  350. }
  351. //
  352. // Otherwise we do not have a subtree successor so we simply return NULL
  353. //
  354. return NULL;
  355. }
  356. PTRI_SPLAY_LINKS
  357. TriSubtreePredecessor (
  358. IN PTRI_SPLAY_LINKS Links
  359. )
  360. /*++
  361. Routine Description:
  362. This SubTreePredecessor function takes as input a pointer to a splay link
  363. in a tree and returns a pointer to the predecessor of the input node of
  364. the subtree rooted at the input node. If there is not a predecessor,
  365. the return value is NULL.
  366. Arguments:
  367. Links - Supplies the pointer to a splay link in a tree
  368. Return Values:
  369. PRTI_SPLAY_LINKS - Returns a pointer to the predecessor in the subtree
  370. --*/
  371. {
  372. PTRI_SPLAY_LINKS Ptr;
  373. //
  374. // check to see if there is a left subtree to the input link
  375. // if there is then the subtree predecessor is the right most node in
  376. // the left subtree. That is find and return P in the following diagram
  377. //
  378. // Links
  379. // /
  380. // .
  381. // .
  382. // .
  383. // P
  384. // /
  385. //
  386. if ((Ptr = TriLeftChild(Links)) != NULL) {
  387. while (TriRightChild(Ptr) != NULL) {
  388. Ptr = TriRightChild(Ptr);
  389. }
  390. return Ptr;
  391. }
  392. //
  393. // Otherwise we do not have a subtree predecessor so we simply return NULL
  394. //
  395. return NULL;
  396. }
  397. PTRI_SPLAY_LINKS
  398. TriRealSuccessor (
  399. IN PTRI_SPLAY_LINKS Links
  400. )
  401. /*++
  402. Routine Description:
  403. This RealSuccess function takes as input a pointer to a splay link in a
  404. tree and returns a pointer to the successor of the input node within the
  405. entire tire. If there is not a successor, the return value is NULL.
  406. Arguments:
  407. Links - Supplies the pointer to a splay link in a tree
  408. Return Values:
  409. PRTI_SPLAY_LINKS - Returns a pointer to the successor in the entire tree
  410. --*/
  411. {
  412. PTRI_SPLAY_LINKS Ptr;
  413. //
  414. // first check to see if there is a right subtree to the input link
  415. // if there is then the real successor is the left most node in
  416. // the right subtree. That is find and return P in the following diagram
  417. //
  418. // Links
  419. // \
  420. // .
  421. // .
  422. // .
  423. // /
  424. // P
  425. // \
  426. //
  427. if ((Ptr = TriRightChild(Links)) != NULL) {
  428. while (TriLeftChild(Ptr) != NULL) {
  429. Ptr = TriLeftChild(Ptr);
  430. }
  431. return Ptr;
  432. }
  433. //
  434. // we do not have a right child so check to see if have a parent and if
  435. // so find the first ancestor that we are a left decendent of. That
  436. // is find and return P in the following diagram
  437. //
  438. // P
  439. // /
  440. // .
  441. // .
  442. // .
  443. // Links
  444. //
  445. Ptr = Links;
  446. while (!TriIsLeftChild(Ptr) && !TriIsRoot(Ptr)) { // (TriIsRightChild(Ptr)) {
  447. Ptr = TriParent(Ptr);
  448. }
  449. if (TriIsLeftChild(Ptr)) {
  450. return TriParent(Ptr);
  451. }
  452. //
  453. // Otherwise we do not have a real successor so we simply return NULL
  454. //
  455. return NULL;
  456. }
  457. PTRI_SPLAY_LINKS
  458. TriRealPredecessor (
  459. IN PTRI_SPLAY_LINKS Links
  460. )
  461. /*++
  462. Routine Description:
  463. This RealPredecessor function takes as input a pointer to a splay link in
  464. a tree and returns a pointer to the predecessor of the input node within
  465. the entire tree. If there is not a predecessor, the return value is NULL.
  466. Arguments:
  467. Links - Supplies the pointer to a splay link in a tree
  468. Return Values:
  469. PRTI_SPLAY_LINKS - Returns a pointer to the predecessor in the entire tree
  470. --*/
  471. {
  472. PTRI_SPLAY_LINKS Ptr;
  473. //
  474. // first check to see if there is a left subtree to the input link
  475. // if there is then the real predecessor is the right most node in
  476. // the left subtree. That is find and return P in the following diagram
  477. //
  478. // Links
  479. // /
  480. // .
  481. // .
  482. // .
  483. // P
  484. // /
  485. //
  486. if ((Ptr = TriLeftChild(Links)) != NULL) {
  487. while (TriRightChild(Ptr) != NULL) {
  488. Ptr = TriRightChild(Ptr);
  489. }
  490. return Ptr;
  491. }
  492. //
  493. // we do not have a left child so check to see if have a parent and if
  494. // so find the first ancestor that we are a right decendent of. That
  495. // is find and return P in the following diagram
  496. //
  497. // P
  498. // \
  499. // .
  500. // .
  501. // .
  502. // Links
  503. //
  504. Ptr = Links;
  505. while (TriIsLeftChild(Ptr)) {
  506. Ptr = TriParent(Ptr);
  507. }
  508. if (!TriIsLeftChild(Ptr) && !TriIsRoot(Ptr)) { // (TriIsRightChild(Ptr)) {
  509. return TriParent(Ptr);
  510. }
  511. //
  512. // Otherwise we do not have a real predecessor so we simply return NULL
  513. //
  514. return NULL;
  515. }
  516. PULONG
  517. TriAddressOfBackRefViaParent (
  518. IN PTRI_SPLAY_LINKS Links
  519. )
  520. {
  521. PTRI_SPLAY_LINKS Ptr;
  522. //
  523. // If Links is the root then we do not have a back pointer via our parent
  524. // so return NULL
  525. //
  526. if (TriIsRoot(Links)) {
  527. return NULL;
  528. }
  529. //
  530. // We are not the root so find our parent and if our parent directly points
  531. // to us we return the address of our parent's reference to us. Otherwise
  532. // (we must be a right child with a sibling) so return the address of
  533. // our sibling's ParSib reference to us.
  534. //
  535. Ptr = TriParent(Links);
  536. if (MakeIntoPointer(Ptr->Refs.Child) == Links) {
  537. return &(Ptr->Refs.Child);
  538. } else {
  539. return &(MakeIntoPointer(Ptr->Refs.Child)->Refs.ParSib);
  540. }
  541. }
  542. PULONG
  543. TriAddressOfBackRefViaChild (
  544. IN PTRI_SPLAY_LINKS Links
  545. )
  546. {
  547. PTRI_SPLAY_LINKS Ptr;
  548. //
  549. // Make Ptr be the same reference as found in our child field.
  550. //
  551. Ptr = MakeIntoPointer(Links->Refs.Child);
  552. //
  553. // If our child pointer is null then we don't have a back pointer
  554. // via our child so return NULL.
  555. //
  556. if (Ptr == NULL) {
  557. return NULL;
  558. //
  559. // if our child directly reference's us (then we only have one child)
  560. // return the address of the ParSib of our only child.
  561. //
  562. } else if (MakeIntoPointer(Ptr->Refs.ParSib) == Links) {
  563. return &(Ptr->Refs.ParSib);
  564. //
  565. // otherwise we have two children so return the address of the ParSib
  566. // of the second child.
  567. //
  568. } else {
  569. return &(MakeIntoPointer(Ptr->Refs.ParSib)->Refs.ParSib);
  570. }
  571. }
  572. VOID
  573. TriSwapSplayLinks (
  574. IN PTRI_SPLAY_LINKS Link1,
  575. IN PTRI_SPLAY_LINKS Link2
  576. )
  577. {
  578. PULONG Parent1ChildRef;
  579. PULONG Parent2ChildRef;
  580. PULONG Child1ParSibRef;
  581. PULONG Child2ParSibRef;
  582. //
  583. // We have the following situation
  584. //
  585. //
  586. // Parent1 Parent2
  587. // | |
  588. // | |
  589. // Link1 Link2
  590. // / \ / \
  591. // / \ / \
  592. // LC1 RC1 LC2 RC2
  593. //
  594. // where one of the links can possibly be the root and one of the links
  595. // can possibly be a direct child of the other, or can be connected
  596. // via their sibling pointers. Without loss of generality we'll make
  597. // link2 be the possible and root and link1 be the possible child, or
  598. // link2 have a parsib pointer to link1
  599. //
  600. if ((TriIsRoot(Link1)) ||
  601. (TriParent(Link2) == Link1) ||
  602. (MakeIntoPointer(Link1->Refs.ParSib) == Link2)) {
  603. SwapPointers(Link1, Link2);
  604. }
  605. //
  606. // The cases we need to handle are
  607. //
  608. // 1. Link1 is not a child of link2, link2 is not the root, and they are not siblings
  609. // 2. Link1 is not a child of link2, link2 is not the root, and they are siblings
  610. //
  611. // 3. Link1 is not a child of link2, link2 is the root
  612. //
  613. // 4. Link1 is an only child of link2, and link2 is not the root
  614. // 5. Link1 is an only child of link2, and link2 is the root
  615. //
  616. // 6. Link1 is a left child of link2 (has a sibling), and link2 is not the root
  617. // 7. Link1 is a left child of link2 (has a sibling), and link2 is the root
  618. //
  619. // 8. Link1 is a right child of link2 (has a sibling), and link2 is not the root
  620. // 9. Link1 is a right child of link2 (has a sibling), and link2 is the root
  621. //
  622. // Each case will be handled separately
  623. //
  624. if (TriParent(Link1) != Link2) {
  625. if (!TriIsRoot(Link2)) {
  626. if (MakeIntoPointer(Link2->Refs.ParSib) != Link1) {
  627. //
  628. // Case 1 - Link1 is not a child of link2,
  629. // Link2 is not the root, and
  630. // they are not siblings
  631. //
  632. Parent1ChildRef = TriAddressOfBackRefViaParent(Link1);
  633. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  634. Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
  635. Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
  636. SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
  637. SwapUlongs(Link1->Refs.ParSib, Link2->Refs.ParSib);
  638. SetRefViaPointer(Parent1ChildRef, Link2);
  639. SetRefViaPointer(Parent2ChildRef, Link1);
  640. SetRefViaPointer(Child1ParSibRef, Link2);
  641. SetRefViaPointer(Child2ParSibRef, Link1);
  642. } else {
  643. //
  644. // Case 2 - Link1 is not a child of link2,
  645. // Link2 is not the root, and
  646. // they are siblings
  647. //
  648. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  649. Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
  650. Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
  651. SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
  652. SetRefViaPointer(Child1ParSibRef, Link2);
  653. SetRefViaPointer(Child2ParSibRef, Link1);
  654. *Parent2ChildRef = MakeIntoLeftChildRef(Link1);
  655. Link2->Refs.ParSib = Link1->Refs.ParSib;
  656. Link1->Refs.ParSib = MakeIntoSiblingRef(Link2);
  657. }
  658. } else {
  659. //
  660. // Case 3 - Link1 is not a child of link2, and
  661. // Link2 is the root
  662. //
  663. Parent1ChildRef = TriAddressOfBackRefViaParent(Link1);
  664. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  665. Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
  666. SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
  667. Link2->Refs.ParSib = Link1->Refs.ParSib;
  668. Link1->Refs.ParSib = MakeIntoParentRef(Link1);
  669. SetRefViaPointer(Child1ParSibRef, Link2);
  670. SetRefViaPointer(Child2ParSibRef, Link1);
  671. SetRefViaPointer(Parent1ChildRef, Link2);
  672. }
  673. } else { // TriParent(Link1) == Link2
  674. if (MakeIntoPointer(Link2->Refs.Child) == Link1 &&
  675. MakeIntoPointer(Link1->Refs.ParSib) == Link2) { // Link1 is an only child
  676. if (!TriIsRoot(Link2)) {
  677. //
  678. // Case 4 - Link1 is an only child of link2, and
  679. // Link2 is not the root
  680. //
  681. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  682. Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
  683. SetRefViaPointer(Child1ParSibRef, Link2);
  684. SetRefViaPointer(Parent2ChildRef, Link1);
  685. Link1->Refs.ParSib = Link2->Refs.ParSib;
  686. Link2->Refs.ParSib = MakeIntoParentRef(Link1);
  687. SwapRefsButKeepFlags(Link1->Refs.Child, Link2->Refs.Child);
  688. SetRefViaPointer(&Link1->Refs.Child, Link2);
  689. } else {
  690. //
  691. // Case 5 - Link1 is an only child of link2, and
  692. // Link2 is the root
  693. //
  694. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  695. SetRefViaPointer(Child1ParSibRef, Link2);
  696. Link1->Refs.ParSib = MakeIntoParentRef(Link1);
  697. Link2->Refs.ParSib = MakeIntoParentRef(Link1);
  698. SwapRefsButKeepFlags(Link1->Refs.Child, Link2->Refs.Child);
  699. SetRefViaPointer(&Link1->Refs.Child, Link2);
  700. }
  701. } else if (TriIsLeftChild(Link1)) { // and link1 has a sibling
  702. if (!TriIsRoot(Link2)) {
  703. //
  704. // Case 6 - Link1 is a left child of link2 (has a sibling), and
  705. // Link2 is not the root
  706. //
  707. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  708. Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
  709. Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
  710. SetRefViaPointer(Child1ParSibRef, Link2);
  711. SetRefViaPointer(Parent2ChildRef, Link1);
  712. SetRefViaPointer(Child2ParSibRef, Link1);
  713. Link2->Refs.Child = Link1->Refs.Child;
  714. Link1->Refs.Child = MakeIntoLeftChildRef(Link2);
  715. SwapUlongs(Link1->Refs.ParSib, Link2->Refs.ParSib);
  716. } else {
  717. //
  718. // Case 7 - Link1 is a left child of link2 (has a sibling), and
  719. // Link2 is the root
  720. //
  721. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  722. Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
  723. SetRefViaPointer(Child1ParSibRef, Link2);
  724. SetRefViaPointer(Child2ParSibRef, Link1);
  725. Link2->Refs.Child = Link1->Refs.Child;
  726. Link1->Refs.Child = MakeIntoLeftChildRef(Link2);
  727. Link2->Refs.ParSib = Link1->Refs.ParSib;
  728. Link1->Refs.ParSib = MakeIntoParentRef(Link1);
  729. }
  730. } else { // TriIsRightChild(Link1) and Link1 has a sibling
  731. if (!TriIsRoot(Link2)) {
  732. //
  733. // Case 8 - Link1 is a right child of link2 (has a sibling), and
  734. // Link2 is not the root
  735. //
  736. Parent1ChildRef = TriAddressOfBackRefViaParent(Link1);
  737. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  738. Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
  739. SetRefViaPointer(Parent1ChildRef, Link2);
  740. SetRefViaPointer(Child1ParSibRef, Link2);
  741. SetRefViaPointer(Parent2ChildRef, Link1);
  742. SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
  743. Link1->Refs.ParSib = Link2->Refs.ParSib;
  744. Link2->Refs.ParSib = MakeIntoParentRef(Link1);
  745. } else {
  746. //
  747. // Case 9 - Link1 is a right child of link2 (has a sibling), and
  748. // Link2 is the root
  749. //
  750. Parent1ChildRef = TriAddressOfBackRefViaParent(Link1);
  751. Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
  752. SetRefViaPointer(Parent1ChildRef, Link2);
  753. SetRefViaPointer(Child1ParSibRef, Link2);
  754. SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
  755. Link1->Refs.ParSib = MakeIntoParentRef(Link1);
  756. Link1->Refs.ParSib = MakeIntoParentRef(Link1);
  757. }
  758. }
  759. }
  760. }
  761. VOID
  762. TriRotateRight (
  763. IN PTRI_SPLAY_LINKS Links
  764. )
  765. {
  766. BOOLEAN IsRoot;
  767. PULONG ParentChildRef;
  768. ULONG SavedParSibRef;
  769. PTRI_SPLAY_LINKS LeftChild;
  770. PTRI_SPLAY_LINKS a,b,c;
  771. //
  772. // We perform the following rotation
  773. //
  774. // -Links- -LeftChild-
  775. // / \ / \
  776. // LeftChild c ==> a Links
  777. // / \ / \
  778. // a b b c
  779. //
  780. // where Links is a possible root and a,b, and c are all optional.
  781. // We will consider each combination of optional children individually
  782. // and handle the case of the root when we set T's parsib pointer and
  783. // the backpointer to T.
  784. //
  785. //
  786. // First remember if we are the root and if not also remember our
  787. // back ref via our parent.
  788. //
  789. if (TriIsRoot(Links)) {
  790. IsRoot = TRUE;
  791. } else {
  792. IsRoot = FALSE;
  793. ParentChildRef = TriAddressOfBackRefViaParent(Links);
  794. SavedParSibRef = Links->Refs.ParSib;
  795. }
  796. //
  797. // Now we set LeftChild, a, b, and c, and then later check for the
  798. // different combinations. In the diagrams only those links that
  799. // need to change are shown in the after part.
  800. //
  801. LeftChild = TriLeftChild(Links);
  802. a = TriLeftChild(LeftChild);
  803. b = TriRightChild(LeftChild);
  804. c = TriRightChild(Links);
  805. if ((a != NULL) && (b != NULL) && (c != NULL)) {
  806. //
  807. // Handle the following case
  808. //
  809. // Links LeftChild
  810. // / \ ==> \
  811. // LeftChild c a ----- Links
  812. // / \ /
  813. // a b b - c
  814. //
  815. a->Refs.ParSib = MakeIntoSiblingRef(Links);
  816. b->Refs.ParSib = MakeIntoSiblingRef(c);
  817. Links->Refs.Child = MakeIntoLeftChildRef(b);
  818. Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
  819. } else if ((a != NULL) && (b != NULL) && (c == NULL)) {
  820. //
  821. // Handle the following case
  822. //
  823. // Links LeftChild
  824. // / ==> \
  825. // LeftChild a ----- Links
  826. // / \ /
  827. // a b b --
  828. //
  829. a->Refs.ParSib = MakeIntoSiblingRef(Links);
  830. b->Refs.ParSib = MakeIntoParentRef(Links);
  831. Links->Refs.Child = MakeIntoLeftChildRef(b);
  832. Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
  833. } else if ((a != NULL) && (b == NULL) && (c != NULL)) {
  834. //
  835. // Handle the following case
  836. //
  837. // Links LeftChild
  838. // / \ ==> \
  839. // LeftChild c a ----- Links
  840. // / /
  841. // a c
  842. //
  843. a->Refs.ParSib = MakeIntoSiblingRef(Links);
  844. Links->Refs.Child = MakeIntoRightChildRef(c);
  845. Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
  846. } else if ((a != NULL) && (b == NULL) && (c == NULL)) {
  847. //
  848. // Handle the following case
  849. //
  850. // Links LeftChild
  851. // / ==> \
  852. // LeftChild a ----- Links
  853. // / /
  854. // a
  855. //
  856. a->Refs.ParSib = MakeIntoSiblingRef(Links);
  857. Links->Refs.Child = 0L;
  858. Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
  859. } else if ((a == NULL) && (b != NULL) && (c != NULL)) {
  860. //
  861. // Handle the following case
  862. //
  863. // Links LeftChild
  864. // / \ ==> / \
  865. // LeftChild c Links
  866. // \ /
  867. // b b - c
  868. //
  869. b->Refs.ParSib = MakeIntoSiblingRef(c);
  870. Links->Refs.Child = MakeIntoLeftChildRef(b);
  871. Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
  872. LeftChild->Refs.Child = MakeIntoRightChildRef(Links);
  873. } else if ((a == NULL) && (b != NULL) && (c == NULL)) {
  874. //
  875. // Handle the following case
  876. //
  877. // Links LeftChild
  878. // / ==> / \
  879. // LeftChild Links
  880. // \ /
  881. // b b -
  882. //
  883. b->Refs.ParSib = MakeIntoParentRef(Links);
  884. Links->Refs.Child = MakeIntoLeftChildRef(b);
  885. Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
  886. LeftChild->Refs.Child = MakeIntoRightChildRef(Links);
  887. } else if ((a == NULL) && (b == NULL) && (c != NULL)) {
  888. //
  889. // Handle the following case
  890. //
  891. // Links LeftChild
  892. // / \ ==> / \
  893. // LeftChild c Links
  894. // /
  895. // c
  896. //
  897. Links->Refs.Child = MakeIntoRightChildRef(c);
  898. Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
  899. LeftChild->Refs.Child = MakeIntoRightChildRef(Links);
  900. } else if ((a == NULL) && (b == NULL) && (c == NULL)) {
  901. //
  902. // Handle the following case
  903. //
  904. // Links LeftChild
  905. // / ==> / \
  906. // LeftChild Links
  907. // /
  908. //
  909. Links->Refs.Child = 0L;
  910. Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
  911. LeftChild->Refs.Child = MakeIntoRightChildRef(Links);
  912. }
  913. if (IsRoot) {
  914. LeftChild->Refs.ParSib = MakeIntoParentRef(LeftChild);
  915. } else {
  916. LeftChild->Refs.ParSib = SavedParSibRef;
  917. SetRefViaPointer(ParentChildRef, LeftChild);
  918. }
  919. }
  920. VOID
  921. TriRotateLeft (
  922. IN PTRI_SPLAY_LINKS Links
  923. )
  924. {
  925. BOOLEAN IsRoot;
  926. PULONG ParentChildRef;
  927. ULONG SavedParSibRef;
  928. PTRI_SPLAY_LINKS RightChild;
  929. PTRI_SPLAY_LINKS a,b,c;
  930. //
  931. // We perform the following rotation
  932. //
  933. // -Links- -RightChild-
  934. // / \ / \
  935. // a RightChild ==> Links c
  936. // / \ / \
  937. // b c a b
  938. //
  939. // where Links is a possible root and a,b, and c are all optional.
  940. // We will consider each combination of optional children individually
  941. // and handle the case of the root when we set T's parsib pointer and
  942. // the backpointer to T.
  943. //
  944. //
  945. // First remember if we are the root and if not also remember our
  946. // back ref via our parent.
  947. //
  948. if (TriIsRoot(Links)) {
  949. IsRoot = TRUE;
  950. } else {
  951. IsRoot = FALSE;
  952. ParentChildRef = TriAddressOfBackRefViaParent(Links);
  953. SavedParSibRef = Links->Refs.ParSib;
  954. }
  955. //
  956. // Now we set RightChild, a, b, and c, and then later check for the
  957. // different combinations. In the diagrams only those links that
  958. // need to change are shown in the after part.
  959. //
  960. RightChild = TriRightChild(Links);
  961. a = TriLeftChild(Links);
  962. b = TriLeftChild(RightChild);
  963. c = TriRightChild(RightChild);
  964. if ((a != NULL) && (b != NULL) && (c != NULL)) {
  965. //
  966. // Handle the following case
  967. //
  968. // Links RightChild
  969. // / \ /
  970. // a RightChild ==> Links ----- c
  971. // / \ \
  972. // b c a - b
  973. //
  974. a->Refs.ParSib = MakeIntoSiblingRef(b);
  975. b->Refs.ParSib = MakeIntoParentRef(Links);
  976. Links->Refs.ParSib = MakeIntoSiblingRef(c);
  977. RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
  978. } else if ((a != NULL) && (b != NULL) && (c == NULL)) {
  979. //
  980. // Handle the following case
  981. //
  982. // Links RightChild
  983. // / \ /
  984. // a RightChild ==> Links -----
  985. // / \
  986. // b a - b
  987. //
  988. a->Refs.ParSib = MakeIntoSiblingRef(b);
  989. b->Refs.ParSib = MakeIntoParentRef(Links);
  990. Links->Refs.ParSib = MakeIntoParentRef(RightChild);
  991. RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
  992. } else if ((a != NULL) && (b == NULL) && (c != NULL)) {
  993. //
  994. // Handle the following case
  995. //
  996. // Links RightChild
  997. // / \ /
  998. // a RightChild ==> Links ----- c
  999. // \
  1000. // c a -
  1001. //
  1002. a->Refs.ParSib = MakeIntoParentRef(Links);
  1003. Links->Refs.ParSib = MakeIntoSiblingRef(c);
  1004. RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
  1005. } else if ((a != NULL) && (b == NULL) && (c == NULL)) {
  1006. //
  1007. // Handle the following case
  1008. //
  1009. // Links RightChild
  1010. // / \ /
  1011. // a RightChild ==> Links -----
  1012. //
  1013. // a -
  1014. //
  1015. a->Refs.ParSib = MakeIntoParentRef(Links);
  1016. Links->Refs.ParSib = MakeIntoParentRef(RightChild);
  1017. RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
  1018. } else if ((a == NULL) && (b != NULL) && (c != NULL)) {
  1019. //
  1020. // Handle the following case
  1021. //
  1022. // Links RightChild
  1023. // \ /
  1024. // RightChild ==> Links ----- c
  1025. // / \ / \
  1026. // b c b
  1027. //
  1028. b->Refs.ParSib = MakeIntoParentRef(Links);
  1029. Links->Refs.Child = MakeIntoRightChildRef(b);
  1030. Links->Refs.ParSib = MakeIntoSiblingRef(c);
  1031. RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
  1032. } else if ((a == NULL) && (b != NULL) && (c == NULL)) {
  1033. //
  1034. // Handle the following case
  1035. //
  1036. // Links RightChild
  1037. // \ /
  1038. // RightChild ==> Links -----
  1039. // / / \
  1040. // b b
  1041. //
  1042. b->Refs.ParSib = MakeIntoParentRef(Links);
  1043. Links->Refs.Child = MakeIntoRightChildRef(b);
  1044. Links->Refs.ParSib = MakeIntoParentRef(RightChild);
  1045. RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
  1046. } else if ((a == NULL) && (b == NULL) && (c != NULL)) {
  1047. //
  1048. // Handle the following case
  1049. //
  1050. // Links RightChild
  1051. // \ /
  1052. // RightChild ==> Links ----- c
  1053. // \ /
  1054. // c
  1055. //
  1056. Links->Refs.Child = 0L;
  1057. Links->Refs.ParSib = MakeIntoSiblingRef(c);
  1058. RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
  1059. } else if ((a == NULL) && (b == NULL) && (c == NULL)) {
  1060. //
  1061. // Handle the following case
  1062. //
  1063. // Links RightChild
  1064. // \ /
  1065. // RightChild ==> Links -----
  1066. // /
  1067. //
  1068. //
  1069. Links->Refs.Child = 0L;
  1070. Links->Refs.ParSib = MakeIntoParentRef(RightChild);
  1071. RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
  1072. }
  1073. if (IsRoot) {
  1074. RightChild->Refs.ParSib = MakeIntoParentRef(RightChild);
  1075. } else {
  1076. RightChild->Refs.ParSib = SavedParSibRef;
  1077. SetRefViaPointer(ParentChildRef, RightChild);
  1078. }
  1079. }