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.

532 lines
16 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: DynamicArray.cpp
  3. //
  4. // Copyright (c) 1999-2000, Microsoft Corporation
  5. //
  6. // This file contains related classes to manage dynamic arrays. The array is
  7. // grown as required but never shrunk. The base class handles struct arrays.
  8. // Subclasses handle special cases of these arrays (such as pointer or
  9. // CCountedObject arrays).
  10. //
  11. // History: 1999-11-16 vtan created
  12. // 2000-02-01 vtan moved from Neptune to Whistler
  13. // --------------------------------------------------------------------------
  14. #include "StandardHeader.h"
  15. #include "DynamicArray.h"
  16. #include "CountedObject.h"
  17. // --------------------------------------------------------------------------
  18. // CDynamicArray::CDynamicArray
  19. //
  20. // Arguments: iElementSize = Size of each array element.
  21. //
  22. // Returns: <none>
  23. //
  24. // Purpose: Constructor for CDynamicArray. Stores the element size and
  25. // initializes the memory used to NULL.
  26. //
  27. // History: 1999-11-16 vtan created
  28. // --------------------------------------------------------------------------
  29. CDynamicArray::CDynamicArray (int iElementSize) :
  30. _iElementSize(iElementSize),
  31. _iArraySize(0),
  32. _pvArray(NULL)
  33. {
  34. ASSERTMSG(iElementSize > 0, "Cannot have negative or zero length element size in CDynamicArray::CDynamicArray");
  35. }
  36. // --------------------------------------------------------------------------
  37. // CDynamicArray::~CDynamicArray
  38. //
  39. // Arguments: <none>
  40. //
  41. // Returns: <none>
  42. //
  43. // Purpose: Destructor for CDynamicArray. Frees the memory used by the
  44. // array.
  45. //
  46. // History: 1999-11-16 vtan created
  47. // --------------------------------------------------------------------------
  48. CDynamicArray::~CDynamicArray (void)
  49. {
  50. ReleaseMemory(_pvArray);
  51. }
  52. // --------------------------------------------------------------------------
  53. // CDynamicArray::Add
  54. //
  55. // Arguments: pvData = Pointer to the data to copy to the array.
  56. //
  57. // Returns: NTSTATUS
  58. //
  59. // Purpose: Allocates memory for the element to be added to the array. If
  60. // there is no memory block it allocates an initial block. If
  61. // there isn't enough memory in the block to hold the next
  62. // element then it allocates a new larger block.
  63. //
  64. // History: 1999-11-16 vtan created
  65. // --------------------------------------------------------------------------
  66. NTSTATUS CDynamicArray::Add (const void *pvData)
  67. {
  68. NTSTATUS status;
  69. static const int DEFAULT_ELEMENTS_PER_ALLOCATE = 16;
  70. status = STATUS_NO_MEMORY;
  71. // If no array exists then allocate the first
  72. // block of memory for this array.
  73. if (_pvArray == NULL)
  74. {
  75. _iArraySize = 0;
  76. _iArrayAllocatedSize = DEFAULT_ELEMENTS_PER_ALLOCATE;
  77. _pvArray = LocalAlloc(LPTR, _iElementSize * _iArrayAllocatedSize);
  78. }
  79. // If the array exists but the limit of the allocated size has
  80. // been reached then allocate a new block, copy the current
  81. // block contents and fall thru.
  82. if (_pvArray != NULL)
  83. {
  84. if (_iArraySize == _iArrayAllocatedSize)
  85. {
  86. void *pvNewArray;
  87. pvNewArray = LocalAlloc(LPTR, _iElementSize * (_iArrayAllocatedSize + DEFAULT_ELEMENTS_PER_ALLOCATE));
  88. if (pvNewArray != NULL)
  89. {
  90. _iArrayAllocatedSize += DEFAULT_ELEMENTS_PER_ALLOCATE;
  91. CopyMemory(pvNewArray, _pvArray, _iElementSize * _iArraySize);
  92. (HLOCAL)LocalFree(_pvArray);
  93. _pvArray = pvNewArray;
  94. }
  95. }
  96. // Otherwise there is a spare slot in the array. Copy the
  97. // data to the array. Increment the array size.
  98. if (_iArraySize < _iArrayAllocatedSize)
  99. {
  100. CopyMemory(static_cast<char*>(_pvArray) + (_iElementSize * _iArraySize), pvData, _iElementSize);
  101. ++_iArraySize;
  102. status = STATUS_SUCCESS;
  103. }
  104. }
  105. return(status);
  106. }
  107. // --------------------------------------------------------------------------
  108. // CDynamicArray::Remove
  109. //
  110. // Arguments: iElementIndex = Index of the element to remove.
  111. //
  112. // Returns: NTSTATUS
  113. //
  114. // Purpose: Removes the element from the array. Slides down all the
  115. // members but does not reduce the size of the memory block used
  116. // by the array.
  117. //
  118. // History: 1999-11-16 vtan created
  119. // --------------------------------------------------------------------------
  120. NTSTATUS CDynamicArray::Remove (int iElementIndex)
  121. {
  122. NTSTATUS status;
  123. status = STATUS_SUCCESS;
  124. if (_pvArray != NULL)
  125. {
  126. // Make sure the index is valid.
  127. if (iElementIndex < _iArraySize)
  128. {
  129. int iMoveSize;
  130. // Determine the amount of bytes to move when deleting this
  131. // element and move the memory. Don't resize the array when
  132. // shrinking. Just leave it alone.
  133. iMoveSize = _iElementSize * (_iArraySize - iElementIndex - 1);
  134. ASSERTMSG(iMoveSize >= 0, "Negative move memory size in CDynamicArray::Remove");
  135. if (iMoveSize > 0)
  136. {
  137. MoveMemory(static_cast<char*>(_pvArray) + (_iElementSize * iElementIndex), static_cast<char*>(_pvArray) + (_iElementSize * (iElementIndex + 1)), iMoveSize);
  138. }
  139. ZeroMemory(static_cast<char*>(_pvArray) + (_iElementSize * (_iArraySize - 1)), _iElementSize);
  140. --_iArraySize;
  141. }
  142. else
  143. {
  144. status = STATUS_INVALID_PARAMETER;
  145. }
  146. }
  147. return(status);
  148. }
  149. // --------------------------------------------------------------------------
  150. // CDynamicArray::GetCount
  151. //
  152. // Arguments: <none>
  153. //
  154. // Returns: int
  155. //
  156. // Purpose: Returns the number of elements in the array.
  157. //
  158. // History: 1999-11-16 vtan created
  159. // --------------------------------------------------------------------------
  160. int CDynamicArray::GetCount (void) const
  161. {
  162. return(_iArraySize);
  163. }
  164. // --------------------------------------------------------------------------
  165. // CDynamicArray::Get
  166. //
  167. // Arguments: pvData = Pointer to memory to receive element.
  168. // iElementIndex = Index of element to retrieve in array.
  169. //
  170. // Returns: NTSTATUS
  171. //
  172. // Purpose: Copies the data for the specified element by index to the
  173. // block of memory given. No checks for access violations.
  174. //
  175. // History: 1999-11-16 vtan created
  176. // --------------------------------------------------------------------------
  177. NTSTATUS CDynamicArray::Get (void *pvData, int iElementIndex)
  178. {
  179. NTSTATUS status;
  180. if ((_pvArray != NULL) && (iElementIndex < _iArraySize))
  181. {
  182. CopyMemory(pvData, static_cast<char*>(_pvArray) + (_iElementSize * iElementIndex), _iElementSize);
  183. status = STATUS_SUCCESS;
  184. }
  185. else
  186. {
  187. status = STATUS_INVALID_PARAMETER;
  188. }
  189. return(status);
  190. }
  191. // --------------------------------------------------------------------------
  192. // CDynamicArray::Set
  193. //
  194. // Arguments: pvData = Pointer to memory to receive element.
  195. // iElementIndex = Index of element to retrieve in array.
  196. //
  197. // Returns: NTSTATUS
  198. //
  199. // Purpose: Copies the data for the specified element by index from the
  200. // block of memory given. No checks for access violations.
  201. //
  202. // History: 2000-11-11 vtan created
  203. // --------------------------------------------------------------------------
  204. NTSTATUS CDynamicArray::Set (const void* pvData, int iElementIndex)
  205. {
  206. NTSTATUS status;
  207. status = STATUS_SUCCESS;
  208. if (_pvArray != NULL)
  209. {
  210. if (iElementIndex < _iArraySize)
  211. {
  212. CopyMemory(static_cast<char*>(_pvArray) + (_iElementSize * iElementIndex), pvData, _iElementSize);
  213. }
  214. else
  215. {
  216. status = STATUS_INVALID_PARAMETER;
  217. }
  218. }
  219. return(status);
  220. }
  221. // --------------------------------------------------------------------------
  222. // CDynamicArray::Iterate
  223. //
  224. // Arguments: pDynamicArrayCallback = Interface containing callback.
  225. //
  226. // Returns: NTSTATUS
  227. //
  228. // Purpose: Iterate the elements of the array. Call the callback function
  229. // specified in the interface and give it a pointer to the
  230. // element and the index. Adhere to the NTSTATUS returned from
  231. // the callback and terminate on an unsuccessful result.
  232. //
  233. // History: 1999-11-16 vtan created
  234. // --------------------------------------------------------------------------
  235. NTSTATUS CDynamicArray::Iterate (CDynamicArrayCallback *pDynamicArrayCallback)
  236. {
  237. NTSTATUS status;
  238. status = STATUS_SUCCESS;
  239. if (_pvArray != NULL)
  240. {
  241. int i;
  242. for (i = _iArraySize - 1; NT_SUCCESS(status) && (i >= 0); --i)
  243. {
  244. status = pDynamicArrayCallback->Callback(static_cast<char*>(_pvArray) + (_iElementSize * i), i);
  245. }
  246. }
  247. return(status);
  248. }
  249. // --------------------------------------------------------------------------
  250. // CDynamicPointerArray::CDynamicPointerArray
  251. //
  252. // Arguments: <none>
  253. //
  254. // Returns: <none>
  255. //
  256. // Purpose: Constructor for CDynamicPointerArray. All elements of this
  257. // class are pointers that are allocated with LocalAlloc.
  258. //
  259. // History: 1999-11-16 vtan created
  260. // --------------------------------------------------------------------------
  261. CDynamicPointerArray::CDynamicPointerArray (void) :
  262. CDynamicArray(sizeof(void*))
  263. {
  264. }
  265. // --------------------------------------------------------------------------
  266. // CDynamicPointerArray::~CDynamicPointerArray
  267. //
  268. // Arguments: <none>
  269. //
  270. // Returns: <none>
  271. //
  272. // Purpose: Destructor for CDynamicPointerArray. Walk the entire array
  273. // and free each pointer in the array before allowing the base
  274. // class destructor to release the memory allocated for the
  275. // actual array itself.
  276. //
  277. // History: 1999-11-16 vtan created
  278. // --------------------------------------------------------------------------
  279. CDynamicPointerArray::~CDynamicPointerArray (void)
  280. {
  281. if (_pvArray != NULL)
  282. {
  283. int i;
  284. for (i = _iArraySize - 1; i >= 0; --i)
  285. {
  286. ReleaseMemory(static_cast<void**>(_pvArray)[i]);
  287. }
  288. }
  289. }
  290. // --------------------------------------------------------------------------
  291. // CDynamicPointerArray::Add
  292. //
  293. // Arguments: pvData = Pointer to add to the array.
  294. //
  295. // Returns: NTSTATUS
  296. //
  297. // Purpose: Add the given pointer to the array. The pointer is passed in
  298. // to this function not a pointer to the pointer.
  299. //
  300. // History: 1999-11-16 vtan created
  301. // --------------------------------------------------------------------------
  302. NTSTATUS CDynamicPointerArray::Add (const void *pvData)
  303. {
  304. return(CDynamicArray::Add(&pvData));
  305. }
  306. // --------------------------------------------------------------------------
  307. // CDynamicPointerArray::Remove
  308. //
  309. // Arguments: iElementIndex = Index of the element to remove.
  310. //
  311. // Returns: NTSTATUS
  312. //
  313. // Purpose: Releases the memory occupied by the element and then removes
  314. // the element from the array.
  315. //
  316. // History: 1999-11-16 vtan created
  317. // --------------------------------------------------------------------------
  318. NTSTATUS CDynamicPointerArray::Remove (int iElementIndex)
  319. {
  320. if ((_pvArray != NULL) && (iElementIndex < _iArraySize))
  321. {
  322. ReleaseMemory(static_cast<void**>(_pvArray)[iElementIndex]);
  323. }
  324. return(CDynamicArray::Remove(iElementIndex));
  325. }
  326. // --------------------------------------------------------------------------
  327. // CDynamicPointerArray::Get
  328. //
  329. // Arguments: iElementIndex = Index of the element to get.
  330. //
  331. // Returns: void*
  332. //
  333. // Purpose: Returns the address of the given element in the array. This
  334. // applies only to pointer arrays.
  335. //
  336. // History: 1999-11-16 vtan created
  337. // --------------------------------------------------------------------------
  338. void* CDynamicPointerArray::Get (int iElementIndex)
  339. {
  340. void* pvData;
  341. if (!NT_SUCCESS(CDynamicArray::Get(&pvData, iElementIndex)))
  342. {
  343. pvData = NULL;
  344. }
  345. return(pvData);
  346. }
  347. // --------------------------------------------------------------------------
  348. // CDynamicCountedObjectArray::CDynamicCountedObjectArray
  349. //
  350. // Arguments: <none>
  351. //
  352. // Returns: <none>
  353. //
  354. // Purpose: Constructor for the CDynamicCountedObjectArray. All elements
  355. // should be a subclass of CCountedObject in some way.
  356. //
  357. // History: 1999-11-16 vtan created
  358. // --------------------------------------------------------------------------
  359. CDynamicCountedObjectArray::CDynamicCountedObjectArray (void) :
  360. CDynamicArray(sizeof(CCountedObject*))
  361. {
  362. }
  363. // --------------------------------------------------------------------------
  364. // CDynamicCountedObjectArray::~CDynamicCountedObjectArray
  365. //
  366. // Arguments: <none>
  367. //
  368. // Returns: <none>
  369. //
  370. // Purpose: Destructor for CDynamicCountedObjectArray. Walk the entire
  371. // array and release each CCountedObject in the array before
  372. // allowing the base class destructor to release the memory
  373. // allocated for the actual array itself.
  374. //
  375. // History: 1999-11-16 vtan created
  376. // --------------------------------------------------------------------------
  377. CDynamicCountedObjectArray::~CDynamicCountedObjectArray (void)
  378. {
  379. if (_pvArray != NULL)
  380. {
  381. int i;
  382. for (i = _iArraySize - 1; i >= 0; --i)
  383. {
  384. reinterpret_cast<CCountedObject**>(_pvArray)[i]->Release();
  385. }
  386. }
  387. }
  388. // --------------------------------------------------------------------------
  389. // CDynamicCountedObjectArray::Add
  390. //
  391. // Arguments: pvData = CCountedObject* to add to the array.
  392. //
  393. // Returns: NTSTATUS
  394. //
  395. // Purpose: Adds the CCountedObject* to the array. Calls
  396. // CCountedObject::AddRef to incremenet the reference count on
  397. // the object. If the object cannot be added the reference is
  398. // released.
  399. //
  400. // History: 1999-11-16 vtan created
  401. // --------------------------------------------------------------------------
  402. NTSTATUS CDynamicCountedObjectArray::Add (CCountedObject *pvData)
  403. {
  404. NTSTATUS status;
  405. pvData->AddRef();
  406. status = CDynamicArray::Add(&pvData);
  407. if (!NT_SUCCESS(status))
  408. {
  409. pvData->Release();
  410. }
  411. return(status);
  412. }
  413. // --------------------------------------------------------------------------
  414. // CDynamicCountedObjectArray::Remove
  415. //
  416. // Arguments: iElementIndex = Index of the element to remove.
  417. //
  418. // Returns: NTSTATUS
  419. //
  420. // Purpose: Releases the reference held on the CCountedObject* and then
  421. // removes the element from the array.
  422. //
  423. // History: 1999-11-16 vtan created
  424. // --------------------------------------------------------------------------
  425. NTSTATUS CDynamicCountedObjectArray::Remove (int iElementIndex)
  426. {
  427. if ((_pvArray != NULL) && (iElementIndex < _iArraySize))
  428. {
  429. reinterpret_cast<CCountedObject**>(_pvArray)[iElementIndex]->Release();
  430. }
  431. return(CDynamicArray::Remove(iElementIndex));
  432. }
  433. // --------------------------------------------------------------------------
  434. // CDynamicCountedObjectArray::Get
  435. //
  436. // Arguments: iElementIndex = Index of the element to get.
  437. //
  438. // Returns: CCountedObject*
  439. //
  440. // Purpose: Returns the address of the given element in the array. This
  441. // applies only to CCountedObject* arrays. This does NOT call
  442. // CCountedObject::AddRef on the returned pointer.
  443. //
  444. // History: 1999-11-16 vtan created
  445. // --------------------------------------------------------------------------
  446. CCountedObject* CDynamicCountedObjectArray::Get (int iElementIndex)
  447. {
  448. CCountedObject* pObject;
  449. pObject = NULL;
  450. (NTSTATUS)CDynamicArray::Get(&pObject, iElementIndex);
  451. return(pObject);
  452. }