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.

237 lines
5.2 KiB

  1. #include "mbftpch.h"
  2. #include "cntlist.h"
  3. CList::CList(ULONG cMaxItems, BOOL fQueue)
  4. :
  5. m_fQueue(fQueue),
  6. m_cMaxEntries(cMaxItems)
  7. {
  8. Init();
  9. }
  10. CList::CList(CList *pSrc)
  11. :
  12. m_fQueue(pSrc->m_fQueue),
  13. m_cMaxEntries(pSrc->GetCount())
  14. {
  15. Init();
  16. LPVOID p;
  17. pSrc->Reset();
  18. while (NULL != (p = pSrc->Iterate()))
  19. {
  20. Append(p);
  21. }
  22. }
  23. BOOL CList::Init(void)
  24. {
  25. if (m_cMaxEntries < CLIST_DEFAULT_MAX_ITEMS)
  26. {
  27. m_cMaxEntries = CLIST_DEFAULT_MAX_ITEMS;
  28. }
  29. m_cEntries = 0;
  30. m_nHeadOffset = 0;
  31. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  32. // it is kind of bad here because there is no way to return an error.
  33. // unfortunately it won't fault here and later.
  34. DBG_SAVE_FILE_LINE
  35. m_aEntries = (LPVOID *) new char[m_cMaxEntries * sizeof(LPVOID)];
  36. return (BOOL) (m_aEntries != NULL);
  37. }
  38. CList::~CList(void)
  39. {
  40. delete m_aEntries;
  41. }
  42. BOOL CList::Expand(void)
  43. {
  44. if (NULL == m_aEntries)
  45. {
  46. // it is impossible.
  47. ASSERT(FALSE);
  48. return Init();
  49. }
  50. // the current array is full
  51. ASSERT(m_cEntries == m_cMaxEntries);
  52. // remember the old array to free or to restore
  53. LPVOID *aOldEntries = m_aEntries;
  54. // we need to allocate a bigger array to hold more data.
  55. // the new array has twice the size of the old one
  56. ULONG cNewMaxEntries = m_cMaxEntries << 1;
  57. DBG_SAVE_FILE_LINE
  58. m_aEntries = (LPVOID *) new char[cNewMaxEntries * sizeof(LPVOID)];
  59. if (NULL == m_aEntries)
  60. {
  61. // we failed; we have to restore the array and return
  62. m_aEntries = aOldEntries;
  63. return FALSE;
  64. }
  65. // copy the old entries into the new array, starting from the beginning
  66. ULONG nIdx = m_cMaxEntries - m_nHeadOffset;
  67. ::CopyMemory(m_aEntries, &aOldEntries[m_nHeadOffset], nIdx * sizeof(LPVOID));
  68. ::CopyMemory(&m_aEntries[nIdx], aOldEntries, m_nHeadOffset * sizeof(LPVOID));
  69. // set the new max entries (required for the key array)
  70. m_cMaxEntries = cNewMaxEntries;
  71. // Free the old array of entries
  72. delete aOldEntries;
  73. // Set the instance variables
  74. m_nHeadOffset = 0;
  75. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  76. return TRUE;
  77. }
  78. BOOL CList::Append(LPVOID pData)
  79. {
  80. if (NULL == m_aEntries || m_cEntries >= m_cMaxEntries)
  81. {
  82. if (! Expand())
  83. {
  84. return FALSE;
  85. }
  86. }
  87. ASSERT(NULL != m_aEntries);
  88. ASSERT(m_cEntries < m_cMaxEntries);
  89. m_aEntries[(m_nHeadOffset + (m_cEntries++)) % m_cMaxEntries] = pData;
  90. return TRUE;
  91. }
  92. BOOL CList::Prepend(LPVOID pData)
  93. {
  94. if (NULL == m_aEntries || m_cEntries >= m_cMaxEntries)
  95. {
  96. if (! Expand())
  97. {
  98. return FALSE;
  99. }
  100. }
  101. ASSERT(NULL != m_aEntries);
  102. ASSERT(m_cEntries < m_cMaxEntries);
  103. m_cEntries++;
  104. m_nHeadOffset = (0 == m_nHeadOffset) ? m_cMaxEntries - 1 : m_nHeadOffset - 1;
  105. m_aEntries[m_nHeadOffset] = pData;
  106. return TRUE;
  107. }
  108. BOOL CList::Find(LPVOID pData)
  109. {
  110. for (ULONG i = 0; i < m_cEntries; i++)
  111. {
  112. if (pData == m_aEntries[(m_nHeadOffset + i) % m_cMaxEntries])
  113. {
  114. return TRUE;
  115. }
  116. }
  117. return FALSE;
  118. }
  119. BOOL CList::Remove(LPVOID pData)
  120. {
  121. ULONG nIdx, nIdxSrc;
  122. for (ULONG i = 0; i < m_cEntries; i++)
  123. {
  124. nIdx = (m_nHeadOffset + i) % m_cMaxEntries;
  125. if (pData == m_aEntries[nIdx])
  126. {
  127. if (! m_fQueue)
  128. {
  129. // to remove the current, we simply move the last to here.
  130. nIdxSrc = (m_nHeadOffset + (m_cEntries - 1)) % m_cMaxEntries;
  131. m_aEntries[nIdx] = m_aEntries[nIdxSrc];
  132. }
  133. else
  134. {
  135. // to preserve the ordering
  136. if (0 == i)
  137. {
  138. m_nHeadOffset = (m_nHeadOffset + 1) % m_cMaxEntries;
  139. }
  140. else
  141. {
  142. for (ULONG j = i + 1; j < m_cEntries; j++)
  143. {
  144. nIdx = (m_nHeadOffset + j - 1) % m_cMaxEntries;
  145. nIdxSrc = (m_nHeadOffset + j) % m_cMaxEntries;
  146. m_aEntries[nIdx] = m_aEntries[nIdxSrc];
  147. }
  148. }
  149. }
  150. m_cEntries--;
  151. return TRUE;
  152. }
  153. }
  154. return FALSE;
  155. }
  156. LPVOID CList::Get(void)
  157. {
  158. LPVOID pRet = NULL;
  159. if (m_cEntries > 0)
  160. {
  161. pRet = m_aEntries[m_nHeadOffset];
  162. m_cEntries--;
  163. m_nHeadOffset = (m_nHeadOffset + 1) % m_cMaxEntries;
  164. }
  165. else
  166. {
  167. pRet = NULL;
  168. }
  169. return pRet;
  170. }
  171. LPVOID CList::Iterate(void)
  172. {
  173. if (0 == m_cEntries)
  174. {
  175. return NULL;
  176. }
  177. if (m_nCurrOffset == CLIST_END_OF_ARRAY_MARK)
  178. {
  179. // start from the beginning
  180. m_nCurrOffset = 0;
  181. }
  182. else
  183. {
  184. if (++m_nCurrOffset >= m_cEntries)
  185. {
  186. // reset the iterator
  187. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  188. return NULL;
  189. }
  190. }
  191. return m_aEntries[(m_nHeadOffset + m_nCurrOffset) % m_cMaxEntries];
  192. }
  193.