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.

267 lines
5.5 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 ( -1 == nGrowBy )
  49. {
  50. nGrowBy = m_nGrowBy;
  51. }
  52. if (nNewSize == 0)
  53. {
  54. //
  55. // Shrink to nothing
  56. //
  57. HeapFree(m_hHeap, 0, m_pData);
  58. m_pData = NULL;
  59. m_nSize = m_nMaxSize = 0;
  60. }
  61. else if (m_pData == NULL)
  62. {
  63. //
  64. // Data array doesn't exist yet, allocate it now
  65. //
  66. LPVOID * pnew = (LPVOID *) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, nNewSize * sizeof(*m_pData));
  67. if (pnew)
  68. {
  69. m_pData = pnew;
  70. m_nSize = nNewSize;
  71. m_nMaxSize = nNewSize;
  72. }
  73. else
  74. {
  75. return FALSE;
  76. }
  77. }
  78. else if (nNewSize <= m_nMaxSize)
  79. {
  80. //
  81. // It fits
  82. //
  83. if (nNewSize > m_nSize)
  84. {
  85. // initialize the new elements
  86. ZeroMemory(&m_pData[m_nSize], (nNewSize-m_nSize) * sizeof(*m_pData));
  87. }
  88. m_nSize = nNewSize;
  89. }
  90. else
  91. {
  92. Assert( -1 != nGrowBy );
  93. //
  94. // It doesn't fit: grow the array
  95. //
  96. m_nGrowBy = nGrowBy;
  97. if (nGrowBy == 0)
  98. {
  99. //
  100. // Heuristically determine growth when nGrowBy == 0
  101. // (this avoids heap fragmentation in many situations)
  102. //
  103. nGrowBy = min(1024, max(4, m_nSize / 8));
  104. }
  105. int nNewMax;
  106. if (nNewSize < m_nMaxSize + nGrowBy)
  107. {
  108. nNewMax = m_nMaxSize + nGrowBy; // granularity
  109. }
  110. else
  111. {
  112. nNewMax = nNewSize; // no slush
  113. }
  114. ASSERT(nNewMax >= m_nMaxSize); // no wrap around
  115. LPVOID * pNewData = (LPVOID *) HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_pData, nNewMax * sizeof(*m_pData));
  116. if (NULL == pNewData)
  117. {
  118. return FALSE;
  119. }
  120. ASSERT(nNewSize > m_nSize);
  121. m_pData = pNewData;
  122. m_nSize = nNewSize;
  123. m_nMaxSize = nNewMax;
  124. }
  125. return TRUE;
  126. }
  127. BOOL CPtrArray::FreeExtra()
  128. {
  129. if (m_nSize != m_nMaxSize)
  130. {
  131. //
  132. // shrink to desired size
  133. //
  134. void** pNewData = NULL;
  135. if (m_nSize != 0)
  136. {
  137. pNewData = (void**) HeapAlloc(m_hHeap, 0, m_nSize * sizeof(*m_pData));
  138. if (NULL == pNewData)
  139. {
  140. return FALSE;
  141. }
  142. //
  143. // copy new data from old
  144. //
  145. CopyMemory(pNewData, m_pData, m_nSize * sizeof(*m_pData));
  146. }
  147. //
  148. // get rid of old stuff (note: no destructors called)
  149. //
  150. HeapFree(m_hHeap, 0, m_pData);
  151. m_pData = pNewData;
  152. m_nMaxSize = m_nSize;
  153. }
  154. return TRUE;
  155. }
  156. BOOL CPtrArray::InsertAt(int nIndex, void* newElement, int nCount)
  157. {
  158. ASSERT(nIndex >= 0); // will expand to meet need
  159. ASSERT(nCount > 0); // zero or negative size not allowed
  160. if (nIndex >= m_nSize)
  161. {
  162. //
  163. // adding after the end of the array
  164. //
  165. if (FALSE == SetSize(nIndex + nCount)) // grow so nIndex is valid
  166. {
  167. return FALSE;
  168. }
  169. }
  170. else
  171. {
  172. //
  173. // inserting in the middle of the array
  174. //
  175. int nOldSize = m_nSize;
  176. if (FALSE == SetSize(m_nSize + nCount)) // grow it to new size
  177. {
  178. return FALSE;
  179. }
  180. //
  181. // shift old data up to fill gap
  182. //
  183. MoveMemory(&m_pData[nIndex+nCount], &m_pData[nIndex], (nOldSize-nIndex) * sizeof(*m_pData));
  184. // re-init slots we copied from
  185. ZeroMemory(&m_pData[nIndex], nCount * sizeof(*m_pData));
  186. }
  187. // insert new value in the gap
  188. ASSERT(nIndex + nCount <= m_nSize);
  189. while (nCount--)
  190. {
  191. m_pData[nIndex++] = newElement;
  192. }
  193. return TRUE;
  194. }
  195. BOOL CPtrArray::InsertAt(int nStartIndex, CPtrArray* pNewArray)
  196. {
  197. ASSERT(nStartIndex >= 0);
  198. if (pNewArray->GetSize() > 0)
  199. {
  200. if (FALSE == InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize()))
  201. {
  202. return FALSE;
  203. }
  204. for (int i = 0; i < pNewArray->GetSize(); i++)
  205. {
  206. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  207. }
  208. }
  209. return TRUE;
  210. }