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.

300 lines
8.0 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * dynarray.hpp
  8. *
  9. * Abstract:
  10. *
  11. * Dynamic array template classes. See DynamicArrays.doc in the Specs
  12. * directory.
  13. *
  14. * DynArray is a container which keeps its contents in a contiguous buffer,
  15. * reallocating memory as necessary. It accepts an optional initial
  16. * allocation, which is used unless it is too small to accommodate the
  17. * elements.
  18. *
  19. * DynArrayIA is a cosmetic wrapper which encapsulates the intial allocation,
  20. * allowing the dynamic array to be treated like a normal class.
  21. *
  22. * Revision History:
  23. *
  24. * 12/02/1998 davidx
  25. * Created it.
  26. * 02/26/1999 agodfrey
  27. * Revamped it to use an implementation class (DynArrayImpl).
  28. * Now the template part of it can compile to nothing, or be small enough
  29. * to inline efficiently, so that using the template with many different
  30. * types doesn't cause code bloat.
  31. *
  32. * Also, I added a version (DynArrayIA) which makes using an initial
  33. * allocation much easier.
  34. *
  35. * 06/10/1999 t-wehunt
  36. * Added AddXXAt, DeletXXAt, and InsertAt methods.
  37. *
  38. * Notes:
  39. *
  40. * 12/02/1998 davidx
  41. * Changes from the previous version in gdiplus prototype:
  42. * + getData: Use &dynarr[index] instead.
  43. * + increaseCount: Use addMultiple instead (2nd variation).
  44. * + replace: Use dynarr[index] = newItem.
  45. * + attachData: Use dynarr.replaceWith(dynarr2).
  46. * + constructor: No longer takes initialCapacity, use ReserveSpace instead
  47. * + new constructor: Takes a stack array which is used for buffer (faster).
  48. *
  49. * 02/26/1999 agodfrey
  50. * + Use the 'implementation class' to avoid code bloat for out-of-line
  51. * functions.
  52. * + GetCapacity: Unused, not useful - removed.
  53. * + Reset: Added 'shrink' flag (default true). If it's false, Reset sets the
  54. * count to zero but doesn't free the memory. This is preferable to
  55. * SetCount(0).
  56. * + Made ShrinkToSize() reuse the initial allocation. This also makes the
  57. * growing and shrinking logic simpler - 'no initial allocation' is treated
  58. * like an initial allocation of size zero (at memory location 'NULL').
  59. *
  60. * 06/10/1999 t-wehunt
  61. * + AddXXAt, DeletXXAt, and InsertAt methods shift elements around in memory
  62. * to keep the array contiguous.
  63. * + CAUTION: This could cause a big performance hit if the array is very large.
  64. * Use care when calling these methods!!!
  65. *
  66. \**************************************************************************/
  67. #ifndef _DYNARRAY_HPP
  68. #define _DYNARRAY_HPP
  69. #include "dynArrayImpl.hpp"
  70. template <class T> class DynArray : public DynArrayImpl
  71. {
  72. public:
  73. // Constructor
  74. //
  75. // initalAllocation - the initial allocation, which can be global,
  76. // static or dynamic memory (or NULL)
  77. // allocSize - size of the initial allocation
  78. // (0 if there is none)
  79. // count - the initial count
  80. //
  81. DynArray(
  82. T *initialAllocation,
  83. UINT allocSize,
  84. UINT count = 0):
  85. DynArrayImpl(initialAllocation, allocSize, count)
  86. {
  87. }
  88. // Constructor (no initial allocation)
  89. //
  90. DynArray(void):
  91. DynArrayImpl(NULL, 0, 0)
  92. {
  93. }
  94. // Destructor
  95. ~DynArray()
  96. {
  97. if (DataBuffer != InitialAllocation)
  98. {
  99. GpFree(DataBuffer);
  100. }
  101. }
  102. // Return a pointer to the array data
  103. // NOTE: We intentionally avoid type conversion operator here
  104. // to reduce the chances for confusion.
  105. T *GetDataBuffer() const
  106. {
  107. return static_cast<T *>(DataBuffer);
  108. }
  109. // Index operator
  110. T &operator[](INT n) const
  111. {
  112. ASSERT(n >= 0 && (UINT)n < Count);
  113. return GetDataBuffer()[n];
  114. }
  115. // First/last element of the array
  116. T &First() const
  117. {
  118. ASSERT(Count > 0);
  119. return GetDataBuffer()[0];
  120. }
  121. T &Last() const
  122. {
  123. ASSERT(Count > 0);
  124. return GetDataBuffer()[Count-1];
  125. }
  126. // Number of elements in the array
  127. INT GetCount() const
  128. {
  129. return Count;
  130. }
  131. UINT GetCapacity() const
  132. {
  133. return Capacity;
  134. }
  135. // Reset the dynamic array to empty state
  136. //
  137. // shrink - If FALSE, don't free the current buffer.
  138. VOID Reset(BOOL shrink=TRUE)
  139. {
  140. Count = 0;
  141. if (shrink)
  142. {
  143. ShrinkToSize();
  144. }
  145. }
  146. // Shrink the dynamic array capacity to be just big enough
  147. // for the number of existing elements in the array.
  148. //
  149. // This reuses the initial allocation if possible.
  150. VOID ShrinkToSize()
  151. {
  152. DynArrayImpl::ShrinkToSize(sizeof(T));
  153. }
  154. // Add a new element to the end of the dynamic array
  155. GpStatus Add(const T& newItem)
  156. {
  157. return DynArrayImpl::AddMultiple(sizeof(T), 1, &newItem);
  158. }
  159. // Add multiple items to the end of the dynamic array
  160. GpStatus AddMultiple(const T* newItems, INT n)
  161. {
  162. return DynArrayImpl::AddMultiple(sizeof(T), n, newItems);
  163. }
  164. // Another variation of addMultiple above
  165. //
  166. // In this case, the data for the new elements are
  167. // not available. Instead, we'll do the following:
  168. // (1) reserve the space for additional elements
  169. // (2) increase the Count by the number of additional elements
  170. // (3) return a pointer to the first new elements
  171. T *AddMultiple(INT n)
  172. {
  173. return static_cast<T *>(DynArrayImpl::AddMultiple(sizeof(T), n));
  174. }
  175. // Detach the data buffer from the dynamic array
  176. // Allocates the buffer to detatch if it is the initial allocation.
  177. GpStatus DetachData(T **buffer)
  178. {
  179. return DynArrayImpl::DetachData(sizeof(T), (void **)buffer);
  180. }
  181. // Detatch the buffer from another array, and set this array
  182. // to point to it. NOTE: This modifies the other array.
  183. GpStatus ReplaceWith(DynArray<T> *dynarr)
  184. {
  185. if (DataBuffer != InitialAllocation)
  186. {
  187. GpFree(DataBuffer);
  188. }
  189. Count = dynarr->Count;
  190. Capacity = dynarr->Capacity;
  191. GpStatus status = dynarr->DetachData((T**)(&DataBuffer));
  192. if(Ok != status)
  193. {
  194. Count = 0;
  195. Capacity = 0;
  196. }
  197. return status;
  198. }
  199. // More dangerous interface:
  200. //
  201. // These functions are alternatives to Add/AddMultiple.
  202. // They can be used to reduce overhead, but you have to know what
  203. // you're doing.
  204. //
  205. // AdjustCount/SetCount - modify the count directly, without growing or
  206. // shrinking the array.
  207. // ReserveSpace - grow the buffer, but don't actually add any elements to
  208. // the array.
  209. VOID AdjustCount(UINT addElts)
  210. {
  211. Count += addElts;
  212. ASSERT(Count <= Capacity);
  213. }
  214. VOID SetCount(UINT count)
  215. {
  216. ASSERT(Count <= Capacity);
  217. Count = count;
  218. }
  219. GpStatus ReserveSpace(UINT newElements, BOOL exact = FALSE)
  220. {
  221. return Grow(sizeof(T), newElements, exact);
  222. }
  223. };
  224. // DynArrayIA: A version of DynArray which encapsulates the initial allocation.
  225. //
  226. // For example:
  227. //
  228. // DynArrayIA<MyType, 10> array;
  229. //
  230. // This declares a DynArray of MyType objects, with an initial allocation of
  231. // 10 elements. Such a declaration can be used on the stack or in another
  232. // object.
  233. template <class T, int ALLOCSIZE> class DynArrayIA : public DynArray<T>
  234. {
  235. public:
  236. // Constructor
  237. //
  238. DynArrayIA(void):
  239. DynArray<T>(InitialAllocationBuffer, ALLOCSIZE, 0)
  240. {
  241. }
  242. DynArrayIA(T * initialAllocationBuffer, UINT initialAllocationSize, UINT count = 0) :
  243. DynArray<T>(initialAllocationBuffer, initialAllocationSize, count)
  244. {
  245. }
  246. private:
  247. T InitialAllocationBuffer[ALLOCSIZE];
  248. };
  249. #endif // !_DYNARRAY_HPP