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.

289 lines
6.2 KiB

  1. /* Template class for doing a simple linked list ...
  2. */
  3. #ifndef _TLIST_H
  4. #define _TLIST_H
  5. // the enum marker that remembers the current position
  6. typedef void * CLISTPOS;
  7. // template class for providing a doubly linked of pointers to nodes
  8. template< class NODETYPE >
  9. class CList
  10. {
  11. protected:
  12. struct CNode
  13. {
  14. NODETYPE * m_pData;
  15. CNode * m_pPrev;
  16. CNode * m_pNext;
  17. };
  18. public:
  19. CList();
  20. ~CList();
  21. CLISTPOS GetHeadPosition();
  22. NODETYPE * GetNext( CLISTPOS & rpCurPos );
  23. int GetCount();
  24. void RemoveAt( CLISTPOS pPos );
  25. void RemoveAll( void );
  26. CLISTPOS FindIndex( int iIndex );
  27. CLISTPOS AddTail( NODETYPE * pData );
  28. CLISTPOS AddBefore( CLISTPOS pPos, NODETYPE * pData );
  29. #ifdef DEBUG
  30. void ValidateList();
  31. #define VALIDATELIST() ValidateList()
  32. #else
  33. #define VALIDATELIST()
  34. #endif
  35. protected:
  36. CNode * m_pHead;
  37. CNode * m_pTail;
  38. };
  39. /////////////////////////////////////////////////////////////////////////////////////////
  40. template< class NODETYPE >
  41. CList<NODETYPE>::CList()
  42. {
  43. m_pHead = NULL;
  44. m_pTail = NULL;
  45. }
  46. /////////////////////////////////////////////////////////////////////////////////////////
  47. template< class NODETYPE >
  48. CList<NODETYPE>::~CList()
  49. {
  50. RemoveAll();
  51. }
  52. /////////////////////////////////////////////////////////////////////////////////////////
  53. template< class NODETYPE >
  54. CLISTPOS CList<NODETYPE>::GetHeadPosition( )
  55. {
  56. return (CLISTPOS) m_pHead;
  57. }
  58. /////////////////////////////////////////////////////////////////////////////////////////
  59. template< class NODETYPE >
  60. NODETYPE * CList<NODETYPE>::GetNext( CLISTPOS & rpCurPos )
  61. {
  62. ASSERT( rpCurPos != NULL );
  63. CNode * pCur = (CNode *) rpCurPos;
  64. NODETYPE * pData = pCur->m_pData;
  65. rpCurPos = (CLISTPOS) pCur->m_pNext;
  66. return pData;
  67. }
  68. /////////////////////////////////////////////////////////////////////////////////////////
  69. template< class NODETYPE >
  70. int CList<NODETYPE>::GetCount()
  71. {
  72. int iLength = 0;
  73. CNode * pCur = m_pHead;
  74. while ( pCur != NULL )
  75. {
  76. pCur = pCur->m_pNext;
  77. iLength ++;
  78. }
  79. return iLength;
  80. }
  81. /////////////////////////////////////////////////////////////////////////////////////////
  82. template< class NODETYPE >
  83. void CList<NODETYPE>::RemoveAt( CLISTPOS pPos )
  84. {
  85. ASSERT( pPos != NULL );
  86. #ifdef _DEBUG
  87. // scan the list to ensure the marker is valid....
  88. CNode * pCur = m_pHead;
  89. while ( pCur != NULL )
  90. {
  91. if ( pCur == (CNode *) pPos )
  92. {
  93. break;
  94. }
  95. pCur = pCur->m_pNext;
  96. }
  97. ASSERT( pCur != NULL )
  98. #endif
  99. CNode * pRealPos = (CNode *) pPos;
  100. if ( pRealPos->m_pPrev == NULL )
  101. {
  102. // we are at the start of the list
  103. m_pHead = pRealPos->m_pNext;
  104. }
  105. else
  106. {
  107. // link the prev one to the next one (bypassing this one)
  108. pRealPos->m_pPrev->m_pNext = pRealPos->m_pNext;
  109. }
  110. if ( pRealPos->m_pNext == NULL )
  111. {
  112. // we are at the end of the list
  113. m_pTail = pRealPos->m_pPrev;
  114. }
  115. else
  116. {
  117. // link the next to the prev (bypassing this one)
  118. pRealPos->m_pNext->m_pPrev = pRealPos->m_pPrev;
  119. }
  120. LocalFree( pRealPos );
  121. VALIDATELIST();
  122. }
  123. /////////////////////////////////////////////////////////////////////////////////////////
  124. template< class NODETYPE >
  125. CLISTPOS CList<NODETYPE>::FindIndex( int iIndex )
  126. {
  127. ASSERT( iIndex >= 0 );
  128. CNode * pCur = m_pHead;
  129. while ( iIndex > 0 && pCur != NULL )
  130. {
  131. pCur = pCur->m_pNext;
  132. iIndex --;
  133. }
  134. return (CLISTPOS)(iIndex == 0 ? pCur : NULL );
  135. }
  136. /////////////////////////////////////////////////////////////////////////////////////////
  137. template< class NODETYPE >
  138. void CList<NODETYPE>::RemoveAll( void )
  139. {
  140. // note we will not free the data elements, the client must do this...
  141. CNode * pCur = m_pHead;
  142. while (pCur != NULL )
  143. {
  144. CNode * pTmp = pCur->m_pNext;
  145. LocalFree( pCur );
  146. pCur = pTmp;
  147. }
  148. m_pHead = m_pTail = NULL;
  149. }
  150. /////////////////////////////////////////////////////////////////////////////////////////
  151. template< class NODETYPE >
  152. CLISTPOS CList<NODETYPE>::AddTail( NODETYPE * pData )
  153. {
  154. CNode * pCurTail = m_pTail;
  155. CNode * pNewNode = (CNode * ) LocalAlloc( GPTR, sizeof( CNode ));
  156. if ( pNewNode == NULL )
  157. {
  158. return NULL;
  159. }
  160. pNewNode->m_pData = pData;
  161. pNewNode->m_pPrev = pCurTail;
  162. pNewNode->m_pNext = NULL;
  163. m_pTail = pNewNode;
  164. if ( pCurTail != NULL )
  165. {
  166. // we are not an empty list
  167. pCurTail->m_pNext = pNewNode;
  168. }
  169. else
  170. {
  171. m_pHead = pNewNode;
  172. }
  173. VALIDATELIST();
  174. return (CLISTPOS) pNewNode;
  175. }
  176. /////////////////////////////////////////////////////////////////////////////////////////
  177. template< class NODETYPE >
  178. CLISTPOS CList<NODETYPE>::AddBefore( CLISTPOS pPos, NODETYPE * pData )
  179. {
  180. if ( !pPos )
  181. {
  182. return NULL;
  183. }
  184. CNode * pPrev = (CNode *) pPos;
  185. CNode * pNewNode = (CNode * ) LocalAlloc( GPTR, sizeof( CNode ));
  186. if ( pNewNode == NULL )
  187. {
  188. return NULL;
  189. }
  190. pNewNode->m_pData = pData;
  191. pNewNode->m_pPrev = pPrev->m_pPrev;
  192. pNewNode->m_pNext = pPrev;
  193. if ( pPrev->m_pPrev != NULL )
  194. {
  195. pPrev->m_pPrev->m_pNext = pNewNode;
  196. }
  197. else
  198. {
  199. // must be at the start of the list...
  200. m_pHead = pNewNode;
  201. }
  202. pPrev->m_pPrev = pNewNode;
  203. VALIDATELIST();
  204. return (CLISTPOS) pNewNode;
  205. }
  206. /////////////////////////////////////////////////////////////////////////////////////////
  207. #ifdef DEBUG
  208. template< class NODETYPE >
  209. void CList<NODETYPE>::ValidateList( )
  210. {
  211. CNode * pPos = m_pHead;
  212. while ( pPos )
  213. {
  214. ASSERT( pPos->m_pData );
  215. if ( pPos != m_pHead )
  216. {
  217. ASSERT( pPos->m_pPrev );
  218. }
  219. pPos = pPos->m_pNext;
  220. }
  221. pPos = m_pTail;
  222. while ( pPos )
  223. {
  224. ASSERT( pPos->m_pData );
  225. if ( pPos != m_pTail )
  226. {
  227. ASSERT( pPos->m_pNext );
  228. }
  229. pPos = pPos->m_pPrev;
  230. }
  231. if ( m_pHead || m_pTail )
  232. {
  233. ASSERT( !m_pHead->m_pPrev );
  234. ASSERT( m_pTail );
  235. ASSERT( m_pHead );
  236. ASSERT( !m_pTail->m_pNext );
  237. }
  238. }
  239. #endif
  240. #endif