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.

263 lines
5.2 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995
  5. //
  6. // File: ptrarray.cpp
  7. //
  8. // Contents: Handles dynamic arrays of void *. Stolen from MFC
  9. //
  10. // History: 7-13-95 Davepl Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "precomp.h"
  14. //
  15. // Default contstructor just invokes normal constructor, using the
  16. // current process' heap as the heap handle
  17. //
  18. CPtrArray::CPtrArray()
  19. {
  20. CPtrArray::CPtrArray(GetProcessHeap());
  21. }
  22. //
  23. // Constructor save a handle to the heap supplied to use for future
  24. // allocations
  25. //
  26. CPtrArray::CPtrArray(HANDLE hHeap)
  27. {
  28. m_hHeap = hHeap;
  29. m_pData = NULL;
  30. m_nSize = 0;
  31. m_nMaxSize = 0;
  32. m_nGrowBy = 0;
  33. }
  34. CPtrArray::~CPtrArray()
  35. {
  36. HeapFree(m_hHeap, 0, m_pData);
  37. }
  38. BOOL CPtrArray::SetSize(int nNewSize, int nGrowBy)
  39. {
  40. ASSERT(nNewSize >= 0);
  41. //
  42. // Set the new size
  43. //
  44. if (nGrowBy != -1)
  45. {
  46. m_nGrowBy = nGrowBy;
  47. }
  48. if (nNewSize == 0)
  49. {
  50. //
  51. // Shrink to nothing
  52. //
  53. VERIFY( HeapFree(m_hHeap, 0, m_pData) );
  54. m_pData = NULL;
  55. m_nSize = m_nMaxSize = 0;
  56. }
  57. else if (m_pData == NULL)
  58. {
  59. //
  60. // Data array doesn't exist yet, allocate it now
  61. //
  62. LPVOID * pnew = (LPVOID *) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, nNewSize * sizeof(void*));
  63. if (pnew)
  64. {
  65. m_pData = pnew;
  66. m_nSize = nNewSize;
  67. m_nMaxSize = nNewSize;
  68. }
  69. else
  70. {
  71. return FALSE;
  72. }
  73. }
  74. else if (nNewSize <= m_nMaxSize)
  75. {
  76. //
  77. // It fits
  78. //
  79. if (nNewSize > m_nSize)
  80. {
  81. // initialize the new elements
  82. ZeroMemory(&m_pData[m_nSize], (nNewSize-m_nSize) * sizeof(void*));
  83. }
  84. m_nSize = nNewSize;
  85. }
  86. else
  87. {
  88. //
  89. // It doesn't fit: grow the array
  90. //
  91. m_nGrowBy = nGrowBy; // BUGBUG verify this
  92. if (nGrowBy == 0)
  93. {
  94. //
  95. // Heuristically determine growth when nGrowBy == 0
  96. // (this avoids heap fragmentation in many situations)
  97. //
  98. nGrowBy = min(1024, max(4, m_nSize / 8));
  99. }
  100. int nNewMax;
  101. if (nNewSize < m_nMaxSize + nGrowBy)
  102. {
  103. nNewMax = m_nMaxSize + nGrowBy; // granularity
  104. }
  105. else
  106. {
  107. nNewMax = nNewSize; // no slush
  108. }
  109. ASSERT(nNewMax >= m_nMaxSize); // no wrap around
  110. LPVOID * pNewData = (LPVOID *) HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_pData, nNewMax * sizeof(void*));
  111. if (NULL == pNewData)
  112. {
  113. return FALSE;
  114. }
  115. ASSERT(nNewSize > m_nSize);
  116. m_pData = pNewData;
  117. m_nSize = nNewSize;
  118. m_nMaxSize = nNewMax;
  119. }
  120. return TRUE;
  121. }
  122. BOOL CPtrArray::FreeExtra()
  123. {
  124. if (m_nSize != m_nMaxSize)
  125. {
  126. //
  127. // shrink to desired size
  128. //
  129. void** pNewData = NULL;
  130. if (m_nSize != 0)
  131. {
  132. pNewData = (void**) HeapAlloc(m_hHeap, 0, m_nSize * sizeof(void*));
  133. ASSERT(pNewData);
  134. if (NULL == pNewData)
  135. {
  136. return FALSE;
  137. }
  138. //
  139. // copy new data from old
  140. //
  141. CopyMemory(pNewData, m_pData, m_nSize * sizeof(void*));
  142. }
  143. //
  144. // get rid of old stuff (note: no destructors called)
  145. //
  146. VERIFY( HeapFree(m_hHeap, 0, m_pData) );
  147. m_pData = pNewData;
  148. m_nMaxSize = m_nSize;
  149. }
  150. return TRUE;
  151. }
  152. BOOL CPtrArray::InsertAt(int nIndex, void* newElement, int nCount)
  153. {
  154. ASSERT(nIndex >= 0); // will expand to meet need
  155. ASSERT(nCount > 0); // zero or negative size not allowed
  156. if (nIndex >= m_nSize)
  157. {
  158. //
  159. // adding after the end of the array
  160. //
  161. if (FALSE == SetSize(nIndex + nCount)) // grow so nIndex is valid
  162. {
  163. return FALSE;
  164. }
  165. }
  166. else
  167. {
  168. //
  169. // inserting in the middle of the array
  170. //
  171. int nOldSize = m_nSize;
  172. if (FALSE == SetSize(m_nSize + nCount)) // grow it to new size
  173. {
  174. return FALSE;
  175. }
  176. //
  177. // shift old data up to fill gap
  178. //
  179. MoveMemory(&m_pData[nIndex+nCount], &m_pData[nIndex], (nOldSize-nIndex) * sizeof(void*));
  180. // re-init slots we copied from
  181. ZeroMemory(&m_pData[nIndex], nCount * sizeof(void*));
  182. }
  183. // insert new value in the gap
  184. ASSERT(nIndex + nCount <= m_nSize);
  185. while (nCount--)
  186. {
  187. m_pData[nIndex++] = newElement;
  188. }
  189. return TRUE;
  190. }
  191. BOOL CPtrArray::InsertAt(int nStartIndex, CPtrArray* pNewArray)
  192. {
  193. ASSERT(pNewArray != NULL);
  194. ASSERT(nStartIndex >= 0);
  195. if (pNewArray->GetSize() > 0)
  196. {
  197. if (FALSE == InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize()))
  198. {
  199. return FALSE;
  200. }
  201. for (int i = 0; i < pNewArray->GetSize(); i++)
  202. {
  203. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  204. }
  205. }
  206. return TRUE;
  207. }