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.

316 lines
8.8 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: implements a growable array
  5. // ThreadSafe: no
  6. // Locks: none
  7. // Please read stdinfo.txt for conventions on reading/writing code that i use
  8. //================================================================================
  9. #include <mm.h>
  10. #define FILE "mm\\array.h"
  11. #ifdef IMPORTS
  12. MemAlloc
  13. MemFree
  14. AssertRet
  15. Require
  16. #endif IMPORTS
  17. //BeginExport(typedef)
  18. typedef struct _ARRAY {
  19. DWORD nElements;
  20. DWORD nAllocated;
  21. LPVOID *Ptrs;
  22. } ARRAY, *PARRAY, *LPARRAY;
  23. //EndExport(typedef)
  24. //BeginExport(typedef)
  25. typedef DWORD ARRAY_LOCATION;
  26. typedef ARRAY_LOCATION* PARRAY_LOCATION;
  27. typedef PARRAY_LOCATION LPARRAY_LOCATION;
  28. //EndExport(typedef)
  29. //BeginExport(inline)
  30. DWORD _inline
  31. MemArrayInit( // initialize the STRUCTURE
  32. OUT PARRAY Array // input structure pre-allocated
  33. ) {
  34. AssertRet(Array, ERROR_INVALID_PARAMETER);
  35. Array->nElements = Array->nAllocated = 0;
  36. Array->Ptrs = NULL;
  37. return ERROR_SUCCESS;
  38. }
  39. //EndExport(inline)
  40. //BeginExport(inline)
  41. DWORD _inline
  42. MemArrayCleanup( // freeup the memory if any, allocated in this module
  43. IN OUT PARRAY Array
  44. ) {
  45. AssertRet(Array, ERROR_INVALID_PARAMETER);
  46. if( Array->Ptrs) MemFree(Array->Ptrs);
  47. Array->nElements = Array->nAllocated = 0;
  48. Array->Ptrs = NULL;
  49. return ERROR_SUCCESS;
  50. }
  51. //EndExport(inline)
  52. //BeginExport(inline)
  53. DWORD _inline
  54. MemArraySize(
  55. IN PARRAY Array
  56. ) {
  57. AssertRet(Array, ERROR_INVALID_PARAMETER);
  58. return Array->nElements;
  59. }
  60. //EndExport(inline)
  61. //BeginExport(inline)
  62. DWORD _inline
  63. MemArrayInitLoc( // Initialize an array location
  64. IN PARRAY Array,
  65. IN OUT PARRAY_LOCATION Location
  66. ) {
  67. AssertRet(Array && Location, ERROR_INVALID_PARAMETER);
  68. (*Location) = 0;
  69. if( 0 == Array->nElements ) return ERROR_FILE_NOT_FOUND;
  70. return ERROR_SUCCESS;
  71. }
  72. //EndExport(inline)
  73. //BeginExport(inline)
  74. BOOL _inline
  75. MemArrayValidLoc(
  76. IN PARRAY Array,
  77. IN PARRAY_LOCATION Location
  78. )
  79. {
  80. AssertRet(Array && Location, FALSE);
  81. return ( *Location < Array->nElements );
  82. }
  83. //EndExport(inline)
  84. //BeginExport(inline)
  85. DWORD _inline
  86. MemArrayNextLoc( // move one step forward
  87. IN PARRAY Array,
  88. IN OUT PARRAY_LOCATION Location
  89. ) {
  90. AssertRet(Array && Location, ERROR_INVALID_PARAMETER);
  91. if( (*Location) + 1 >= Array->nElements ) return ERROR_FILE_NOT_FOUND;
  92. (*Location) ++;
  93. return ERROR_SUCCESS;
  94. }
  95. //EndExport(inline)
  96. //BeginExport(inline)
  97. DWORD _inline
  98. MemArrayPrevLoc(
  99. IN PARRAY Array,
  100. IN OUT PARRAY_LOCATION Location
  101. ) {
  102. AssertRet(Array && Location, ERROR_INVALID_PARAMETER);
  103. if( 0 == Array->nElements ) return ERROR_FILE_NOT_FOUND;
  104. if( ((LONG)(*Location)) - 1 < 0 ) return ERROR_FILE_NOT_FOUND;
  105. (*Location) --;
  106. return ERROR_SUCCESS;
  107. }
  108. //EndExport(inline)
  109. //BeginExport(inline)
  110. DWORD _inline
  111. MemArrayLastLoc(
  112. IN PARRAY Array,
  113. IN OUT PARRAY_LOCATION Location
  114. ) {
  115. AssertRet(Array && Location, ERROR_INVALID_PARAMETER);
  116. if( 0 == Array->nElements ) return ERROR_FILE_NOT_FOUND;
  117. (*Location) = Array->nElements -1;
  118. return ERROR_SUCCESS;
  119. }
  120. //EndExport(inline)
  121. //BeginExport(inline)
  122. DWORD _inline
  123. MemArrayGetElement(
  124. IN PARRAY Array,
  125. IN PARRAY_LOCATION Location,
  126. OUT LPVOID *Element
  127. ) {
  128. AssertRet(Array && Location && Element, ERROR_INVALID_PARAMETER);
  129. (*Element) = Array->Ptrs[*Location];
  130. return ERROR_SUCCESS;
  131. }
  132. //EndExport(inline)
  133. //BeginExport(inline)
  134. DWORD _inline
  135. MemArraySetElement(
  136. IN OUT PARRAY Array,
  137. IN PARRAY_LOCATION Location,
  138. IN LPVOID Element
  139. ) {
  140. AssertRet(Array && Location, ERROR_INVALID_PARAMETER );
  141. Array->Ptrs[*Location] = Element;
  142. return ERROR_SUCCESS;
  143. }
  144. //EndExport(inline)
  145. const
  146. DWORD MinAllocUnit = 4;
  147. const
  148. DWORD MinFreeUnit = 4; // Must be a power of two
  149. LPVOID _inline
  150. MemAllocLpvoid(
  151. DWORD nLpvoids
  152. ) {
  153. return MemAlloc(sizeof(LPVOID)*nLpvoids);
  154. }
  155. //BeginExport(function)
  156. DWORD
  157. MemArrayAddElement(
  158. IN OUT PARRAY Array,
  159. IN LPVOID Element
  160. ) //EndExport(function)
  161. {
  162. LPVOID Ptrs;
  163. AssertRet(Array, ERROR_INVALID_PARAMETER );
  164. if( Array->nElements < Array->nAllocated ) {
  165. Array->Ptrs[Array->nElements ++ ] = Element;
  166. return ERROR_SUCCESS;
  167. }
  168. if( 0 == Array->nAllocated ) {
  169. Array->Ptrs = MemAllocLpvoid(MinAllocUnit);
  170. if( NULL == Array->Ptrs ) return ERROR_NOT_ENOUGH_MEMORY;
  171. Array->nAllocated = MinAllocUnit;
  172. Array->nElements = 1;
  173. Array->Ptrs[0] = Element;
  174. return ERROR_SUCCESS;
  175. }
  176. Ptrs = MemAllocLpvoid(MinAllocUnit+Array->nAllocated);
  177. if( NULL == Ptrs ) return ERROR_NOT_ENOUGH_MEMORY;
  178. memcpy(Ptrs, Array->Ptrs, sizeof(LPVOID)*Array->nAllocated);
  179. MemFree(Array->Ptrs);
  180. Array->Ptrs = Ptrs;
  181. Array->Ptrs[Array->nElements++] = Element;
  182. Array->nAllocated += MinAllocUnit;
  183. return ERROR_SUCCESS;
  184. }
  185. //BeginExport(function)
  186. DWORD
  187. MemArrayInsElement(
  188. IN OUT PARRAY Array,
  189. IN PARRAY_LOCATION Location,
  190. IN LPVOID Element
  191. ) //EndExport(function)
  192. {
  193. LPVOID *Ptrs;
  194. AssertRet(Array && Location, ERROR_INVALID_PARAMETER);
  195. if( (*Location) == Array->nElements )
  196. return MemArrayAddElement(Array,Element);
  197. if( Array->nElements < Array->nAllocated ) {
  198. memmove(&Array->Ptrs[1+*Location], &Array->Ptrs[*Location], sizeof(LPVOID)*(Array->nElements - *Location));
  199. Array->Ptrs[*Location] = Element;
  200. Array->nElements++;
  201. return ERROR_SUCCESS;
  202. }
  203. Require(Array->nElements);
  204. Ptrs = MemAllocLpvoid(MinAllocUnit + Array->nAllocated);
  205. if( NULL == Ptrs ) return ERROR_NOT_ENOUGH_MEMORY;
  206. memcpy(Ptrs, Array->Ptrs, sizeof(LPVOID)*(*Location) );
  207. Ptrs[*Location] = Element;
  208. memcpy(&Ptrs[1+*Location], &Array->Ptrs[*Location], sizeof(LPVOID)*(Array->nElements - *Location));
  209. MemFree(Array->Ptrs);
  210. Array->Ptrs = Ptrs;
  211. Array->nElements ++;
  212. Array->nAllocated += MinAllocUnit;
  213. return ERROR_SUCCESS;
  214. }
  215. //BeginExport(function)
  216. DWORD
  217. MemArrayDelElement(
  218. IN OUT PARRAY Array,
  219. IN PARRAY_LOCATION Location,
  220. IN LPVOID *Element
  221. ) //EndExport(function)
  222. {
  223. LPVOID *Ptrs;
  224. AssertRet(Array && Location && Array->nElements && Element, ERROR_INVALID_PARAMETER);
  225. (*Element) = Array->Ptrs[*Location];
  226. Array->nElements--;
  227. if( 0 == Array->nElements ) {
  228. Require(0 == *Location);
  229. return MemArrayCleanup(Array);
  230. }
  231. if( Array->nElements % MinFreeUnit || NULL == (Ptrs = MemAllocLpvoid(Array->nElements))) {
  232. memcpy(&Array->Ptrs[*Location], &Array->Ptrs[1+*Location], sizeof(LPVOID)*(Array->nElements - (*Location)));
  233. return ERROR_SUCCESS;
  234. }
  235. Require(Ptrs);
  236. memcpy(Ptrs, Array->Ptrs, sizeof(LPVOID)*(*Location));
  237. memcpy(&Ptrs[*Location], &Array->Ptrs[1+*Location], sizeof(LPVOID)*(Array->nElements - (*Location)));
  238. MemFree(Array->Ptrs);
  239. Array->Ptrs = Ptrs;
  240. Array->nAllocated = Array->nElements;
  241. return ERROR_SUCCESS;
  242. }
  243. //BeginExport(inline)
  244. DWORD _inline
  245. MemArrayAdjustLocation( // reset location to "next" after a delete
  246. IN PARRAY Array,
  247. IN OUT PARRAY_LOCATION Location
  248. ) {
  249. AssertRet(Location && Array, ERROR_INVALID_PARAMETER);
  250. if( *Location >= Array->nElements ) return ERROR_FILE_NOT_FOUND;
  251. return ERROR_SUCCESS;
  252. }
  253. //EndExport(inline)
  254. //BeginExport(inline)
  255. DWORD _inline
  256. MemArrayRotateCyclical( // rotate forward/right cyclical
  257. IN PARRAY Array
  258. ) {
  259. LPVOID FirstPtr;
  260. AssertRet(Array, ERROR_INVALID_PARAMETER);
  261. if( Array->nElements < 2 ) return ERROR_SUCCESS;
  262. FirstPtr = Array->Ptrs[0];
  263. memcpy(Array->Ptrs, &Array->Ptrs[1], sizeof(Array->Ptrs[0])* (Array->nElements -1));
  264. Array->Ptrs[Array->nElements -1] = FirstPtr;
  265. return ERROR_SUCCESS;
  266. }
  267. //EndExport(inline)
  268. //================================================================================
  269. // end of file
  270. //================================================================================