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.

494 lines
12 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. * 6/10/1999 t-wehunt
  19. * + Added AddMultipleAt and DeleteMultipleAt methods.
  20. * + Fixed a problem in ShrinkToSize that caused elements to potentially
  21. * be lost.
  22. * 8/16/2000 bhouse
  23. * + Changed cpacity growth to be exponential
  24. *
  25. \**************************************************************************/
  26. #include "precomp.hpp"
  27. /**************************************************************************\
  28. *
  29. * Function Description:
  30. *
  31. * DynArrayImpl constructor
  32. *
  33. * Arguments:
  34. *
  35. * initialAllocation - initial allocation, or NULL
  36. * allocSize - size of the initial allocation
  37. * count - initial count
  38. *
  39. * Return Value:
  40. *
  41. * NONE
  42. *
  43. * Created:
  44. *
  45. * 2/25/1999 agodfrey
  46. *
  47. \**************************************************************************/
  48. DynArrayImpl::DynArrayImpl(
  49. void *initialAllocation,
  50. UINT allocSize,
  51. UINT count
  52. )
  53. {
  54. ASSERT((initialAllocation != NULL) || (allocSize == 0));
  55. ASSERT(count <= allocSize);
  56. DataBuffer = InitialAllocation = initialAllocation;
  57. Capacity = AllocSize = allocSize;
  58. Count = count;
  59. }
  60. /**************************************************************************\
  61. *
  62. * Function Description:
  63. *
  64. * Shrink the buffer so that it is just big enough for the items
  65. * the dynamic array holds.
  66. *
  67. * Arguments:
  68. *
  69. * eltSize - size of each array element
  70. *
  71. * Return Value:
  72. *
  73. * NONE
  74. *
  75. * Created:
  76. *
  77. * 1/18/1999 agodfrey
  78. * Added code to reuse the initial allocation.
  79. *
  80. \**************************************************************************/
  81. VOID DynArrayImpl::ShrinkToSize(UINT eltSize)
  82. {
  83. ASSERT(Count <= Capacity);
  84. if (DataBuffer == InitialAllocation)
  85. {
  86. // Since we're shrinking, we know that the current data buffer
  87. // is big enough.
  88. return;
  89. }
  90. if (Count <= AllocSize)
  91. {
  92. // The buffer will fit into the initial allocation.
  93. GpMemcpy(InitialAllocation,DataBuffer,Count * eltSize);
  94. GpFree(DataBuffer);
  95. DataBuffer = InitialAllocation;
  96. Capacity = AllocSize;
  97. return;
  98. }
  99. // If we get here, we know that DataBuffer points to dynamic memory,
  100. // and that Count != 0.
  101. //
  102. // The second point is important because GpRealloc(x, 0) returns
  103. // a pointer to a valid zero-length buffer.
  104. void *newbuf = GpRealloc(DataBuffer, Count*eltSize);
  105. if (!newbuf)
  106. {
  107. // GpRealloc failed. Keep the current allocation
  108. WARNING(("ShrinkToSize: GpRealloc failed"));
  109. return;
  110. }
  111. DataBuffer = newbuf;
  112. Capacity = Count;
  113. }
  114. /**************************************************************************\
  115. *
  116. * Function Description:
  117. *
  118. * Add space for new elements (if necessary). Does not update Count.
  119. *
  120. * Arguments:
  121. *
  122. * eltSize - size of each array element
  123. * newElements - the number of new elements
  124. * exactSize - no exponential growth, just add required amount
  125. *
  126. * Return Value:
  127. *
  128. * GpStatus - Ok or failure status
  129. *
  130. * Created:
  131. *
  132. * 1/18/1999 agodfrey
  133. *
  134. \**************************************************************************/
  135. GpStatus DynArrayImpl::Grow(UINT eltSize, UINT newElements, BOOL exactSize)
  136. {
  137. UINT newCount = Count + newElements;
  138. if (newCount <= Capacity)
  139. {
  140. return Ok;
  141. }
  142. UINT capacityIncrement = newCount - Capacity;
  143. if (!exactSize)
  144. {
  145. capacityIncrement = max(capacityIncrement,
  146. min(max(Capacity, kMinCapacityGrowth),
  147. kMaxCapacityGrowth));
  148. };
  149. UINT newCapacity = Capacity + capacityIncrement;
  150. void *newbuf;
  151. if (DataBuffer == InitialAllocation)
  152. {
  153. // Do our first dynamic allocation
  154. newbuf = GpMalloc(newCapacity*eltSize);
  155. if (newbuf && Count)
  156. {
  157. GpMemcpy(newbuf, DataBuffer, Count*eltSize);
  158. }
  159. }
  160. else
  161. {
  162. // Reallocate memory
  163. newbuf = GpRealloc(DataBuffer, newCapacity*eltSize);
  164. }
  165. if (!newbuf)
  166. {
  167. WARNING(("Grow: alloc failed"));
  168. // Aid in tracking down memory failure cases not handled properly
  169. #if 0
  170. ASSERT(FALSE);
  171. #endif
  172. return OutOfMemory;
  173. }
  174. Capacity = newCapacity;
  175. DataBuffer = newbuf;
  176. return Ok;
  177. }
  178. /**************************************************************************\
  179. *
  180. * Function Description:
  181. *
  182. * Detach the data buffer from the dynamic array.
  183. * Allocates the buffer to detatch if it is the initial allocation.
  184. *
  185. * Return Value:
  186. *
  187. * The data buffer
  188. *
  189. * Created:
  190. *
  191. * 2/25/1999 agodfrey
  192. * 12/19/2000 asecchia - handle initial allocation by returning a copy.
  193. *
  194. \**************************************************************************/
  195. GpStatus DynArrayImpl::DetachData(UINT eltSize, void **buffer)
  196. {
  197. void *data = DataBuffer;
  198. // Copy the initial allocation if there is one -
  199. // otherwise we simply use the DataBuffer.
  200. if (DataBuffer == InitialAllocation)
  201. {
  202. data = GpMalloc(Capacity*eltSize);
  203. if (NULL == data)
  204. {
  205. *buffer = NULL;
  206. return OutOfMemory;
  207. }
  208. if (Count)
  209. {
  210. GpMemcpy(data, DataBuffer, Count*eltSize);
  211. }
  212. }
  213. DataBuffer = NULL;
  214. Count = Capacity = 0;
  215. *buffer = data;
  216. return Ok;
  217. }
  218. /**************************************************************************\
  219. *
  220. * Function Description:
  221. *
  222. * Add new, uninitialized elements, and return a pointer to them.
  223. *
  224. * Arguments:
  225. *
  226. * eltSize - size of each element
  227. * newElements - number of new elements
  228. *
  229. * Return Value:
  230. *
  231. * Pointer to the new space, or NULL on failure
  232. *
  233. * Created:
  234. *
  235. * 2/25/1999 agodfrey
  236. *
  237. \**************************************************************************/
  238. void *DynArrayImpl::AddMultiple(UINT eltSize, UINT newElements)
  239. {
  240. ASSERT(newElements>0);
  241. if (Grow(eltSize, newElements) != Ok)
  242. return NULL;
  243. void *newSpace = static_cast<BYTE *>(DataBuffer) + Count * eltSize;
  244. Count += newElements;
  245. return newSpace;
  246. }
  247. /**************************************************************************\
  248. *
  249. * Function Description:
  250. *
  251. * Add new elements, initializing them with the given data.
  252. *
  253. * Arguments:
  254. *
  255. * eltSize - size of each element
  256. * newElements - number of new elements
  257. * newData - the data to be copied into the new space
  258. *
  259. * Return Value:
  260. *
  261. * GpStatus - Ok or failure status
  262. *
  263. * Created:
  264. *
  265. * 2/25/1999 agodfrey
  266. *
  267. \**************************************************************************/
  268. GpStatus DynArrayImpl::AddMultiple(
  269. UINT eltSize,
  270. UINT newElements,
  271. const void *newData
  272. )
  273. {
  274. ASSERT(newElements>0);
  275. GpStatus status = Grow(eltSize, newElements);
  276. if (status == Ok)
  277. {
  278. // NOTE: assume T is a shallow data type, i.e.
  279. // it doesn't contain nested references.
  280. GpMemcpy(
  281. static_cast<BYTE *>(DataBuffer) + Count * eltSize,
  282. newData,
  283. newElements * eltSize
  284. );
  285. Count += newElements;
  286. }
  287. return status;
  288. }
  289. #ifdef USE_OBSOLETE_DYNSORTARRAY
  290. /**************************************************************************\
  291. *
  292. * Function Description:
  293. *
  294. * Add new, uninitialized elements, and return a pointer to them.
  295. * All data from index on is shift towards the end of the array to make room.
  296. * CAUTION! could cause a big performance hit if the array is large!
  297. *
  298. * Arguments:
  299. *
  300. * eltSize - size of each element
  301. * index - index from which to insert the new elements.
  302. * newElements - number of new elements
  303. *
  304. * Return Value:
  305. *
  306. * Pointer to the new space, or NULL on failure
  307. *
  308. * Created:
  309. *
  310. * 6/10/1999 t-wehunt
  311. *
  312. \**************************************************************************/
  313. void *DynArrayImpl::AddMultipleAt(
  314. UINT eltSize,
  315. UINT index,
  316. UINT newElements
  317. )
  318. {
  319. ASSERT(newElements>0 && index<=Count);
  320. if (Grow(eltSize, newElements) != Ok)
  321. return NULL;
  322. // NOTE: assume T is a shallow data type, i.e.
  323. // it doesn't contain nested references.
  324. GpMemmove(
  325. static_cast<BYTE *>(DataBuffer) + (index + newElements) * eltSize,
  326. static_cast<BYTE *>(DataBuffer) + index * eltSize,
  327. (Count - index) * eltSize
  328. );
  329. void *newSpace = static_cast<BYTE *>(DataBuffer) + index * eltSize;
  330. Count += newElements;
  331. return newSpace;
  332. }
  333. /**************************************************************************\
  334. *
  335. * Function Description:
  336. *
  337. * Add new elements, initializing them with the given data.
  338. * All data from index on is shift towards the end of the array to make room.
  339. * CAUTION! could cause a big performance hit if the array is large!
  340. *
  341. * Arguments:
  342. *
  343. * eltSize - size of each element
  344. * index - index from which to insert the new elements.
  345. * newElements - number of new elements
  346. * newData - the data to be copied into the new space
  347. *
  348. * Return Value:
  349. *
  350. * GpStatus - Ok or failure status
  351. *
  352. * Created:
  353. *
  354. * 6/10/1999 t-wehunt
  355. *
  356. \**************************************************************************/
  357. GpStatus DynArrayImpl::AddMultipleAt(
  358. UINT eltSize,
  359. UINT index,
  360. UINT newElements,
  361. const void *newData
  362. )
  363. {
  364. ASSERT(newElements>0 && index<=Count);
  365. GpStatus status = Grow(eltSize, newElements);
  366. if (status == Ok)
  367. {
  368. // NOTE: assume T is a shallow data type, i.e.
  369. // it doesn't contain nested references.
  370. GpMemmove(
  371. static_cast<BYTE *>(DataBuffer) + (index + newElements) * eltSize,
  372. static_cast<BYTE *>(DataBuffer) + index * eltSize,
  373. (Count - index) * eltSize
  374. );
  375. GpMemcpy(
  376. static_cast<BYTE *>(DataBuffer) + index * eltSize,
  377. newData,
  378. newElements * eltSize
  379. );
  380. Count += newElements;
  381. }
  382. return status;
  383. }
  384. /**************************************************************************\
  385. *
  386. * Function Description:
  387. *
  388. * Deletes multiple items from the array starting at the index'th position.
  389. * CAUTION! could cause a big performance hit if the array is large!
  390. *
  391. * Arguments:
  392. *
  393. * eltSize - size of each element
  394. * index - index from which to delete the elements.
  395. * numElements - number of elements to delete
  396. *
  397. * Return Value:
  398. *
  399. * GpStatus - Ok or failure status
  400. *
  401. * Created:
  402. *
  403. * 6/10/1999 t-wehunt
  404. *
  405. \**************************************************************************/
  406. GpStatus DynArrayImpl::DeleteMultipleAt(
  407. UINT eltSize,
  408. UINT index,
  409. UINT numElements
  410. )
  411. {
  412. ASSERT(numElements>0 && (index+numElements)<=Count);
  413. GpMemmove(
  414. static_cast<BYTE *>(DataBuffer) + index * eltSize,
  415. static_cast<BYTE *>(DataBuffer) + (index + numElements) * eltSize,
  416. (Count - (index + numElements)) * eltSize
  417. );
  418. Count -= numElements;
  419. ShrinkToSize(eltSize);
  420. return Ok;
  421. }
  422. #endif