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.

259 lines
4.3 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. DynArray.h
  5. Abstract:
  6. Implementation of a dynamic array
  7. History:
  8. a-dcrews 01-Mar-00 Created
  9. --*/
  10. #ifndef _DYNARRAY_H_
  11. #define _DYNARRAY_H_
  12. #include "cookerutils.h"
  13. #define WMI_DEFAULT_CACHE_SIZE 64
  14. enum enumCDynArrayExceptions
  15. {
  16. WMI_BOUNDARY_VIOLATION
  17. };
  18. class CDynArrayException
  19. {
  20. private:
  21. unsigned int nException;
  22. public:
  23. CDynArrayException(unsigned int n) : nException(n) {}
  24. ~CDynArrayException() {}
  25. unsigned int GetException() { return nException; }
  26. };
  27. /////////////////////////////////////////////////////////////////////////
  28. //
  29. //
  30. // CDynArray
  31. //
  32. //
  33. /////////////////////////////////////////////////////////////////////////
  34. template <class T>
  35. class CDynArray
  36. {
  37. BOOL m_bOK;
  38. HANDLE m_hHeap;
  39. T* m_aArray;
  40. DWORD m_dwSize; // The total size of the array
  41. DWORD m_dwUsage; //
  42. DWORD m_dwEnum;
  43. WMISTATUS Initialize();
  44. WMISTATUS Compact();
  45. public:
  46. CDynArray();
  47. virtual ~CDynArray();
  48. WMISTATUS Resize( DWORD dwSize );
  49. UINT GetCapacity(){ return m_dwSize; }
  50. UINT GetUsage(){ return m_dwUsage; }
  51. T& operator[]( DWORD dwIndex);
  52. WMISTATUS BeginEnum() { m_dwEnum = 0; return WBEM_NO_ERROR; }
  53. WMISTATUS Next( T* pData )
  54. {
  55. WMISTATUS dwStatus = WBEM_S_FALSE;
  56. while ( ( m_dwEnum >= 0 ) && ( m_dwEnum < m_dwSize ) )
  57. {
  58. if ( NULL != m_aArray[ m_dwEnum ] )
  59. {
  60. *pData = m_aArray[ m_dwEnum ];
  61. dwStatus = WBEM_NO_ERROR;
  62. m_dwEnum++;
  63. break;
  64. }
  65. else
  66. {
  67. m_dwEnum++;
  68. }
  69. }
  70. return dwStatus;
  71. }
  72. WMISTATUS EndEnum() { m_dwEnum = -1; return WBEM_NO_ERROR; }
  73. WMISTATUS Add( T Data, DWORD* pdwID );
  74. WMISTATUS Remove( DWORD dwID );
  75. };
  76. template <class T>
  77. CDynArray<T>::CDynArray() :
  78. m_hHeap( NULL ),
  79. m_dwSize( WMI_DEFAULT_CACHE_SIZE ),
  80. m_dwEnum( -1 )
  81. {
  82. m_bOK = SUCCEEDED( Initialize() );
  83. }
  84. template <class T>
  85. CDynArray<T>::~CDynArray()
  86. {
  87. try
  88. {
  89. HeapFree( m_hHeap, 0, m_aArray );
  90. HANDLE hHeap = GetProcessHeap();
  91. if (hHeap != m_hHeap){
  92. HeapDestroy(m_hHeap);
  93. }
  94. }
  95. catch(...)
  96. {
  97. // Just pass it along
  98. // ==================
  99. throw;
  100. }
  101. }
  102. template <class T>
  103. WMISTATUS CDynArray<T>::Initialize()
  104. {
  105. WMISTATUS dwStatus = WBEM_NO_ERROR;
  106. // Create our private heap
  107. // =======================
  108. try
  109. {
  110. m_hHeap = HeapCreate( HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE, 0, 0 );
  111. if ( NULL == m_hHeap )
  112. m_hHeap = GetProcessHeap();
  113. }
  114. catch(...)
  115. {
  116. dwStatus = WBEM_E_OUT_OF_MEMORY;
  117. }
  118. if ( SUCCEEDED( dwStatus ) )
  119. {
  120. // Initialize the array size
  121. // =========================
  122. try
  123. {
  124. m_aArray = (T*)HeapAlloc( m_hHeap, HEAP_ZERO_MEMORY, ( sizeof(T*) * m_dwSize ) );
  125. }
  126. catch(...)
  127. {
  128. dwStatus = WBEM_E_OUT_OF_MEMORY;
  129. }
  130. if ( NULL == m_aArray )
  131. {
  132. dwStatus = WBEM_E_OUT_OF_MEMORY;
  133. }
  134. }
  135. return dwStatus;
  136. }
  137. template <class T>
  138. WMISTATUS CDynArray<T>::Add( T Data, DWORD* pdwID )
  139. {
  140. WMISTATUS dwStatus = WBEM_E_FAILED;
  141. DWORD dwIndex = 0;
  142. for ( dwIndex = 0; dwIndex < m_dwSize; dwIndex++ )
  143. {
  144. if ( NULL == m_aArray[ dwIndex ] )
  145. {
  146. m_aArray[ dwIndex ] = Data;
  147. *pdwID = dwIndex;
  148. dwStatus = WBEM_NO_ERROR;
  149. m_dwUsage++;
  150. break;
  151. }
  152. }
  153. if ( dwStatus == WBEM_E_FAILED )
  154. {
  155. dwIndex = m_dwSize;
  156. dwStatus = Resize( m_dwSize + 8 );
  157. if ( SUCCEEDED( dwStatus ) )
  158. {
  159. m_aArray[ dwIndex ] = Data;
  160. *pdwID = dwIndex;
  161. dwStatus = WBEM_NO_ERROR;
  162. m_dwUsage++;
  163. }
  164. }
  165. return dwStatus;
  166. }
  167. template <class T>
  168. WMISTATUS CDynArray<T>::Remove( DWORD dwID )
  169. {
  170. WMISTATUS dwStatus = WBEM_NO_ERROR;
  171. m_aArray[ dwID ] = NULL;
  172. m_dwUsage--;
  173. return dwStatus;
  174. }
  175. template <class T>
  176. WMISTATUS CDynArray<T>::Resize( DWORD dwNewSize )
  177. {
  178. WMISTATUS dwStatus = WBEM_NO_ERROR;
  179. if ( !m_bOK )
  180. {
  181. dwStatus = WBEM_E_NOT_AVAILABLE;
  182. }
  183. else if ( dwNewSize == m_dwSize ) // If the requested size is the same as the current size, then we are done
  184. {
  185. dwStatus = WBEM_S_FALSE;
  186. }
  187. else if ( dwNewSize < m_dwUsage ) // Are we trying to shrink the array beyond it's current capacity?
  188. {
  189. dwStatus = WBEM_E_FAILED;
  190. }
  191. else
  192. {
  193. m_aArray = (T*)HeapReAlloc( m_hHeap, HEAP_ZERO_MEMORY, m_aArray, sizeof( T* ) * dwNewSize );
  194. m_dwSize = dwNewSize;
  195. }
  196. return dwStatus;
  197. }
  198. template<class T>
  199. T& CDynArray<T>::operator[]( DWORD dwIndex )
  200. {
  201. if ( m_bOK && ( 0 <= dwIndex ) && ( m_dwSize > dwIndex ) )
  202. return m_aArray[ dwIndex ];
  203. else
  204. throw CDynArrayException( WMI_BOUNDARY_VIOLATION );
  205. }
  206. #endif // _DYNARRAY_H_