home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / directx2 / sdk / samples / cgutil / linklist.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-28  |  10.8 KB  |  384 lines

  1. /*===========================================================================*\
  2. |
  3. |  File:        linklist.cpp
  4. |
  5. |  Description: 
  6. |   Class to maintain a doubly linked list.
  7. |       
  8. |-----------------------------------------------------------------------------
  9. |
  10. |  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
  11. |
  12. |  Written by Moss Bay Engineering, Inc. under contract to Microsoft Corporation
  13. |
  14. \*===========================================================================*/
  15. #include "linklist.h"
  16.  
  17. #define NULL    0L
  18.  
  19. // -----------------------------------------------------------------
  20. //  CLinkedList constructor - initialize to empty
  21. // -----------------------------------------------------------------
  22. CLinkedList::CLinkedList()
  23. {
  24.     pHead = pTail = pCurPosition = NULL;
  25. }
  26.  
  27. // -----------------------------------------------------------------
  28. //  CLinkedList destructor - free each node
  29. //  Note: we do not free the app data pointed to by each node.
  30. // -----------------------------------------------------------------
  31. CLinkedList::~CLinkedList()
  32. {
  33.     LPNODE  pCur, pNext;
  34.  
  35.     pCur = pHead;
  36.     pHead = pTail = pCurPosition = NULL;
  37.  
  38.     // Go thru list and free each node
  39.     while (pCur != NULL)
  40.     {
  41.         pNext = pCur->pNext;
  42.         delete(pCur);
  43.         pCur = pNext;
  44.     }
  45. }   
  46.  
  47. // -----------------------------------------------------------------
  48. //  GetFirst - return app data for first entry in list and make it
  49. //  the current node.
  50. // -----------------------------------------------------------------
  51. void  * CLinkedList::GetFirst()
  52. {
  53.     pCurPosition = pHead;
  54.     if (pCurPosition == NULL)
  55.     {
  56.         return(NULL);
  57.     }
  58.  
  59.     return(pCurPosition->pData);
  60. }
  61.  
  62. // -----------------------------------------------------------------
  63. //  GetLast - return app data to last entry in list and make it
  64. //  the current node.
  65. // -----------------------------------------------------------------
  66. void  * CLinkedList::GetLast()
  67. {
  68.     pCurPosition = pTail;
  69.     if (pCurPosition == NULL)
  70.     {
  71.         return(NULL);
  72.     }
  73.  
  74.     return(pCurPosition->pData);
  75. }
  76.  
  77. // -----------------------------------------------------------------
  78. //  GetNext - return next app data entry in list and make it
  79. //  the current node.
  80. // -----------------------------------------------------------------
  81. void  * CLinkedList::GetNext()
  82. {
  83.     LPNODE  pNext;
  84.  
  85.     // check for empty list or already at end of list.
  86.     if ((pCurPosition == NULL) || (pCurPosition->pNext == NULL))
  87.     {
  88.         return(NULL);
  89.     }
  90.  
  91.     pNext = pCurPosition->pNext;
  92.     pCurPosition = pNext;
  93.     return(pNext->pData);
  94. }
  95.  
  96. // -----------------------------------------------------------------
  97. //  GetFirst - return app data that follows a given entry and make it
  98. //  the current node.
  99. // -----------------------------------------------------------------
  100. void  * CLinkedList::GetNext(void  *pData)
  101. {
  102.     pCurPosition = Find(pData);
  103.     return(GetNext());
  104. }
  105.  
  106. // -----------------------------------------------------------------
  107. //  GetPrev - return app data for previous entry in list and make it
  108. //  the current node.
  109. // -----------------------------------------------------------------
  110. void  * CLinkedList::GetPrev()
  111. {
  112.     LPNODE  pPrev;
  113.  
  114.     // check for empty list or already at start
  115.     if ((pCurPosition == NULL) || (pCurPosition->pPrev == NULL))
  116.     {
  117.         return(NULL);
  118.     }
  119.  
  120.     pPrev = pCurPosition->pPrev;
  121.     pCurPosition = pPrev;
  122.     return(pPrev->pData);
  123.     
  124. }
  125. // -----------------------------------------------------------------
  126. //  GetFirst - return app data that preceeds a given entry and make it
  127. //  the current node.
  128. // -----------------------------------------------------------------
  129. void  * CLinkedList::GetPrev(void  *pData)
  130. {
  131.     pCurPosition = Find(pData);
  132.     return(GetPrev());
  133. }
  134.  
  135. // -----------------------------------------------------------------
  136. //  Add - create a new node and put it at the start of the list and
  137. //  make it the current node.
  138. // -----------------------------------------------------------------
  139. void CLinkedList::Add(void  *pData)
  140. {
  141.     LPNODE  pNew = new NODE;
  142.  
  143.     // setup node and prepare it for its role as the new head of the list
  144.     pNew->pData = pData;
  145.     pNew->pNext = pHead;
  146.     pNew->pPrev = NULL;
  147.  
  148.     // The old head of list (if any) should point to new node)
  149.     if (pHead != NULL)
  150.         pHead->pPrev = pNew;
  151.  
  152.     // Make new node the head and current position
  153.     pHead = pNew;
  154.     pCurPosition = pNew;
  155.  
  156.     // Check to see if new node is also the tail (ie. only list entry)
  157.     if (pTail == NULL)
  158.         pTail = pNew;
  159. }
  160.  
  161. // -----------------------------------------------------------------
  162. //  Append - create a new node and put it at the end of the list.
  163. // -----------------------------------------------------------------
  164. void CLinkedList::Append(void  *pData)
  165. {
  166.     LPNODE  pNew = new NODE;
  167.  
  168.     // setup node and prepare it for its role as the new tail of the list
  169.     pNew->pData = pData;
  170.     pNew->pPrev = pTail;
  171.     pNew->pNext = NULL;
  172.  
  173.     // The old tail of list (if any) should point to new node.
  174.     if (pTail != NULL)
  175.         pTail->pNext = pNew;
  176.  
  177.     // Make new node the tail
  178.     pTail = pNew;
  179.  
  180.     // Check to see if new node is also the head (ie. only list entry)
  181.     if (pHead == NULL)
  182.     {
  183.         pHead = pNew;
  184.         pCurPosition = pNew;
  185.     }
  186. }
  187.  
  188. // -----------------------------------------------------------------
  189. //  Find - private method to find the node with the specified app data
  190. //  attached to it.
  191. // -----------------------------------------------------------------
  192. LPNODE CLinkedList::Find(void  *pData)
  193. {
  194.     LPNODE  pCur;
  195.  
  196.     // go thru list until we reach end or we find the right node.
  197.     for (pCur=pHead; (pCur != NULL) && (pCur->pData != pData); pCur= pCur->pNext);
  198.     return(pCur);
  199. }
  200.  
  201.  
  202. // -----------------------------------------------------------------
  203. //  Insert - create a new node and put it in front of the current
  204. //  position node and make it the current position.
  205. // -----------------------------------------------------------------
  206. void CLinkedList::Insert(void  *pData)
  207. {
  208.     LPNODE  pNext, pPrev;
  209.     LPNODE  pNew = new NODE;
  210.  
  211.     pNew->pData = pData;
  212.  
  213.     // check to be sure that there is a current node
  214.     if (pCurPosition != NULL)
  215.     {
  216.         
  217.         // get pointers of current position
  218.         pPrev = pCurPosition->pPrev;
  219.         pNext = pCurPosition->pNext;
  220.  
  221.         // set new nodes pointers for insertion into the list
  222.         pNew->pPrev = pPrev;
  223.         pNew->pNext = pCurPosition;
  224.  
  225.         // Set the node in front of new node (if any) to point to it
  226.         if (pPrev != NULL)
  227.         {
  228.             pPrev->pNext = pNew;
  229.  
  230.         // No node in front -> new node is at head
  231.         } else {
  232.             pHead = pNew;
  233.         }
  234.  
  235.         // make new node the current node
  236.         pCurPosition = pNew;
  237.  
  238.     // No current node, just Add to front
  239.     } else {
  240.         Add(pData);
  241.     }
  242. }
  243.  
  244. // -----------------------------------------------------------------
  245. //  Insert - create a new node and put it in front of the specified
  246. //  node and make it the current position.
  247. // -----------------------------------------------------------------
  248. void CLinkedList::Insert(void  *pData, void  *pBefore)
  249. {
  250.     // simply make the specified node current and insert the new
  251.     // node.
  252.     pCurPosition = Find(pBefore);
  253.     Insert(pData);
  254. }
  255.  
  256. // -----------------------------------------------------------------
  257. //  Remove - remove a specified node from the list.
  258. //  Note: we do not delete the app data attached to the node!
  259. // -----------------------------------------------------------------
  260. void CLinkedList::Remove()
  261. {
  262.     LPNODE  pCur, pNext, pPrev;
  263.  
  264.     pCur = pCurPosition;
  265.  
  266.     if (pCur != NULL)
  267.     {
  268.  
  269.         // save a copy of the links
  270.         pPrev = pCur->pPrev;
  271.         pNext = pCur->pNext;
  272.  
  273.         // Is there a node ahead of us?
  274.         if (pPrev != NULL)
  275.         {
  276.             // yes -> update it to not point to us.
  277.             pPrev->pNext = pNext;
  278.         } else {
  279.             // no -> update head to not point to us.
  280.             pHead = pNext;
  281.             pCurPosition = pNext;
  282.         }
  283.  
  284.         // Is there a node behind us?
  285.         if (pNext != NULL)
  286.         {
  287.             // yes -> update it to not point to us.
  288.             pNext->pPrev = pPrev;
  289.             pCurPosition = pNext;
  290.         } else {
  291.             // no -> update tail to not point to us.
  292.             pTail = pPrev;
  293.             pCurPosition = pPrev;
  294.         }
  295.  
  296.         delete(pCur);
  297.     }
  298.  
  299. }   
  300.  
  301. // -----------------------------------------------------------------
  302. //  Remove - remove a specified node from the list.
  303. //  Note: we do not delete the app data attached to the node!
  304. // -----------------------------------------------------------------
  305. void CLinkedList::Remove(void  *pData)
  306. {
  307.     pCurPosition = Find(pData);
  308.     Remove();
  309. }   
  310. // -----------------------------------------------------------------
  311. //  RemoveFirst - remove the first node in the list and return the
  312. //  app data associated with it.
  313. // -----------------------------------------------------------------
  314. void * CLinkedList::RemoveFirst()
  315. {
  316.     LPNODE  pCur, pNext;
  317.     void    *pData = NULL;
  318.  
  319.     pCur = pHead;
  320.  
  321.     // is there a node at the head?
  322.     if (pCur != NULL)
  323.     {
  324.  
  325.         // take first node out of list.
  326.         pNext = pCur->pNext;
  327.         pHead = pNext;
  328.         pCurPosition = pNext;
  329.  
  330.         // are there any nodes after us?
  331.         if (pNext != NULL)
  332.         {
  333.             // yes -> make it the new head
  334.             pNext->pPrev = NULL;
  335.         } else {
  336.             // no -> the list is now empty
  337.             pTail = NULL;
  338.         }
  339.  
  340.         // get app data for node and then delete it
  341.         pData = pCur->pData;
  342.         delete(pCur);
  343.     }
  344.  
  345.     return(pData);
  346. }
  347.  
  348. // -----------------------------------------------------------------
  349. //  RemoveLast - remove the last node in the list and return the
  350. //  app data associated with it.
  351. // -----------------------------------------------------------------
  352. void * CLinkedList::RemoveLast()
  353. {
  354.     LPNODE  pCur, pPrev;
  355.     void    *pData = NULL;
  356.  
  357.     pCur = pTail;
  358.  
  359.     // is there a node at the tail?
  360.     if (pCur != NULL)
  361.     {
  362.         // take last node out of list.
  363.         pPrev = pCur->pPrev;
  364.         pTail = pPrev;
  365.  
  366.         // are there any nodes ahead of us?
  367.         if (pPrev != NULL)
  368.         {
  369.             // yes -> make it the new tail node
  370.             pPrev->pNext = NULL;
  371.         } else {
  372.             // no -> list is now empty
  373.             pHead = NULL;
  374.             pCurPosition = NULL;
  375.         }
  376.  
  377.         // get app data for node and then delete it
  378.         pData = pCur->pData;
  379.         delete(pCur);
  380.     }
  381.  
  382.     return(pData);
  383. }
  384.