list.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. //
  2. // File: list.h
  3. //
  4. // Description:
  5. // This file contains codes for a linked list template that
  6. // can be used as a stack or a queue.
  7. //
  8. // History:
  9. // Mar 5, 1997 jfink Created file.
  10. // Jan 7, 1998 jfink Added Empty method.
  11. //
  12. #ifndef _LIST_H_
  13. #define _LIST_H_
  14. #include "base.h"
  15. template <class TElement> class FListIterator
  16. {
  17. public:
  18. virtual void OnIterate(TElement* pElement, DWORD dw, void* pv) = 0;
  19. } ;
  20. template <class TElement> class FList : public CBase
  21. {
  22. protected:
  23. TElement *mpHead, *mpTail;
  24. DWORD mcElements;
  25. public:
  26. FList();
  27. virtual ~FList();
  28. DWORD Length();
  29. VOID Enqueue(TElement *pElement);
  30. TElement *Dequeue();
  31. VOID Push(TElement *pElement);
  32. TElement *Pop();
  33. TElement *Find(const TElement &Element);
  34. TElement *Find(TElement *pStart, const TElement &Element);
  35. TElement *Remove(const TElement &Element);
  36. TElement *Remove(TElement *pELement);
  37. void Iterate(FListIterator<TElement>* pIterator, DWORD dw, void* pv);
  38. VOID Empty();
  39. } ;
  40. template <class TElement>
  41. FList<TElement>::FList() : CBase()
  42. {
  43. mpHead = mpTail = NULL;
  44. mcElements = 0;
  45. }
  46. template <class TElement>
  47. FList<TElement>::~FList()
  48. {
  49. this->Empty();
  50. }
  51. template <class TElement>
  52. DWORD FList<TElement>::Length()
  53. {
  54. return(mcElements);
  55. }
  56. template <class TElement>
  57. VOID FList<TElement>::Enqueue(TElement *pElement)
  58. {
  59. this->Lock();
  60. if (NULL == mpHead)
  61. mpHead = pElement;
  62. else
  63. mpTail->mpNext = pElement;
  64. mpTail = pElement;
  65. pElement->mpNext = NULL;
  66. mcElements++;
  67. this->Unlock();
  68. }
  69. template <class TElement>
  70. TElement *FList<TElement>::Dequeue()
  71. {
  72. TElement *pTemp;
  73. this->Lock();
  74. pTemp = mpHead;
  75. if (NULL != mpHead)
  76. {
  77. mpHead = mpHead->mpNext;
  78. pTemp->mpNext = NULL;
  79. mcElements--;
  80. } else
  81. mpTail = NULL;
  82. this->Unlock();
  83. return(pTemp);
  84. }
  85. template <class TElement>
  86. VOID FList<TElement>::Iterate(FListIterator<TElement>* pIterator, DWORD dw, void* pv)
  87. {
  88. if (!pIterator)
  89. return;
  90. this->Lock();
  91. for (TElement* pTemp = mpHead; NULL != pTemp; pTemp = pTemp->mpNext)
  92. {
  93. pIterator->OnIterate(pTemp, dw, pv);
  94. }
  95. this->Unlock();
  96. }
  97. template <class TElement>
  98. VOID FList<TElement>::Push(TElement *pElement)
  99. {
  100. if (pElement)
  101. {
  102. this->Lock();
  103. if (NULL == mpHead)
  104. mpTail = pElement;
  105. pElement->mpNext = mpHead;
  106. mpHead = pElement;
  107. mcElements++;
  108. this->Unlock();
  109. }
  110. }
  111. template <class TElement>
  112. TElement *FList<TElement>::Pop()
  113. {
  114. return(this->Dequeue());
  115. }
  116. //
  117. // Find the element in the list, starting a pStart, whose contents
  118. // match Element.
  119. //
  120. template <class TElement>
  121. TElement *FList<TElement>::Find(TElement *pStart, const TElement &Element)
  122. {
  123. TElement *pLoop;
  124. this->Lock();
  125. for(pLoop = pStart; NULL != pLoop; pLoop = pLoop->mpNext)
  126. {
  127. if (pLoop->Find(Element))
  128. break;
  129. }
  130. this->Unlock();
  131. return(pLoop);
  132. }
  133. //
  134. // Find the element in the list, starting at the head, whose contents
  135. // match Element.
  136. //
  137. template <class TElement>
  138. TElement *FList<TElement>::Find(const TElement &Element)
  139. {
  140. return(this->Find(mpHead, Element));
  141. }
  142. //
  143. // Remove the element from the list whose contents match
  144. // Element.
  145. //
  146. template <class TElement>
  147. TElement *FList<TElement>::Remove(const TElement &Element)
  148. {
  149. TElement *pLoop, *pPrev;
  150. this->Lock();
  151. for(pPrev = NULL, pLoop = mpHead;
  152. NULL != pLoop;
  153. pPrev = pLoop, pLoop = pLoop->mpNext)
  154. {
  155. if (*pLoop == Element)
  156. {
  157. //
  158. // Remove the node from the list.
  159. //
  160. if (pLoop == mpHead)
  161. mpHead = pLoop->mpNext;
  162. else
  163. pPrev->mpNext = pLoop->mpNext;
  164. if (pLoop == mpTail)
  165. mpTail = pPrev;
  166. pLoop->mpNext = NULL;
  167. mcElements--;
  168. break;
  169. }
  170. }
  171. this->Unlock();
  172. return(pLoop);
  173. }
  174. //
  175. // Remove the element from the list whose pointer matches
  176. // pElement.
  177. //
  178. template <class TElement>
  179. TElement *FList<TElement>::Remove(TElement * pElement)
  180. {
  181. TElement *pLoop, *pPrev;
  182. this->Lock();
  183. for(pPrev = NULL, pLoop = mpHead;
  184. NULL != pLoop;
  185. pPrev = pLoop, pLoop = pLoop->mpNext)
  186. {
  187. if (pLoop == pElement)
  188. {
  189. //
  190. // Remove the node from the list.
  191. //
  192. if (pLoop == mpHead)
  193. mpHead = pLoop->mpNext;
  194. else
  195. pPrev->mpNext = pLoop->mpNext;
  196. if (pLoop == mpTail)
  197. mpTail = pPrev;
  198. pLoop->mpNext = NULL;
  199. mcElements--;
  200. break;
  201. }
  202. }
  203. this->Unlock();
  204. return(pLoop);
  205. }
  206. template <class TElement>
  207. VOID FList<TElement>::Empty()
  208. {
  209. TElement *pElement;
  210. this->Lock();
  211. while(pElement = this->Pop())
  212. {
  213. delete pElement;
  214. }
  215. this->Unlock();
  216. }
  217. #endif