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.

318 lines
7.3 KiB

  1. /********************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. PFArray.cpp
  5. Abstract:
  6. dynamic array implementation. This dynamic array is NOT thread
  7. safe.
  8. Revision History:
  9. DerekM modified 03/14/00
  10. ********************************************************************/
  11. #include "stdafx.h"
  12. #include "pfarray.h"
  13. /////////////////////////////////////////////////////////////////////////////
  14. // tracing
  15. #ifdef THIS_FILE
  16. #undef THIS_FILE
  17. #endif
  18. static char __szTraceSourceFile[] = __FILE__;
  19. #define THIS_FILE __szTraceSourceFile
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CPFArrayBase initialization & deinitialization
  22. // **************************************************************************
  23. CPFArrayBase::CPFArrayBase(void)
  24. {
  25. m_pfnAlloc = NULL;
  26. m_pfnDelete = NULL;
  27. m_rgpv = NULL;
  28. m_cSlots = 0;
  29. m_iHighest = (DWORD)-1;
  30. }
  31. // **************************************************************************
  32. CPFArrayBase::~CPFArrayBase(void)
  33. {
  34. this->CompressArray(0, (DWORD)-1);
  35. if (m_rgpv != NULL)
  36. MyFree(m_rgpv, g_hPFPrivateHeap);
  37. }
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CAUOPropDB internal methods
  40. // ***************************************************************************
  41. inline HRESULT CPFArrayBase::Grow(DWORD iMinLast)
  42. {
  43. USE_TRACING("CPFArrayBase::SetItem");
  44. HRESULT hr = NOERROR;
  45. if (iMinLast >= m_cSlots || m_rgpv == NULL)
  46. {
  47. LPVOID *rgpv = NULL;
  48. DWORD cSlots;
  49. cSlots = MyMax(iMinLast + 1, 8);
  50. cSlots = MyMax(m_cSlots * 2, cSlots);
  51. rgpv = (LPVOID *)MyAlloc(cSlots * sizeof(LPVOID), g_hPFPrivateHeap);
  52. VALIDATEEXPR(hr, (rgpv == NULL), E_OUTOFMEMORY);
  53. if (FAILED(hr))
  54. goto done;
  55. if (m_rgpv != NULL)
  56. {
  57. CopyMemory(rgpv, m_rgpv, m_cSlots * sizeof(LPVOID));
  58. MyFree(m_rgpv);
  59. }
  60. m_rgpv = rgpv;
  61. m_cSlots = cSlots;
  62. }
  63. done:
  64. return hr;
  65. }
  66. // ***************************************************************************
  67. inline HRESULT CPFArrayBase::CompressArray(DWORD iStart, DWORD iEnd)
  68. {
  69. USE_TRACING("CPFArrayBase::CompressArray");
  70. _ASSERT(iStart < iEnd);
  71. // don't need to do anything cuz we're already empty
  72. if (m_iHighest == (DWORD)-1)
  73. return NOERROR;
  74. if (iStart <= m_iHighest)
  75. {
  76. DWORD i;
  77. // note that this will also catch passing -1 for iEnd cuz (DWORD)-1
  78. // is greater than any other DWORD value... Of course, this
  79. // assumes that we don't have 2^32 - 1 elements. While it is
  80. // theoretically possible to have an array that big on ia64, this
  81. // class can't be used for it.
  82. if (iEnd > m_iHighest + 1)
  83. iEnd = m_iHighest + 1;
  84. for(i = iStart; i < iEnd; i++)
  85. {
  86. if (m_rgpv[i] != NULL)
  87. this->DeleteItem(m_rgpv[i]);
  88. }
  89. // no point in doing a move if we're not going to be moving anything
  90. if (iEnd <= m_iHighest)
  91. {
  92. MoveMemory(&m_rgpv[iStart], &m_rgpv[iEnd],
  93. (m_iHighest - iEnd + 1) * sizeof(LPVOID));
  94. }
  95. }
  96. m_iHighest -= (iEnd - iStart);
  97. return NOERROR;
  98. }
  99. // ***************************************************************************
  100. HRESULT CPFArrayBase::internalCopyFrom(CPFArrayBase *prg)
  101. {
  102. USE_TRACING("CPFArrayBase::CopyFrom");
  103. HRESULT hr = NOERROR;
  104. DWORD i;
  105. // if it's at -1, then we've deleted everything already...
  106. if (prg->m_iHighest == (DWORD)-1)
  107. goto done;
  108. TESTHR(hr, this->Grow(prg->m_iHighest + 1));
  109. if (FAILED(hr))
  110. goto done;
  111. for(i = 0; i < prg->m_iHighest + 1; i++)
  112. {
  113. m_rgpv[i] = prg->AllocItemCopy(prg->m_rgpv[i]);
  114. VALIDATEEXPR(hr, (m_rgpv[i] == NULL), E_OUTOFMEMORY);
  115. if (FAILED(hr))
  116. {
  117. this->RemoveAll();
  118. goto done;
  119. }
  120. }
  121. done:
  122. return hr;
  123. }
  124. /////////////////////////////////////////////////////////////////////////////
  125. // CPFArrayBase exposed methods / properties
  126. // ***************************************************************************
  127. HRESULT CPFArrayBase::Init(DWORD cSlots)
  128. {
  129. USE_TRACING("CPFArrayBase::Init");
  130. HRESULT hr = NOERROR;
  131. VALIDATEEXPR(hr, (m_rgpv != NULL), E_FAIL);
  132. if (FAILED(hr))
  133. goto done;
  134. TESTHR(hr, this->Grow(cSlots - 1));
  135. if (FAILED(hr))
  136. goto done;
  137. done:
  138. return hr;
  139. }
  140. // ***************************************************************************
  141. LPVOID &CPFArrayBase::operator [](DWORD iItem)
  142. {
  143. USE_TRACING("CPFArrayBase::operator []");
  144. if (iItem >= m_cSlots || m_rgpv == NULL)
  145. {
  146. HRESULT hr;
  147. TESTHR(hr, this->Grow(iItem));
  148. _ASSERT(SUCCEEDED(hr));
  149. }
  150. // since we have to return a reference, we can't do much about Grow failing
  151. // which means of course that we could fault...
  152. return m_rgpv[iItem];
  153. }
  154. // ***************************************************************************
  155. HRESULT CPFArrayBase::get_Item(DWORD iItem, LPVOID *ppv)
  156. {
  157. USE_TRACING("CPFArrayBase::get_Item");
  158. HRESULT hr = NOERROR;
  159. VALIDATEPARM(hr, (ppv == NULL))
  160. if (FAILED(hr))
  161. goto done;
  162. if (iItem >= m_cSlots || m_rgpv == NULL)
  163. {
  164. TESTHR(hr, this->Grow(iItem));
  165. if (FAILED(hr))
  166. goto done;
  167. }
  168. if (ppv != NULL)
  169. *ppv = m_rgpv[iItem];
  170. done:
  171. return hr;
  172. }
  173. // ***************************************************************************
  174. HRESULT CPFArrayBase::put_Item(DWORD iItem, LPVOID pv, LPVOID *ppvOld)
  175. {
  176. USE_TRACING("CPFArrayBase::put_Item");
  177. HRESULT hr = NOERROR;
  178. if (iItem >= m_cSlots || m_rgpv == NULL)
  179. {
  180. TESTHR(hr, this->Grow(m_iHighest + 1));
  181. if (FAILED(hr))
  182. goto done;
  183. }
  184. if (ppvOld != NULL)
  185. *ppvOld = m_rgpv[iItem];
  186. else if (m_rgpv[iItem] != NULL)
  187. this->DeleteItem(m_rgpv[iItem]);
  188. m_rgpv[iItem] = pv;
  189. if (iItem > m_iHighest)
  190. m_iHighest = iItem;
  191. done:
  192. return hr;
  193. }
  194. // ***************************************************************************
  195. HRESULT CPFArrayBase::Append(LPVOID pv)
  196. {
  197. USE_TRACING("CPFArrayBase::Append");
  198. HRESULT hr = NOERROR;
  199. if (pv == NULL)
  200. pv = NULL;
  201. if (m_iHighest + 1 >= m_cSlots || m_rgpv == NULL)
  202. {
  203. TESTHR(hr, this->Grow(m_iHighest + 1));
  204. if (FAILED(hr))
  205. goto done;
  206. }
  207. m_iHighest++;
  208. m_rgpv[m_iHighest] = pv;
  209. done:
  210. return hr;
  211. }
  212. // ***************************************************************************
  213. HRESULT CPFArrayBase::Remove(DWORD iItem, LPVOID *ppvOld)
  214. {
  215. USE_TRACING("CPFArrayBase::Remove");
  216. HRESULT hr = NOERROR;
  217. if (iItem > m_iHighest)
  218. goto done;
  219. if (ppvOld != NULL)
  220. *ppvOld = m_rgpv[iItem];
  221. TESTHR(hr, this->CompressArray(iItem, iItem + 1));
  222. if (FAILED(hr))
  223. return hr;
  224. done:
  225. return hr;
  226. }
  227. // ***************************************************************************
  228. HRESULT CPFArrayBase::RemoveAll(void)
  229. {
  230. USE_TRACING("CPFArrayBase::RemoveAll");
  231. HRESULT hr = NOERROR;
  232. // if it's at -1, then we've deleted everything already...
  233. if (m_iHighest == (DWORD)-1)
  234. goto done;
  235. TESTHR(hr, this->CompressArray(0, (DWORD)-1));
  236. if (FAILED(hr))
  237. return hr;
  238. done:
  239. return hr;
  240. }