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.

298 lines
6.5 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * Dynamic array implementation class
  8. *
  9. * Abstract:
  10. *
  11. * This is the class which implements the dynamic array.
  12. * It is used by the wrapper template classes DynArray and DynArrayIA.
  13. *
  14. * Created:
  15. *
  16. * 2/18/1999 agodfrey
  17. *
  18. \**************************************************************************/
  19. #include "gdiptest.h"
  20. /**************************************************************************\
  21. *
  22. * Function Description:
  23. *
  24. * DynArrayImpl constructor
  25. *
  26. * Arguments:
  27. *
  28. * initialAllocation - initial allocation, or NULL
  29. * allocSize - size of the initial allocation
  30. * stepSize - number of elements added each time the buffer grows
  31. *
  32. * Return Value:
  33. *
  34. * NONE
  35. *
  36. * Created:
  37. *
  38. * 2/25/1999 agodfrey
  39. *
  40. \**************************************************************************/
  41. DynArrayImpl::DynArrayImpl(
  42. void *initialAllocation,
  43. UINT allocSize,
  44. UINT stepSize
  45. )
  46. {
  47. ASSERT((initialAllocation != NULL) || (allocSize == 0));
  48. DataBuffer = InitialAllocation = initialAllocation;
  49. Capacity = AllocSize = allocSize;
  50. Count = 0;
  51. StepSize = stepSize;
  52. }
  53. /**************************************************************************\
  54. *
  55. * Function Description:
  56. *
  57. * Shrink the buffer so that it is just big enough for the items
  58. * the dynamic array holds.
  59. *
  60. * Arguments:
  61. *
  62. * eltSize - size of each array element
  63. *
  64. * Return Value:
  65. *
  66. * NONE
  67. *
  68. * Created:
  69. *
  70. * 1/18/1999 agodfrey
  71. * Added code to reuse the initial allocation.
  72. *
  73. \**************************************************************************/
  74. VOID DynArrayImpl::ShrinkToSize(UINT eltSize)
  75. {
  76. ASSERT(Count <= Capacity);
  77. if (DataBuffer == InitialAllocation)
  78. {
  79. // Since we're shrinking, we know that the current data buffer
  80. // is big enough.
  81. return;
  82. }
  83. if (Count <= AllocSize)
  84. {
  85. // The buffer will fit into the initial allocation.
  86. GpFree(DataBuffer);
  87. DataBuffer = InitialAllocation;
  88. Capacity = AllocSize;
  89. return;
  90. }
  91. // If we get here, we know that DataBuffer points to dynamic memory,
  92. // and that Count != 0.
  93. //
  94. // The second point is important because GpRealloc(x, 0) returns
  95. // a pointer to a valid zero-length buffer.
  96. void *newbuf = GpRealloc(DataBuffer, Count*eltSize);
  97. if (!newbuf)
  98. {
  99. // GpRealloc failed. Keep the current allocation
  100. WARNING(("ShrinkToSize: GpRealloc failed"));
  101. return;
  102. }
  103. DataBuffer = newbuf;
  104. Capacity = Count;
  105. }
  106. /**************************************************************************\
  107. *
  108. * Function Description:
  109. *
  110. * Add space for new elements (if necessary). Does not update Count.
  111. *
  112. * Arguments:
  113. *
  114. * eltSize - size of each array element
  115. * newElements - the number of new elements
  116. *
  117. * Return Value:
  118. *
  119. * GpStatus - Ok or failure status
  120. *
  121. * Created:
  122. *
  123. * 1/18/1999 agodfrey
  124. *
  125. \**************************************************************************/
  126. GpStatus DynArrayImpl::Grow(UINT eltSize, UINT newElements)
  127. {
  128. UINT newCount = Count + newElements;
  129. if (newCount <= Capacity)
  130. {
  131. return Ok;
  132. }
  133. ASSERT(newCount > 0);
  134. // Round up new capacity to be a multiple of allocation step size
  135. Capacity = StepSize * ((newCount + StepSize - 1) / StepSize);
  136. void *newbuf;
  137. if (DataBuffer == InitialAllocation)
  138. {
  139. // Do our first dynamic allocation
  140. newbuf = GpMalloc(Capacity*eltSize);
  141. if (newbuf && Count)
  142. {
  143. GpMemcpy(newbuf, DataBuffer, Count*eltSize);
  144. }
  145. }
  146. else
  147. {
  148. // Reallocate memory
  149. newbuf = GpRealloc(DataBuffer, Capacity*eltSize);
  150. }
  151. if (!newbuf)
  152. {
  153. WARNING(("Grow: alloc failed\n"));
  154. return OutOfMemory;
  155. }
  156. DataBuffer = newbuf;
  157. return Ok;
  158. }
  159. /**************************************************************************\
  160. *
  161. * Function Description:
  162. *
  163. * Detach the data buffer from the dynamic array.
  164. * Cannot be used if there is an initial allocation.
  165. *
  166. * Return Value:
  167. *
  168. * The data buffer
  169. *
  170. * Created:
  171. *
  172. * 2/25/1999 agodfrey
  173. *
  174. \**************************************************************************/
  175. void *DynArrayImpl::DetachData()
  176. {
  177. ASSERT(InitialAllocation == NULL);
  178. void *data = DataBuffer;
  179. DataBuffer = NULL;
  180. Count = Capacity = 0;
  181. return data;
  182. }
  183. /**************************************************************************\
  184. *
  185. * Function Description:
  186. *
  187. * Add new, uninitialized elements, and return a pointer to them.
  188. *
  189. * Arguments:
  190. *
  191. * eltSize - size of each element
  192. * newElements - number of new elements
  193. *
  194. * Return Value:
  195. *
  196. * Pointer to the new space, or NULL on failure
  197. *
  198. * Created:
  199. *
  200. * 2/25/1999 agodfrey
  201. *
  202. \**************************************************************************/
  203. void *DynArrayImpl::AddMultiple(UINT eltSize, UINT newElements)
  204. {
  205. ASSERT(newElements>0);
  206. if (Grow(eltSize, newElements) != Ok)
  207. return NULL;
  208. void *newSpace = static_cast<BYTE *>(DataBuffer) + Count * eltSize;
  209. Count += newElements;
  210. return newSpace;
  211. }
  212. /**************************************************************************\
  213. *
  214. * Function Description:
  215. *
  216. * Add new elements, initializing them with the given data.
  217. *
  218. * Arguments:
  219. *
  220. * eltSize - size of each element
  221. * newElements - number of new elements
  222. * newData - the data to be copied into the new space
  223. *
  224. * Return Value:
  225. *
  226. * GpStatus - Ok or failure status
  227. *
  228. * Created:
  229. *
  230. * 2/25/1999 agodfrey
  231. *
  232. \**************************************************************************/
  233. GpStatus DynArrayImpl::AddMultiple(
  234. UINT eltSize,
  235. UINT newElements,
  236. const void *newData
  237. )
  238. {
  239. ASSERT(newElements>0);
  240. GpStatus status = Grow(eltSize, newElements);
  241. if (status == Ok)
  242. {
  243. // NOTE: assume T is a shallow data type, i.e.
  244. // it doesn't contain nested references.
  245. GpMemcpy(
  246. static_cast<BYTE *>(DataBuffer) + Count * eltSize,
  247. newData,
  248. newElements * eltSize
  249. );
  250. Count += newElements;
  251. }
  252. return status;
  253. }