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.

238 lines
4.7 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) 1998-1998 Microsoft Corporation
  6. //
  7. // File: tlist.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // tlist.cpp
  12. //
  13. //#include "stdafx.h"
  14. #include "tlist.h"
  15. template <class T>
  16. TListItem<T>::~TListItem()
  17. {
  18. //if (m_pNext != NULL) { delete m_pNext; }
  19. // IMPORTANT: user of the list is required to delete content first!
  20. //ZeroMemory(&m_Tinfo, sizeof(T));
  21. }
  22. template <class T>
  23. void TListItem<T>::Delete(TListItem<T>* pFirst)
  24. {
  25. TListItem<T>* pScan = pFirst;
  26. TListItem<T>* pNext = NULL;
  27. while (pScan)
  28. {
  29. pNext = pScan->m_pNext;
  30. delete pScan;
  31. pScan = pNext;
  32. }
  33. }
  34. template <class T>
  35. LONG TListItem<T>::GetCount(void) const
  36. {
  37. LONG l;
  38. const TListItem<T> *li;
  39. for(l=0,li=this; li!=NULL ; li=li->m_pNext,++l);
  40. return l;
  41. }
  42. template <class T>
  43. TListItem<T>* TListItem<T>::Cat(TListItem<T> *pItem)
  44. {
  45. TListItem<T> *li;
  46. if(this==NULL)
  47. return pItem;
  48. for(li=this ; li->m_pNext!=NULL ; li=li->m_pNext);
  49. li->m_pNext=pItem;
  50. return this;
  51. }
  52. template <class T>
  53. TListItem<T>* TListItem<T>::Remove(TListItem<T> *pItem)
  54. {
  55. TListItem<T> *li,*prev;
  56. if(pItem==this)
  57. return m_pNext;
  58. prev=NULL;
  59. for(li=this; li!=NULL && li!=pItem ; li=li->m_pNext)
  60. prev=li;
  61. if(li==NULL) // item not found in list
  62. return this;
  63. // here it is guaranteed that prev is non-NULL since we checked for
  64. // that condition at the very beginning
  65. prev->SetNext(li->m_pNext);
  66. li->SetNext(NULL);
  67. return this;
  68. }
  69. template <class T>
  70. TListItem<T>* TListItem<T>::GetPrev(TListItem<T> *pItem) const
  71. {
  72. const TListItem<T> *li,*prev;
  73. prev=NULL;
  74. for(li=this ; li!=NULL && li!=pItem ; li=li->m_pNext)
  75. prev=li;
  76. return (TListItem<T>*)prev;
  77. }
  78. template <class T>
  79. TListItem<T> * TListItem<T>::GetItem(LONG index)
  80. {
  81. TListItem<T> *scan;
  82. for (scan = this; scan!=NULL && index; scan = scan->m_pNext)
  83. {
  84. index--;
  85. }
  86. return (scan);
  87. }
  88. template <class T>
  89. TListItem<T>* TListItem<T>::MergeSort(BOOL (* fcnCompare) (T&, T&))
  90. {
  91. if (m_pNext != NULL)
  92. {
  93. TListItem<T> *pList1, *pList2;
  94. Divide(pList1, pList2);
  95. return pList1->MergeSort(fcnCompare)->Merge(pList2->MergeSort(fcnCompare), fcnCompare);
  96. }
  97. return this;
  98. }
  99. template <class T>
  100. void TListItem<T>::Divide(TListItem<T>*& pHead1, TListItem<T>*& pHead2)
  101. {
  102. TListItem<T> *pCurrent = this, *pTail1 = NULL, *pTail2 = NULL;
  103. do
  104. {
  105. pHead1 = pCurrent;
  106. pCurrent = pCurrent->m_pNext;
  107. pHead1->m_pNext = pTail1;
  108. pTail1 = pHead1;
  109. if (pCurrent != NULL)
  110. {
  111. pHead2 = pCurrent;
  112. pCurrent = pCurrent->m_pNext;
  113. pHead2->m_pNext = pTail2;
  114. pTail2 = pHead2;
  115. }
  116. } while (pCurrent != NULL);
  117. }
  118. template <class T>
  119. TListItem<T>* TListItem<T>::Merge(TListItem<T>* pOtherList, BOOL (* fcnCompare) (T&, T&))
  120. {
  121. if (!pOtherList) return this;
  122. TListItem<T>
  123. *pThisList = this, *pResultHead = NULL, *pResultTail = NULL, *pMergeItem = NULL;
  124. while (pThisList && pOtherList)
  125. {
  126. if ( fcnCompare(pThisList->m_Tinfo, pOtherList->m_Tinfo) )
  127. {
  128. pMergeItem = pThisList;
  129. pThisList = pThisList->GetNext();
  130. }
  131. else
  132. {
  133. pMergeItem = pOtherList;
  134. pOtherList = pOtherList->GetNext();
  135. }
  136. pMergeItem->SetNext(NULL);
  137. if (!pResultTail)
  138. {
  139. pResultHead = pResultTail = pMergeItem;
  140. }
  141. else
  142. {
  143. pResultTail->SetNext(pMergeItem);
  144. pResultTail = pMergeItem;
  145. }
  146. }
  147. if (pThisList) pResultTail->SetNext(pThisList);
  148. else pResultTail->SetNext(pOtherList);
  149. return pResultHead;
  150. }
  151. template <class T>
  152. void TList<T>::InsertBefore(TListItem<T> *pItem,TListItem<T> *pInsert)
  153. {
  154. TListItem<T> *prev = GetPrev(pItem);
  155. pInsert->SetNext(pItem);
  156. if (prev) prev->SetNext(pInsert);
  157. else m_pHead = pInsert;
  158. }
  159. template <class T>
  160. void TList<T>::AddTail(TListItem<T> *pItem)
  161. {
  162. m_pHead = m_pHead->AddTail(pItem);
  163. }
  164. template <class T>
  165. void TList<T>::MergeSort(BOOL (* fcnCompare) (T&, T&))
  166. {
  167. if (m_pHead != NULL && m_pHead->GetNext() != NULL)
  168. m_pHead = m_pHead->MergeSort(fcnCompare);
  169. }
  170. template <class T>
  171. void TList<T>::Reverse(void)
  172. {
  173. if( m_pHead )
  174. {
  175. TListItem<T>* pNewHead = m_pHead;
  176. TListItem<T>* pNext = m_pHead->GetNext();
  177. pNewHead->SetNext(NULL);
  178. for( m_pHead = pNext; m_pHead; m_pHead = pNext )
  179. {
  180. pNext = m_pHead->GetNext();
  181. m_pHead->SetNext(pNewHead);
  182. pNewHead = m_pHead;
  183. }
  184. m_pHead = pNewHead;
  185. }
  186. }
  187. template <class T>
  188. HRESULT TList<T>::Copy(TList<T>& rList)
  189. {
  190. HRESULT hr = S_OK;
  191. TListItem<T>* pScan = m_pHead;
  192. for (; pScan; pScan = pScan->GetNext())
  193. {
  194. T& rScan = pScan->GetItemValue();
  195. TListItem<T>* pNew = new TListItem<T>(rScan);
  196. if (pNew)
  197. {
  198. rList.AddHead(pNew);
  199. }
  200. else
  201. {
  202. hr = E_OUTOFMEMORY;
  203. break;
  204. }
  205. }
  206. if (SUCCEEDED(hr))
  207. {
  208. rList.Reverse();
  209. }
  210. return hr;
  211. }