Leaked source code of windows server 2003
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.

367 lines
7.6 KiB

  1. /* Copyright (C) Microsoft Corporation, 1998. All rights reserved. */
  2. #include "precomp.h"
  3. #include "cntlist.h"
  4. CList::CList(UINT cMaxItems)
  5. :
  6. m_cMaxEntries(cMaxItems)
  7. {
  8. Init(1);
  9. }
  10. CList::CList(CList *pSrc)
  11. :
  12. m_cMaxEntries(pSrc->GetCount())
  13. {
  14. Init(1);
  15. LPVOID p;
  16. pSrc->Reset();
  17. while (NULL != (p = pSrc->Iterate()))
  18. {
  19. Append(p);
  20. }
  21. }
  22. CList::CList(UINT cMaxItems, UINT cSubItems)
  23. :
  24. m_cMaxEntries(cMaxItems)
  25. {
  26. ASSERT(2 == cSubItems);
  27. Init(cSubItems);
  28. }
  29. BOOL CList::Init(UINT cSubItems)
  30. {
  31. if (m_cMaxEntries < CLIST_DEFAULT_MAX_ITEMS)
  32. {
  33. m_cMaxEntries = CLIST_DEFAULT_MAX_ITEMS;
  34. }
  35. m_cEntries = 0;
  36. m_nHeadOffset = 0;
  37. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  38. m_cSubItems = cSubItems;
  39. // it is kind of bad here because there is no way to return an error.
  40. // unfortunately it won't fault here and later.
  41. m_aEntries = (LPVOID *) new char[m_cMaxEntries * m_cSubItems * sizeof(LPVOID)];
  42. CalcKeyArray();
  43. return (BOOL) m_aEntries;
  44. }
  45. CList::~CList(void)
  46. {
  47. delete m_aEntries;
  48. }
  49. void CList::CalcKeyArray(void)
  50. {
  51. if (1 == m_cSubItems)
  52. {
  53. m_aKeys = NULL;
  54. }
  55. else
  56. {
  57. ASSERT(2 == m_cSubItems);
  58. m_aKeys = (NULL != m_aEntries) ?
  59. (UINT *) &m_aEntries[m_cMaxEntries] :
  60. NULL;
  61. }
  62. }
  63. BOOL CList::Expand(void)
  64. {
  65. if (NULL == m_aEntries)
  66. {
  67. // it is impossible.
  68. ASSERT(FALSE);
  69. return Init(m_cSubItems);
  70. }
  71. // the current array is full
  72. ASSERT(m_cEntries == m_cMaxEntries);
  73. // remember the old array to free or to restore
  74. LPVOID *aOldEntries = m_aEntries;
  75. // we need to allocate a bigger array to hold more data.
  76. // the new array has twice the size of the old one
  77. UINT cNewMaxEntries = m_cMaxEntries << 1;
  78. m_aEntries = (LPVOID *) new char[cNewMaxEntries * m_cSubItems * sizeof(LPVOID)];
  79. if (NULL == m_aEntries)
  80. {
  81. // we failed; we have to restore the array and return
  82. m_aEntries = aOldEntries;
  83. return FALSE;
  84. }
  85. // copy the old entries into the new array, starting from the beginning
  86. UINT nIdx = m_cMaxEntries - m_nHeadOffset;
  87. ::CopyMemory(m_aEntries, &aOldEntries[m_nHeadOffset], nIdx * sizeof(LPVOID));
  88. ::CopyMemory(&m_aEntries[nIdx], aOldEntries, m_nHeadOffset * sizeof(LPVOID));
  89. // set the new max entries (required for the key array)
  90. m_cMaxEntries = cNewMaxEntries;
  91. if (m_cSubItems > 1)
  92. {
  93. ASSERT(2 == m_cSubItems);
  94. UINT *aOldKeys = m_aKeys;
  95. CalcKeyArray();
  96. ::CopyMemory(m_aKeys, &aOldKeys[m_nHeadOffset], nIdx * sizeof(UINT));
  97. ::CopyMemory(&m_aKeys[nIdx], aOldKeys, m_nHeadOffset * sizeof(UINT));
  98. }
  99. // Free the old array of entries
  100. delete aOldEntries;
  101. // Set the instance variables
  102. m_nHeadOffset = 0;
  103. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  104. return TRUE;
  105. }
  106. BOOL CList::Append(LPVOID pData)
  107. {
  108. if (NULL == m_aEntries || m_cEntries >= m_cMaxEntries)
  109. {
  110. if (! Expand())
  111. {
  112. return FALSE;
  113. }
  114. }
  115. ASSERT(NULL != m_aEntries);
  116. ASSERT(m_cEntries < m_cMaxEntries);
  117. m_aEntries[(m_nHeadOffset + (m_cEntries++)) % m_cMaxEntries] = pData;
  118. return TRUE;
  119. }
  120. BOOL CList::Prepend(LPVOID pData)
  121. {
  122. if (NULL == m_aEntries || m_cEntries >= m_cMaxEntries)
  123. {
  124. if (! Expand())
  125. {
  126. return FALSE;
  127. }
  128. }
  129. ASSERT(NULL != m_aEntries);
  130. ASSERT(m_cEntries < m_cMaxEntries);
  131. m_cEntries++;
  132. m_nHeadOffset = (0 == m_nHeadOffset) ? m_cMaxEntries - 1 : m_nHeadOffset - 1;
  133. m_aEntries[m_nHeadOffset] = pData;
  134. return TRUE;
  135. }
  136. BOOL CList::Find(LPVOID pData)
  137. {
  138. for (UINT i = 0; i < m_cEntries; i++)
  139. {
  140. if (pData == m_aEntries[(m_nHeadOffset + i) % m_cMaxEntries])
  141. {
  142. return TRUE;
  143. }
  144. }
  145. return FALSE;
  146. }
  147. BOOL CList::Remove(LPVOID pData)
  148. {
  149. UINT nIdx;
  150. for (UINT i = 0; i < m_cEntries; i++)
  151. {
  152. nIdx = (m_nHeadOffset + i) % m_cMaxEntries;
  153. if (pData == m_aEntries[nIdx])
  154. {
  155. // to remove the current, we simply move the last to here.
  156. UINT nIdxSrc = (m_nHeadOffset + (m_cEntries - 1)) % m_cMaxEntries;
  157. m_aEntries[nIdx] = m_aEntries[nIdxSrc];
  158. if (m_cSubItems > 1)
  159. {
  160. ASSERT(2 == m_cSubItems);
  161. m_aKeys[nIdx] = m_aKeys[nIdxSrc];
  162. }
  163. m_cEntries--;
  164. return TRUE;
  165. }
  166. }
  167. return FALSE;
  168. }
  169. LPVOID CList::Get(void)
  170. {
  171. LPVOID pRet = NULL;
  172. if (m_cEntries > 0)
  173. {
  174. pRet = m_aEntries[m_nHeadOffset];
  175. m_cEntries--;
  176. m_nHeadOffset = (m_nHeadOffset + 1) % m_cMaxEntries;
  177. }
  178. else
  179. {
  180. pRet = NULL;
  181. }
  182. return pRet;
  183. }
  184. LPVOID CList::Iterate(void)
  185. {
  186. if (0 == m_cEntries)
  187. {
  188. return NULL;
  189. }
  190. if (m_nCurrOffset == CLIST_END_OF_ARRAY_MARK)
  191. {
  192. // start from the beginning
  193. m_nCurrOffset = 0;
  194. }
  195. else
  196. {
  197. if (++m_nCurrOffset >= m_cEntries)
  198. {
  199. // reset the iterator
  200. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  201. return NULL;
  202. }
  203. }
  204. return m_aEntries[(m_nHeadOffset + m_nCurrOffset) % m_cMaxEntries];
  205. }
  206. CList2::CList2(CList2 *pSrc)
  207. :
  208. CList(pSrc->GetCount(), 2)
  209. {
  210. CalcKeyArray();
  211. LPVOID p;
  212. UINT n;
  213. pSrc->Reset();
  214. while (NULL != (p = pSrc->Iterate(&n)))
  215. {
  216. Append(n, p);
  217. }
  218. }
  219. BOOL CList2::Append(UINT nKey, LPVOID pData)
  220. {
  221. if (! CList::Append(pData))
  222. {
  223. return FALSE;
  224. }
  225. // after CList::append(), m_cEntries has been incremented,
  226. // therefore, we need decrement it again.
  227. m_aKeys[(m_nHeadOffset + (m_cEntries - 1)) % m_cMaxEntries] = nKey;
  228. return TRUE;
  229. }
  230. BOOL CList2::Prepend(UINT nKey, LPVOID pData)
  231. {
  232. if (! CList::Prepend(pData))
  233. {
  234. return FALSE;
  235. }
  236. m_aKeys[m_nHeadOffset] = nKey;
  237. return TRUE;
  238. }
  239. LPVOID CList2::Find(UINT nKey)
  240. {
  241. UINT nIdx;
  242. for (UINT i = 0; i < m_cEntries; i++)
  243. {
  244. nIdx = (m_nHeadOffset + i) % m_cMaxEntries;
  245. if (nKey == m_aKeys[nIdx])
  246. {
  247. return m_aEntries[nIdx];
  248. }
  249. }
  250. return NULL;
  251. }
  252. LPVOID CList2::Remove(UINT nKey)
  253. {
  254. UINT nIdx;
  255. for (UINT i = 0; i < m_cEntries; i++)
  256. {
  257. nIdx = (m_nHeadOffset + i) % m_cMaxEntries;
  258. if (nKey == m_aKeys[nIdx])
  259. {
  260. LPVOID pRet = m_aEntries[nIdx];
  261. // to remove the current, we simply move the last to here.
  262. UINT nIdxSrc = (m_nHeadOffset + (m_cEntries - 1)) % m_cMaxEntries;
  263. m_aEntries[nIdx] = m_aEntries[nIdxSrc];
  264. m_aKeys[nIdx] = m_aKeys[nIdxSrc];
  265. m_cEntries--;
  266. return pRet;
  267. }
  268. }
  269. return NULL;
  270. }
  271. LPVOID CList2::Get(UINT *pnKey)
  272. {
  273. LPVOID pRet = NULL;
  274. if (m_cEntries > 0)
  275. {
  276. pRet = m_aEntries[m_nHeadOffset];
  277. *pnKey = m_aKeys[m_nHeadOffset];
  278. m_cEntries--;
  279. m_nHeadOffset = (m_nHeadOffset + 1) % m_cMaxEntries;
  280. }
  281. else
  282. {
  283. pRet = NULL;
  284. *pnKey = 0;
  285. }
  286. return pRet;
  287. }
  288. LPVOID CList2::Iterate(UINT *pnKey)
  289. {
  290. LPVOID p = CList::Iterate();
  291. *pnKey = (NULL != p) ? m_aKeys[(m_nHeadOffset + m_nCurrOffset) % m_cMaxEntries] : 0;
  292. return p;
  293. }