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.

258 lines
6.6 KiB

  1. /*
  2. * s r t a r r a y . cpp
  3. *
  4. * Author: Greg Friedman
  5. *
  6. * Purpose: Sorted array that grows dynamically. Sorting is
  7. * deferred until an array element is accessed.
  8. *
  9. * Copyright (C) Microsoft Corp. 1998.
  10. */
  11. #include "pch.hxx"
  12. #include "srtarray.h"
  13. const long c_DefaultCapacity = 16;
  14. //--------------------------------------------------------------------------
  15. // CSortedArray
  16. //--------------------------------------------------------------------------
  17. //--------------------------------------------------------------------------
  18. // CSortedArray::Create
  19. //--------------------------------------------------------------------------
  20. HRESULT CSortedArray::Create(PFNSORTEDARRAYCOMPARE pfnCompare,
  21. PFNSORTEDARRAYFREEITEM pfnFreeItem,
  22. CSortedArray **ppArray)
  23. {
  24. HRESULT hr = S_OK;
  25. if (NULL == ppArray)
  26. return E_INVALIDARG;
  27. CSortedArray *pArray = new CSortedArray(pfnCompare, pfnFreeItem);
  28. if (NULL == pArray)
  29. hr = E_OUTOFMEMORY;
  30. else
  31. *ppArray = pArray;
  32. return hr;
  33. }
  34. //--------------------------------------------------------------------------
  35. // CSortedArray::CSortedArray
  36. //--------------------------------------------------------------------------
  37. CSortedArray::CSortedArray(PFNSORTEDARRAYCOMPARE pfnCompare, PFNSORTEDARRAYFREEITEM pfnFreeItem) :
  38. m_lLength(0),
  39. m_lCapacity(0),
  40. m_data(NULL),
  41. m_pfnCompare(pfnCompare),
  42. m_pfnFreeItem(pfnFreeItem),
  43. m_fSorted(TRUE)
  44. {
  45. // nothing to do
  46. }
  47. //--------------------------------------------------------------------------
  48. // CSortedArray::~CSortedArray
  49. //--------------------------------------------------------------------------
  50. CSortedArray::~CSortedArray(void)
  51. {
  52. if (NULL != m_pfnFreeItem && NULL != m_data)
  53. {
  54. for (long i = 0; i < m_lLength; i++)
  55. (*m_pfnFreeItem)(m_data[i]);
  56. }
  57. SafeMemFree(m_data);
  58. }
  59. //--------------------------------------------------------------------------
  60. // CSortedArray::GetLength
  61. //--------------------------------------------------------------------------
  62. long CSortedArray::GetLength(void) const
  63. {
  64. return m_lLength;
  65. }
  66. //--------------------------------------------------------------------------
  67. // CSortedArray::GetItemAt
  68. //--------------------------------------------------------------------------
  69. void *CSortedArray::GetItemAt(long lIndex) const
  70. {
  71. if (lIndex >= m_lLength || lIndex < 0)
  72. return NULL;
  73. else
  74. {
  75. if (!m_fSorted)
  76. _Sort();
  77. return m_data[lIndex];
  78. }
  79. }
  80. //--------------------------------------------------------------------------
  81. // CSortedArray::Find
  82. //--------------------------------------------------------------------------
  83. BOOL CSortedArray::Find(void* pItem, long *plIndex) const
  84. {
  85. if (!m_fSorted)
  86. _Sort();
  87. if (NULL == plIndex || NULL == pItem)
  88. return FALSE;
  89. *plIndex = 0;
  90. if (0 == m_lLength)
  91. return FALSE;
  92. long lLow = 0;
  93. int result = (*m_pfnCompare)(&pItem, &m_data[lLow]);
  94. if (result < 0)
  95. return FALSE;
  96. if (result == 0)
  97. return TRUE;
  98. long lHigh = m_lLength - 1;
  99. *plIndex = lHigh;
  100. result = (*m_pfnCompare)(&pItem, &m_data[lHigh]);
  101. if (result == 0)
  102. return TRUE;
  103. if (result > 0)
  104. {
  105. *plIndex = lHigh + 1;
  106. return FALSE;
  107. }
  108. while (lLow + 1 < lHigh)
  109. {
  110. long lMid = (lLow + lHigh) / 2;
  111. result = (*m_pfnCompare)(&pItem, &m_data[lMid]);
  112. if (result == 0)
  113. {
  114. *plIndex = lMid;
  115. return TRUE;
  116. }
  117. else
  118. {
  119. if (result < 0)
  120. lHigh = lMid;
  121. else
  122. lLow = lMid;
  123. }
  124. }
  125. *plIndex = lLow + 1;
  126. return FALSE;
  127. }
  128. //--------------------------------------------------------------------------
  129. // CSortedArray::Add
  130. //--------------------------------------------------------------------------
  131. HRESULT CSortedArray::Add(void *pItem)
  132. {
  133. HRESULT hr = S_OK;
  134. if (NULL == pItem)
  135. return E_INVALIDARG;
  136. if (m_lLength == m_lCapacity)
  137. {
  138. if (FAILED(hr = _Grow()))
  139. goto exit;
  140. }
  141. // append the item to the end of the collection,
  142. // and mark the collection as unsorted.
  143. m_data[m_lLength++] = pItem;
  144. m_fSorted = FALSE;
  145. exit:
  146. return hr;
  147. }
  148. //--------------------------------------------------------------------------
  149. // CSortedArray::Remove
  150. //--------------------------------------------------------------------------
  151. HRESULT CSortedArray::Remove(long lIndex)
  152. {
  153. if (lIndex >= m_lLength)
  154. return E_INVALIDARG;
  155. if (!m_fSorted)
  156. _Sort();
  157. --m_lLength;
  158. if (lIndex < m_lLength)
  159. {
  160. memcpy(&m_data[lIndex],
  161. &m_data[lIndex + 1],
  162. (m_lLength - lIndex) * sizeof(void*));
  163. }
  164. return S_OK;
  165. }
  166. //--------------------------------------------------------------------------
  167. // CSortedArray::Remove
  168. //--------------------------------------------------------------------------
  169. HRESULT CSortedArray::Remove(void *pItem)
  170. {
  171. HRESULT hr = S_OK;
  172. long lIndex = 0;
  173. if (NULL == pItem)
  174. return E_INVALIDARG;
  175. if (!m_fSorted)
  176. _Sort();
  177. BOOL fFound = Find(pItem, &lIndex);
  178. if (!fFound)
  179. {
  180. hr = E_FAIL;
  181. goto exit;
  182. }
  183. hr = Remove(lIndex);
  184. exit:
  185. return hr;
  186. }
  187. //--------------------------------------------------------------------------
  188. // CSortedArray::_Grow
  189. //--------------------------------------------------------------------------
  190. HRESULT CSortedArray::_Grow(void) const
  191. {
  192. BOOL fSuccess = FALSE;
  193. if (0 == m_lCapacity)
  194. {
  195. fSuccess = MemAlloc((LPVOID*)&m_data, c_DefaultCapacity * sizeof(void*));
  196. if (fSuccess)
  197. m_lCapacity = c_DefaultCapacity;
  198. }
  199. else
  200. {
  201. long lNewCapacity = m_lCapacity * 2;
  202. fSuccess = MemRealloc((LPVOID*)&m_data, lNewCapacity * sizeof(void*));
  203. if (fSuccess)
  204. m_lCapacity = lNewCapacity;
  205. }
  206. return fSuccess ? S_OK : E_OUTOFMEMORY;;
  207. }
  208. //--------------------------------------------------------------------------
  209. // CSortedArray::_Sort
  210. //--------------------------------------------------------------------------
  211. void CSortedArray::_Sort(void) const
  212. {
  213. if (!m_fSorted && m_lLength > 1 && NULL != m_pfnCompare)
  214. qsort(m_data, m_lLength, sizeof(void*), m_pfnCompare);
  215. m_fSorted = TRUE;
  216. return;
  217. }