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.

274 lines
8.2 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 - 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: BagArray.h
  6. * Content: CBagArray / CBagPtrArray Declaration
  7. *
  8. * History:
  9. * Date By Reason
  10. * ====== == ======
  11. * 12-12-2001 simonpow Created
  12. ***************************************************************************/
  13. #ifndef __BAGARRAY_H__
  14. #define __BAGARRAY_H__
  15. #include "AutoArray.h"
  16. /*
  17. * CBagArray.
  18. * Represents an unordered collection of elements held in an array.
  19. * This class is useful when your repeatedly scanning a set of values
  20. * or objects and don't care what their order is, and have no
  21. * need to maintain persistent reference to specific entries.
  22. * Each time you remove an entry it fills the empty slot with
  23. * the current top entry in the array. Hence, whilst removes cause
  24. * the array order to change, it means scans always take minimal time.
  25. *
  26. * Memory management relies on CAutoArray so see comments on that for more info.
  27. *
  28. * If you need a CBagArray of pointers use the CBagPtrArray specialisation of it
  29. * This is declared below CBagArray.
  30. */
  31. template <class T> class CBagArray
  32. {
  33. public:
  34. //provides the type of entries held
  35. typedef T Entry;
  36. //array starts 0 zero and by default grows in multiples
  37. //of 16 elements at a time
  38. CBagArray(DWORD dwSizeMultiple=16) : m_data(dwSizeMultiple), m_dwTopFreeSlot(0)
  39. { };
  40. //standard d'tor
  41. ~CBagArray()
  42. {};
  43. /*
  44. * Memory Management
  45. */
  46. //Delete existing contents and reset the size multiplier
  47. //Pass 0 for size multiplier to retain the existing value
  48. void Reset(DWORD dwSizeMultiple=16)
  49. { m_data.Reset(dwSizeMultiple); m_dwTopFreeSlot=0; };
  50. //ensure that there is enough space in the array to hold at least
  51. //'numElements' without needing to re-create and copy the data
  52. //Returns FALSE if it fails due to a memory alloc failure
  53. BOOL AllocAtLeast(DWORD dwNumElements)
  54. { return m_data.AllocAtLeast(dwNumElements); };
  55. //ensure that there is enough space in the array
  56. //to hold at least an additional 'numElements'
  57. //Returns FALSE if it fails due to a memory alloc failure
  58. BOOL AllocExtra(DWORD dwNumElements)
  59. { return m_data.AllocAtLeast(dwNumElements+m_dwTopFreeSlot); };
  60. /*
  61. * Adding elements to bag
  62. */
  63. //add an element.
  64. //Returns FALSE if it fails due to a memory alloc failure
  65. BOOL AddElement(const T& elem)
  66. { return m_data.SetElement(m_dwTopFreeSlot++, elem); };
  67. //add a series of entries to the end of the array
  68. //N.B. Don't pass pointers into data in this bag as 'pElem'!
  69. //e.g. Don't do bag.AddElements(bag.GetAllElements, bag.GetNumElements());
  70. //Returns FALSE if it fails due to a memory alloc failure
  71. BOOL AddElements(const T * pElems, DWORD dwNumElem);
  72. //add the entries from another bag to the end of this one
  73. //N.B. Don't pass bag to itself (e.g. Don't do bag.AddElements(bag); )
  74. //Returns FALSE if it fails due to a memory alloc failure
  75. BOOL AddElements(const CBagArray<T>& bag);
  76. //add an entry and don't check if more memory is needed!
  77. //*ONLY* use this if you know the array already
  78. //has enough space. A good example of use is adding a
  79. //sequence of x entries pre-fixed with an AllocExtra(x)
  80. void AddElementNoCheck(const T& elem)
  81. { m_data.SetExistingElement(m_dwTopFreeSlot++, elem); };
  82. /*
  83. * Removing entries
  84. * N.B. These cause the order of the elements to change
  85. */
  86. //remove the first entry that matches 'elem'
  87. //returns TRUE if 'dataEntry' is found or FALSE if it isn't
  88. BOOL RemoveElementByValue(const T& elem);
  89. //return an entry by its *current* index in the array
  90. //N.B. A remove operation can disturb the order in the array.
  91. //Therefore you can't call this repeatedly without checking
  92. //your certain your removing the right thing
  93. inline void RemoveElementByIndex(DWORD dwIndex);
  94. //remove all the current entries
  95. void RemoveAllElements()
  96. { m_dwTopFreeSlot=0; };
  97. /*
  98. * Accessing bag contents
  99. * N.B. Treat any pointers into bag contents very carefully.
  100. * Adding new elements to the bag or using the Alloc* methods
  101. * can cause them to become invalid
  102. */
  103. //returns the number of entries
  104. DWORD GetNumElements() const
  105. { return m_dwTopFreeSlot; };
  106. //return true if the array is empty
  107. BOOL IsEmpty() const
  108. { return (m_dwTopFreeSlot==0); };
  109. //return value at a specific index
  110. T GetElementValue(DWORD dwIndex) const
  111. { return m_data.GetElementValue(dwIndex); };
  112. //return reference to an element at specific index
  113. T& GetElementRef(DWORD dwIndex)
  114. { return m_data.GetElementRef(dwIndex); };
  115. //return constant reference to an element at specific index
  116. const T& GetElementRef(DWORD dwIndex) const
  117. { return m_data.GetElementRef(dwIndex); };
  118. //return a pointer to an element
  119. T * GetElementPtr(DWORD dwIndex)
  120. { return m_data.GetElementPtr(dwIndex); };
  121. //returns pointer to array of all elements
  122. T * GetAllElements()
  123. { return m_data.GetAllElements(); };
  124. //copy dwNumElements from dwIndex into pDestArray
  125. inline void CopyElements(T * pDestArray, DWORD dwIndex, DWORD dwNumElements);
  126. //copy all the elements from the bag to pDestArray
  127. void CopyAllElements(T * pDestArray)
  128. { CopyElements(pDestArray, 0, m_dwTopFreeSlot); };
  129. /*
  130. * Searching Bag
  131. */
  132. //find an instance of 'elem' in bag. If found returns TRUE
  133. //and sets 'pdwIndex' to index of element
  134. BOOL FindElement(const T& elem, DWORD * pdwIndex) const;
  135. //returns TRUE if 'elem' is present in bag
  136. BOOL IsElementPresent(const T& elem) const
  137. { DWORD dwIndex; return (FindElement(elem, &dwIndex)); };
  138. protected:
  139. CAutoArray<T> m_data;
  140. DWORD m_dwTopFreeSlot;
  141. };
  142. /*
  143. * Specialisation of CBagArray for handling pointers
  144. * If you ever need to declare a bag of pointers (e.g. char *)
  145. * declare it as an CBagPtrArray (e.g. CBagPtrArray<char *>).
  146. * This specilisation uses a CBagArray<void *> underneath and hence
  147. * re-uses the same code between all types of CBagPtrArray.
  148. */
  149. template <class T> class CBagPtrArray : public CBagArray<void *>
  150. {
  151. public:
  152. typedef T Entry;
  153. typedef CBagArray<void * > Base;
  154. CBagPtrArray(DWORD dwSizeMultiple=16) : CBagArray<void*>(dwSizeMultiple)
  155. { };
  156. BOOL AddElement(T elem)
  157. { return Base::AddElement((void * ) elem); };
  158. BOOL AddElements(const T * pElems, DWORD dwNumElem)
  159. { return Base::AddElements((void** ) pElems, dwNumElem); };
  160. BOOL AddElements(const CBagArray<T>& bag)
  161. { return Base::AddElements((CBagArray<void*>&) bag); };
  162. void AddElementNoCheck(T elem)
  163. { return Base::AddElementNoCheck((void * ) elem); };
  164. BOOL RemoveElementByValue(T elem)
  165. { return Base::RemoveElementByValue((void * ) elem); };
  166. T GetElementValue(DWORD dwIndex) const
  167. { return (T ) m_data.GetElementValue(dwIndex); };
  168. T& GetElementRef(DWORD dwIndex)
  169. { return (T& ) m_data.GetElementRef(dwIndex); };
  170. const T& GetElementRef(DWORD dwIndex) const
  171. { return (const T&) m_data.GetElementRef(dwIndex); };
  172. T * GetElementPtr(DWORD dwIndex)
  173. { return (T* ) m_data.GetElementPtr(dwIndex); };
  174. T * GetAllElements()
  175. { return (T* ) m_data.GetAllElements(); };
  176. BOOL FindElement(T elem, DWORD * pdwIndex) const
  177. { return Base::FindElement((void*) elem, pdwIndex); };
  178. BOOL IsElementPresent(T elem) const
  179. { DWORD dwIndex; return (Base::FindElement((void * ) elem, &dwIndex)); };
  180. };
  181. /*
  182. * Inline methods for CBagArray
  183. */
  184. template <class T>
  185. void CBagArray<T>::RemoveElementByIndex(DWORD dwIndex)
  186. {
  187. DNASSERT(dwIndex<m_dwTopFreeSlot);
  188. m_dwTopFreeSlot--;
  189. if (dwIndex!=m_dwTopFreeSlot)
  190. m_data.SetExistingElement(dwIndex, m_data.GetElementRef(m_dwTopFreeSlot));
  191. }
  192. template <class T>
  193. void CBagArray<T>::CopyElements(T * pDestArray, DWORD dwIndex, DWORD dwNumElements)
  194. {
  195. DNASSERT(dwIndex+dwNumElements<=m_dwTopFreeSlot);
  196. T * pScan=m_data.GetElementPtr(dwIndex);
  197. T * pEndScan=pScan+dwNumElements;
  198. while (pScan!=pEndScan)
  199. *pDestArray++=*pScan++;
  200. }
  201. /*
  202. * If not building with explicit template instantiation then also
  203. * include all other methods for CBagArray
  204. */
  205. #ifndef DPNBUILD_EXPLICIT_TEMPLATES
  206. #include "BagArray.inl"
  207. #endif
  208. #endif //#ifndef __CBAGARRAY_H__