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.

589 lines
15 KiB

  1. /***************************************************************************\
  2. *
  3. * File: Array.inl
  4. *
  5. * History:
  6. * 1/04/2000: JStall: Created
  7. *
  8. * Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
  9. *
  10. \***************************************************************************/
  11. #if !defined(BASE__Array_inl__INCLUDED)
  12. #define BASE__Array_inl__INCLUDED
  13. #include "SimpleHeap.h"
  14. /***************************************************************************\
  15. *
  16. * class GArrayS
  17. *
  18. \***************************************************************************/
  19. //------------------------------------------------------------------------------
  20. template <class T, class heap>
  21. inline
  22. GArrayS<T, heap>::GArrayS() : m_aT(NULL)
  23. {
  24. //
  25. // All elements in GArrayS<T, heap> must be at least sizeof(int) large. This is
  26. // because of the design that stores the size in the element preceeding the
  27. // data for the array.
  28. //
  29. AssertMsg(sizeof(T) >= sizeof(int), "Ensure minimum element size");
  30. }
  31. //------------------------------------------------------------------------------
  32. template <class T, class heap>
  33. inline
  34. GArrayS<T, heap>::~GArrayS()
  35. {
  36. RemoveAll();
  37. }
  38. //------------------------------------------------------------------------------
  39. template <class T, class heap>
  40. BOOL
  41. GArrayS<T, heap>::IsEmpty() const
  42. {
  43. return m_aT == NULL;
  44. }
  45. //------------------------------------------------------------------------------
  46. template <class T, class heap>
  47. inline void *
  48. GArrayS<T, heap>::GetRawData(BOOL fCheckNull) const
  49. {
  50. if (fCheckNull) {
  51. //
  52. // Need to check if array is allocated
  53. //
  54. if (m_aT != NULL) {
  55. return (void *) (&m_aT[-1]);
  56. } else {
  57. return NULL;
  58. }
  59. } else {
  60. //
  61. // Blindly return the size
  62. //
  63. AssertMsg(m_aT != NULL, "Array must be allocated if not checking");
  64. return &m_aT[-1];
  65. }
  66. }
  67. //------------------------------------------------------------------------------
  68. template <class T, class heap>
  69. inline void
  70. GArrayS<T, heap>::SetRawSize(int cNewItems)
  71. {
  72. //
  73. // Store the size before the array data. This function should only be
  74. // called when an array is allocated (and thus have a non-zero size).
  75. //
  76. AssertMsg(cNewItems > 0, "Must specify a positive number of items");
  77. AssertMsg(m_aT != NULL, "Must allocate range to set number of items");
  78. int * pnSize = (int *) GetRawData(FALSE);
  79. *pnSize = cNewItems;
  80. }
  81. //------------------------------------------------------------------------------
  82. template <class T, class heap>
  83. inline int
  84. GArrayS<T, heap>::GetSize() const
  85. {
  86. if (m_aT != NULL) {
  87. int * pnSize = (int *) GetRawData(FALSE);
  88. int cItems = *pnSize;
  89. AssertMsg(cItems >= 1, "Must have at least one item");
  90. return cItems;
  91. } else {
  92. return 0;
  93. }
  94. }
  95. //------------------------------------------------------------------------------
  96. template <class T, class heap>
  97. inline BOOL
  98. GArrayS<T, heap>::SetSize(int cItems)
  99. {
  100. AssertMsg(cItems >= 0, "Must have valid size");
  101. int cSize = GetSize();
  102. if (cSize == cItems) {
  103. return TRUE;
  104. }
  105. if (cItems == 0) {
  106. RemoveAll();
  107. return TRUE;
  108. } else {
  109. return Resize(cItems, cSize);
  110. }
  111. }
  112. //------------------------------------------------------------------------------
  113. template <class T, class heap>
  114. inline int
  115. GArrayS<T, heap>::Add(const T & t)
  116. {
  117. int idxAdd = GetSize();
  118. if (!Resize(idxAdd + 1, idxAdd)) {
  119. return -1;
  120. }
  121. SetAtIndex(idxAdd, t);
  122. return idxAdd;
  123. }
  124. //------------------------------------------------------------------------------
  125. template <class T, class heap>
  126. inline BOOL
  127. GArrayS<T, heap>::InsertAt(int idxItem, const T & t)
  128. {
  129. AssertMsg(idxItem <= GetSize(), "Check index");
  130. // Actually may need to increase the size by one and shift everything
  131. // down
  132. int idxAdd = GetSize();
  133. if (!Resize(idxAdd + 1, idxAdd)) {
  134. return FALSE;
  135. }
  136. int cbMove = (idxAdd - idxItem) * sizeof(T);
  137. if (cbMove > 0) {
  138. MoveMemory(&m_aT[idxItem + 1], &m_aT[idxItem], cbMove);
  139. }
  140. SetAtIndex(idxItem, t);
  141. return TRUE;
  142. }
  143. //------------------------------------------------------------------------------
  144. template <class T, class heap>
  145. inline BOOL
  146. GArrayS<T, heap>::Remove(const T & t)
  147. {
  148. int idxItem = Find(t);
  149. if(idxItem == -1) {
  150. return FALSE;
  151. }
  152. return RemoveAt(idxItem);
  153. }
  154. //------------------------------------------------------------------------------
  155. template <class T, class heap>
  156. inline BOOL
  157. GArrayS<T, heap>::RemoveAt(int idxItem)
  158. {
  159. int cItems = GetSize();
  160. AssertMsg((idxItem < cItems) && (cItems >= 0), "Ensure valid index");
  161. m_aT[idxItem].~T();
  162. cItems--;
  163. if (cItems > 0) {
  164. //
  165. // Found the element, so we need to splice it out of the array. We
  166. // can not just Realloc() the buffer b/c we need to slide all
  167. // property data after this down one. This means that we have to
  168. // allocate a new buffer. If we are unable to allocate a temporary
  169. // buffer, we can go ahead and just use the existing buffer, but we
  170. // won't be able to free any memory.
  171. //
  172. if (idxItem < cItems) {
  173. MoveMemory((void*)&m_aT[idxItem], (void*)&m_aT[idxItem + 1], (cItems - idxItem) * sizeof(T));
  174. }
  175. T * rgNewData = (T *) ContextRealloc(heap::GetHeap(), GetRawData(FALSE), (cItems + 1) * sizeof(T));
  176. if (rgNewData != NULL) {
  177. m_aT = &rgNewData[1];
  178. }
  179. SetRawSize(cItems);
  180. } else {
  181. ContextFree(heap::GetHeap(), GetRawData(FALSE));
  182. m_aT = NULL;
  183. }
  184. return TRUE;
  185. }
  186. //------------------------------------------------------------------------------
  187. template <class T, class heap>
  188. inline void
  189. GArrayS<T, heap>::RemoveAll()
  190. {
  191. if(m_aT != NULL) {
  192. int cItems = GetSize();
  193. for(int i = 0; i < cItems; i++) {
  194. m_aT[i].~T();
  195. }
  196. ContextFree(heap::GetHeap(), GetRawData(FALSE));
  197. m_aT = NULL;
  198. }
  199. }
  200. //------------------------------------------------------------------------------
  201. template <class T, class heap>
  202. inline T &
  203. GArrayS<T, heap>::operator[] (int idxItem) const
  204. {
  205. Assert(idxItem >= 0 && idxItem < GetSize());
  206. return m_aT[idxItem];
  207. }
  208. //------------------------------------------------------------------------------
  209. template <class T, class heap>
  210. inline T *
  211. GArrayS<T, heap>::GetData() const
  212. {
  213. return m_aT;
  214. }
  215. //------------------------------------------------------------------------------
  216. template <class T, class heap>
  217. inline void
  218. GArrayS<T, heap>::SetAtIndex(int idxItem, const T & t)
  219. {
  220. Assert(idxItem >= 0 && (idxItem < GetSize()));
  221. placement_copynew(&m_aT[idxItem], T, t);
  222. }
  223. //------------------------------------------------------------------------------
  224. template <class T, class heap>
  225. inline int
  226. GArrayS<T, heap>::Find(const T & t) const
  227. {
  228. int cItems = GetSize();
  229. for(int i = 0; i < cItems; i++) {
  230. if(m_aT[i] == t) {
  231. return i;
  232. }
  233. }
  234. return -1; // not found
  235. }
  236. /***************************************************************************\
  237. *
  238. * GArrayS<T, heap>::Resize()
  239. *
  240. * Resize() changes the size of the array to a non-zero number of elements.
  241. *
  242. * NOTE: This function has been specifically written for the GArrayS<T, heap>
  243. * class and has slightly different behavior that GArrayF<T, heap>::Resize().
  244. *
  245. \***************************************************************************/
  246. template <class T, class heap>
  247. inline BOOL
  248. GArrayS<T, heap>::Resize(
  249. IN int cItems, // New number of items
  250. IN int cSize) // Current size
  251. {
  252. AssertMsg(cItems > 0, "Must have non-zero and positive number of items");
  253. AssertMsg(cItems != cSize, "Must have a different size");
  254. if (cItems < cSize) {
  255. //
  256. // Making the array smaller, so need to destruct the objects we are
  257. // getting rid of.
  258. //
  259. AssertMsg(m_aT != NULL, "Should have data allocated");
  260. for(int i = cItems; i < cSize; i++) {
  261. m_aT[i].~T();
  262. }
  263. }
  264. //
  265. // Resize the array and store the new size.
  266. //
  267. T * aT;
  268. aT = (T *) ContextRealloc(heap::GetHeap(), GetRawData(TRUE), (cItems + 1) * sizeof(T));
  269. if(aT == NULL) {
  270. AssertMsg(cItems >= cSize, "Should never fail when shrinking");
  271. return FALSE;
  272. }
  273. m_aT = &aT[1];
  274. SetRawSize(cItems);
  275. return TRUE;
  276. }
  277. /***************************************************************************\
  278. *
  279. * class GArrayBase
  280. *
  281. \***************************************************************************/
  282. //------------------------------------------------------------------------------
  283. template <class T, class heap>
  284. inline
  285. GArrayF<T, heap>::GArrayF() : m_aT(NULL), m_nSize(0), m_nAllocSize(0)
  286. {
  287. }
  288. //------------------------------------------------------------------------------
  289. template <class T, class heap>
  290. inline
  291. GArrayF<T, heap>::~GArrayF()
  292. {
  293. RemoveAll();
  294. }
  295. //------------------------------------------------------------------------------
  296. template <class T, class heap>
  297. inline BOOL
  298. GArrayF<T, heap>::IsEmpty() const
  299. {
  300. //
  301. // GArrayF may have a non-NULL m_aT but a m_nSize if only Add() and Remove()
  302. // are used, treating the array like a stack. Therefore, we must use
  303. // m_nSize to determine if the array is "empty". To free all memory
  304. // allocated by the array, use RemoveAll().
  305. //
  306. return m_nSize <= 0;
  307. }
  308. //------------------------------------------------------------------------------
  309. template <class T, class heap>
  310. inline int
  311. GArrayF<T, heap>::GetSize() const
  312. {
  313. return m_nSize;
  314. }
  315. //------------------------------------------------------------------------------
  316. template <class T, class heap>
  317. inline BOOL
  318. GArrayF<T, heap>::SetSize(int cItems)
  319. {
  320. AssertMsg(cItems >= 0, "Must have valid size");
  321. if (!Resize(cItems)) {
  322. return FALSE;
  323. }
  324. m_nSize = cItems;
  325. return TRUE;
  326. }
  327. //------------------------------------------------------------------------------
  328. template <class T, class heap>
  329. inline int
  330. GArrayF<T, heap>::Add(const T & t)
  331. {
  332. if(m_nSize == m_nAllocSize) {
  333. int nNewAllocSize = (m_nAllocSize == 0) ? 8 : (m_nAllocSize * 2);
  334. if (!Resize(nNewAllocSize)) {
  335. return -1;
  336. }
  337. }
  338. int idxAdd = m_nSize;
  339. m_nSize++;
  340. SetAtIndex(idxAdd, t);
  341. return idxAdd;
  342. }
  343. //------------------------------------------------------------------------------
  344. template <class T, class heap>
  345. inline BOOL
  346. GArrayF<T, heap>::InsertAt(int idxItem, const T & t)
  347. {
  348. AssertMsg(idxItem <= m_nSize, "Check index");
  349. // Actually may need to increase the size by one and shift everything
  350. // down
  351. if (!Resize(m_nSize + 1)) {
  352. return FALSE;
  353. }
  354. int cbMove = (m_nSize - idxItem) * sizeof(T);
  355. if (cbMove > 0) {
  356. MoveMemory(&m_aT[idxItem + 1], &m_aT[idxItem], cbMove);
  357. }
  358. m_nSize++;
  359. SetAtIndex(idxItem, t);
  360. return TRUE;
  361. }
  362. //------------------------------------------------------------------------------
  363. template <class T, class heap>
  364. inline BOOL
  365. GArrayF<T, heap>::Remove(const T & t)
  366. {
  367. int idxItem = Find(t);
  368. if(idxItem == -1) {
  369. return FALSE;
  370. }
  371. return RemoveAt(idxItem);
  372. }
  373. //------------------------------------------------------------------------------
  374. template <class T, class heap>
  375. inline BOOL
  376. GArrayF<T, heap>::RemoveAt(int idxItem)
  377. {
  378. AssertMsg((idxItem < m_nSize) && (idxItem >= 0), "Must specify a valid index");
  379. if(idxItem != (m_nSize - 1)) {
  380. m_aT[idxItem].~T();
  381. MoveMemory((void*)&m_aT[idxItem], (void*)&m_aT[idxItem + 1], (m_nSize - (idxItem + 1)) * sizeof(T));
  382. }
  383. m_nSize--;
  384. return TRUE;
  385. }
  386. //------------------------------------------------------------------------------
  387. template <class T, class heap>
  388. inline void
  389. GArrayF<T, heap>::RemoveAll()
  390. {
  391. if(m_aT != NULL) {
  392. for(int i = 0; i < m_nSize; i++) {
  393. m_aT[i].~T();
  394. }
  395. ContextFree(heap::GetHeap(), m_aT);
  396. m_aT = NULL;
  397. }
  398. m_nSize = 0;
  399. m_nAllocSize = 0;
  400. }
  401. //------------------------------------------------------------------------------
  402. template <class T, class heap>
  403. inline T &
  404. GArrayF<T, heap>::operator[] (int idxItem) const
  405. {
  406. AssertMsg((idxItem < m_nSize) && (idxItem >= 0), "Must specify a valid index");
  407. return m_aT[idxItem];
  408. }
  409. //------------------------------------------------------------------------------
  410. template <class T, class heap>
  411. inline T *
  412. GArrayF<T, heap>::GetData() const
  413. {
  414. return m_aT;
  415. }
  416. //------------------------------------------------------------------------------
  417. template <class T, class heap>
  418. inline void
  419. GArrayF<T, heap>::SetAtIndex(int idxItem, const T & t)
  420. {
  421. AssertMsg((idxItem < m_nSize) && (idxItem >= 0), "Must specify a valid index");
  422. placement_copynew(&m_aT[idxItem], T, t);
  423. }
  424. //------------------------------------------------------------------------------
  425. template <class T, class heap>
  426. inline int
  427. GArrayF<T, heap>::Find(const T & t) const
  428. {
  429. for(int i = 0; i < m_nSize; i++) {
  430. if(m_aT[i] == t) {
  431. return i;
  432. }
  433. }
  434. return -1; // not found
  435. }
  436. /***************************************************************************\
  437. *
  438. * GArrayF<T, heap>::Resize()
  439. *
  440. * Resize() changes the size of the array.
  441. *
  442. * NOTE: This function has been specifically written for the GArrayF<T, heap>
  443. * class and has slightly different behavior that GArrayS<T, heap>::Resize().
  444. *
  445. \***************************************************************************/
  446. template <class T, class heap>
  447. inline BOOL
  448. GArrayF<T, heap>::Resize(int cItems)
  449. {
  450. if (cItems == 0) {
  451. RemoveAll();
  452. } else {
  453. AssertMsg(m_nAllocSize >= m_nSize, "Ensure legal sizes");
  454. if (cItems < m_nSize) {
  455. //
  456. // Making the array smaller, so need to destruct the objects we are
  457. // getting rid of.
  458. //
  459. if(m_aT != NULL) {
  460. for(int i = cItems; i < m_nSize; i++) {
  461. m_aT[i].~T();
  462. }
  463. }
  464. }
  465. //
  466. // Resize the array, but don't update m_nSize b/c that is the caller's
  467. // responsibility.
  468. //
  469. T * aT;
  470. aT = (T *) ContextRealloc(heap::GetHeap(), m_aT, cItems * sizeof(T));
  471. if(aT == NULL) {
  472. return FALSE;
  473. }
  474. m_nAllocSize = cItems;
  475. m_aT = aT;
  476. }
  477. return TRUE;
  478. }
  479. #endif // BASE__Array_inl__INCLUDED