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.

298 lines
8.0 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1998-1999 by Microsoft Corp.
  4. //
  5. // FLEXARRY.CPP
  6. //
  7. // CFlexArray implementation (non-arena).
  8. //
  9. // 15-Jul-97 raymcc Created.
  10. // 8-Jun-98 bobw cleaned up for WBEMPERF usage
  11. //
  12. //***************************************************************************
  13. #include "wpheader.h"
  14. #include <stdio.h>
  15. //***************************************************************************
  16. //
  17. // CFlexArray::CFlexArray
  18. //
  19. // Constructs the array.
  20. //
  21. // Parameters:
  22. // <nSize> The starting preallocated size of the array.
  23. // <nGrowBy> The amount to grow by when the array fills up.
  24. //
  25. // Size() returns the number of elements in use, not the 'true' size.
  26. //
  27. //***************************************************************************
  28. // ok
  29. CFlexArray::CFlexArray(
  30. int nSize,
  31. int nGrowBy
  32. )
  33. {
  34. m_nExtent = nSize;
  35. m_nSize = 0;
  36. m_nGrowBy = nGrowBy;
  37. m_hHeap = GetProcessHeap(); // call this once and save heap handle locally
  38. m_pArray = (void **) ALLOCMEM(m_hHeap, HEAP_ZERO_MEMORY, sizeof(void *) * nSize);
  39. assert (m_pArray != NULL);
  40. }
  41. //***************************************************************************
  42. //
  43. // CFlexArray::~CFlexArray
  44. //
  45. //***************************************************************************
  46. // ok
  47. CFlexArray::~CFlexArray()
  48. {
  49. FREEMEM(m_hHeap, 0, m_pArray);
  50. }
  51. //***************************************************************************
  52. //
  53. // Copy constructor.
  54. //
  55. // Copies the pointers, not their contents.
  56. //
  57. //***************************************************************************
  58. // ok
  59. CFlexArray::CFlexArray(CFlexArray &Src)
  60. {
  61. m_pArray = 0;
  62. m_nSize = 0;
  63. m_nExtent = 0;
  64. m_nGrowBy = 0;
  65. *this = Src;
  66. }
  67. //***************************************************************************
  68. //
  69. // operator =
  70. //
  71. // Assignment operator.
  72. //
  73. // Arenas are not copied. This allows transfer of arrays between arenas.
  74. // Arrays are copied by pointer only.
  75. //
  76. //***************************************************************************
  77. // ok
  78. CFlexArray& CFlexArray::operator=(CFlexArray &Src)
  79. {
  80. m_nSize = Src.m_nSize;
  81. m_nExtent = Src.m_nExtent;
  82. m_nGrowBy = Src.m_nGrowBy;
  83. FREEMEM (m_hHeap, 0, m_pArray);
  84. m_pArray = (void **) ALLOCMEM(m_hHeap, HEAP_ZERO_MEMORY, sizeof(void *) * m_nExtent);
  85. if (m_pArray) {
  86. memcpy(m_pArray, Src.m_pArray, sizeof(void *) * m_nExtent);
  87. }
  88. return *this;
  89. }
  90. //***************************************************************************
  91. //
  92. // CFlexArray::RemoveAt
  93. //
  94. // Removes the element at the specified location. Does not
  95. // actually delete the pointer. Shrinks the array over the top of
  96. // the 'doomed' element.
  97. //
  98. // Parameters:
  99. // <nIndex> The location of the element.
  100. //
  101. // Return value:
  102. // range_error The index is not legal.
  103. // no_error Success.
  104. //
  105. //***************************************************************************
  106. // ok
  107. int CFlexArray::RemoveAt(int nIndex)
  108. {
  109. int i;
  110. if (nIndex >= m_nSize) {
  111. return range_error;
  112. }
  113. for (i = nIndex; i < m_nSize - 1; i++) {
  114. m_pArray[i] = m_pArray[i + 1];
  115. }
  116. m_nSize--;
  117. m_pArray[m_nSize] = 0;
  118. return no_error;
  119. }
  120. //***************************************************************************
  121. //
  122. // CFlexArray::InsertAt
  123. //
  124. // Inserts a new element at the specified location. The pointer is copied.
  125. //
  126. // Parameters:
  127. // <nIndex> The 0-origin location at which to insert the new element.
  128. // <pSrc> The pointer to copy. (contents are not copied).
  129. //
  130. // Return value:
  131. // array_full
  132. // out_of_memory
  133. // no_error
  134. //
  135. //***************************************************************************
  136. // ok
  137. int CFlexArray::InsertAt(int nIndex, void *pSrc)
  138. {
  139. void **pTmp; // pointer to new array
  140. int nReturn = no_error;
  141. LONG lOldSize;
  142. LONG lNewSize;
  143. // If the array is full, we need to expand it.
  144. // ===========================================
  145. if (m_nSize == m_nExtent) {
  146. if (m_nGrowBy == 0) {
  147. nReturn = array_full;
  148. } else {
  149. // compute sizes
  150. lOldSize = sizeof(void *) * m_nExtent;
  151. m_nExtent += m_nGrowBy;
  152. lNewSize = sizeof(void *) * m_nExtent;
  153. // allocate new array
  154. pTmp = (void **) ALLOCMEM(m_hHeap, HEAP_ZERO_MEMORY, lNewSize);
  155. if (!pTmp) {
  156. nReturn = out_of_memory;
  157. } else {
  158. // move bits from old array to new array
  159. memcpy (pTmp, m_pArray, lOldSize);
  160. // toss old arrya
  161. FREEMEM (m_hHeap, 0, m_pArray);
  162. // save pointer to new array
  163. m_pArray = pTmp;
  164. }
  165. }
  166. }
  167. // Special case of appending. This is so frequent
  168. // compared to true insertion that we want to optimize.
  169. // ====================================================
  170. if (nReturn == no_error) {
  171. if (nIndex == m_nSize) {
  172. m_pArray[m_nSize++] = pSrc;
  173. } else {
  174. // If here, we are inserting at some random location.
  175. // We start at the end of the array and copy all the elements
  176. // one position farther to the end to make a 'hole' for
  177. // the new element.
  178. // ==========================================================
  179. for (int i = m_nSize; i > nIndex; i--) {
  180. m_pArray[i] = m_pArray[i - 1];
  181. }
  182. m_pArray[nIndex] = pSrc;
  183. m_nSize++;
  184. }
  185. }
  186. return nReturn;
  187. }
  188. //***************************************************************************
  189. //
  190. // CFlexArray::DebugDump
  191. //
  192. //***************************************************************************
  193. //
  194. void CFlexArray::DebugDump()
  195. {
  196. printf("----CFlexArray Debug Dump----\n");
  197. printf("m_pArray = 0x%p\n", m_pArray);
  198. printf("m_nSize = %d\n", m_nSize);
  199. printf("m_nExtent = %d\n", m_nExtent);
  200. printf("m_nGrowBy = %d\n", m_nGrowBy);
  201. for (int i = 0; i < m_nExtent; i++)
  202. {
  203. if (i < m_nSize) {
  204. printf("![%d] = %p\n", i, m_pArray[i]);
  205. } else {
  206. printf("?[%d] = %p\n", i, m_pArray[i]);
  207. }
  208. }
  209. }
  210. //***************************************************************************
  211. //
  212. // CFlexArray::Compress
  213. //
  214. // Removes NULL elements by moving all non-NULL pointers to the beginning
  215. // of the array. The array "Size" changes, but the extent is untouched.
  216. //
  217. //***************************************************************************
  218. // ok
  219. void CFlexArray::Compress()
  220. {
  221. int nLeftCursor = 0, nRightCursor = 0;
  222. while (nLeftCursor < m_nSize - 1) {
  223. if (m_pArray[nLeftCursor]) {
  224. nLeftCursor++;
  225. continue;
  226. }
  227. else {
  228. nRightCursor = nLeftCursor + 1;
  229. while (m_pArray[nRightCursor] == 0 && nRightCursor < m_nSize)
  230. nRightCursor++;
  231. if (nRightCursor == m_nSize)
  232. break; // Short circuit, no more nonzero elements.
  233. m_pArray[nLeftCursor] = m_pArray[nRightCursor];
  234. m_pArray[nRightCursor] = 0;
  235. }
  236. }
  237. while (m_pArray[m_nSize - 1] == 0 && m_nSize > 0) m_nSize--;
  238. }
  239. //***************************************************************************
  240. //
  241. // CFlexArray::Empty
  242. //
  243. // Clears the array of all pointers (does not deallocate them) and sets
  244. // its apparent size to zero.
  245. //
  246. //***************************************************************************
  247. // ok
  248. void CFlexArray::Empty()
  249. {
  250. FREEMEM(m_hHeap, 0, m_pArray);
  251. m_pArray = (void **) ALLOCMEM(m_hHeap, HEAP_ZERO_MEMORY, sizeof(void *) * m_nGrowBy);
  252. m_nSize = 0;
  253. m_nExtent = m_nGrowBy;
  254. }
  255. //***************************************************************************
  256. //
  257. // CFlexArray::UnbindPtr
  258. //
  259. // Empties the array and returns the pointer to the data it contained
  260. //
  261. //***************************************************************************
  262. void** CFlexArray::UnbindPtr()
  263. {
  264. void** pp = m_pArray;
  265. Empty();
  266. return pp;
  267. }