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.

346 lines
8.3 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright � Microsoft Corporation. All rights reserved.
  4. //
  5. // chptrarr.cpp
  6. //
  7. // Purpose: Non-MFC CPtrArray class implementation
  8. //
  9. //***************************************************************************
  10. //=================================================================
  11. // NOTE: we allocate an array of 'm_nMaxSize' elements, but only
  12. // the current size 'm_nSize' contains properly constructed
  13. // objects.
  14. //===============================================================
  15. #include "precomp.h"
  16. #pragma warning( disable : 4290 )
  17. #include <CHString.h>
  18. #include <chptrarr.h>
  19. #include <AssertBreak.h>
  20. CHPtrArray::CHPtrArray () : m_pData ( NULL ) ,
  21. m_nSize ( 0 ) ,
  22. m_nMaxSize ( 0 ) ,
  23. m_nGrowBy ( 0 )
  24. {
  25. }
  26. CHPtrArray::~CHPtrArray()
  27. {
  28. if ( m_pData )
  29. {
  30. delete [] (BYTE*) m_pData ;
  31. }
  32. }
  33. void CHPtrArray::SetSize(int nNewSize, int nGrowBy)
  34. {
  35. ASSERT_BREAK(nNewSize >= 0) ;
  36. if (nGrowBy != -1)
  37. {
  38. m_nGrowBy = nGrowBy ; // set new size
  39. }
  40. if (nNewSize == 0)
  41. {
  42. // shrink to nothing
  43. delete[] (BYTE*)m_pData ;
  44. m_pData = NULL ;
  45. m_nSize = m_nMaxSize = 0 ;
  46. }
  47. else if (m_pData == NULL)
  48. {
  49. // create one with exact size
  50. m_pData = (void**) new BYTE[nNewSize * sizeof(void*)] ;
  51. if ( m_pData )
  52. {
  53. memset(m_pData, 0, nNewSize * sizeof(void*)) ; // zero fill
  54. m_nSize = m_nMaxSize = nNewSize ;
  55. }
  56. else
  57. {
  58. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  59. }
  60. }
  61. else if (nNewSize <= m_nMaxSize)
  62. {
  63. // it fits
  64. if (nNewSize > m_nSize)
  65. {
  66. // initialize the new elements
  67. memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*)) ;
  68. }
  69. m_nSize = nNewSize ;
  70. }
  71. else
  72. {
  73. // otherwise, grow array
  74. int nGrowBy = m_nGrowBy ;
  75. if (nGrowBy == 0)
  76. {
  77. // heuristically determine growth when nGrowBy == 0
  78. // (this avoids heap fragmentation in many situations)
  79. nGrowBy = min(1024, max(4, m_nSize / 8)) ;
  80. }
  81. int nNewMax ;
  82. if (nNewSize < m_nMaxSize + nGrowBy)
  83. {
  84. nNewMax = m_nMaxSize + nGrowBy ; // granularity
  85. }
  86. else
  87. {
  88. nNewMax = nNewSize ; // no slush
  89. }
  90. ASSERT_BREAK(nNewMax >= m_nMaxSize) ; // no wrap around
  91. void** pNewData = (void**) new BYTE[nNewMax * sizeof(void*)] ;
  92. if ( pNewData )
  93. {
  94. // copy new data from old
  95. memcpy(pNewData, m_pData, m_nSize * sizeof(void*)) ;
  96. // construct remaining elements
  97. ASSERT_BREAK(nNewSize > m_nSize) ;
  98. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*)) ;
  99. // get rid of old stuff (note: no destructors called)
  100. delete[] (BYTE*)m_pData ;
  101. m_pData = pNewData ;
  102. m_nSize = nNewSize ;
  103. m_nMaxSize = nNewMax ;
  104. }
  105. else
  106. {
  107. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  108. }
  109. }
  110. }
  111. int CHPtrArray::Append(const CHPtrArray& src)
  112. {
  113. ASSERT_BREAK(this != &src) ; // cannot append to itself
  114. int nOldSize = m_nSize ;
  115. SetSize(m_nSize + src.m_nSize) ;
  116. memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(void*)) ;
  117. return nOldSize ;
  118. }
  119. void CHPtrArray::Copy(const CHPtrArray& src)
  120. {
  121. ASSERT_BREAK(this != &src) ; // cannot append to itself
  122. SetSize(src.m_nSize) ;
  123. memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(void*)) ;
  124. }
  125. void CHPtrArray::FreeExtra()
  126. {
  127. if (m_nSize != m_nMaxSize)
  128. {
  129. // shrink to desired size
  130. void** pNewData = NULL ;
  131. if (m_nSize != 0)
  132. {
  133. pNewData = (void**) new BYTE[m_nSize * sizeof(void*)] ;
  134. if ( pNewData )
  135. {
  136. // copy new data from old
  137. memcpy(pNewData, m_pData, m_nSize * sizeof(void*)) ;
  138. }
  139. else
  140. {
  141. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  142. }
  143. }
  144. // get rid of old stuff (note: no destructors called)
  145. delete[] (BYTE*)m_pData ;
  146. m_pData = pNewData ;
  147. m_nMaxSize = m_nSize ;
  148. }
  149. }
  150. /////////////////////////////////////////////////////////////////////////////
  151. void CHPtrArray::SetAtGrow(int nIndex, void* newElement)
  152. {
  153. ASSERT_BREAK(nIndex >= 0) ;
  154. if (nIndex >= m_nSize)
  155. {
  156. SetSize(nIndex+1) ;
  157. }
  158. m_pData[nIndex] = newElement ;
  159. }
  160. void CHPtrArray::InsertAt(int nIndex, void* newElement, int nCount)
  161. {
  162. ASSERT_BREAK(nIndex >= 0) ; // will expand to meet need
  163. ASSERT_BREAK(nCount > 0) ; // zero or negative size not allowed
  164. if (nIndex >= m_nSize)
  165. {
  166. // adding after the end of the array
  167. SetSize(nIndex + nCount) ; // grow so nIndex is valid
  168. }
  169. else
  170. {
  171. // inserting in the middle of the array
  172. int nOldSize = m_nSize ;
  173. SetSize(m_nSize + nCount) ; // grow it to new size
  174. // shift old data up to fill gap
  175. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  176. (nOldSize-nIndex) * sizeof(void*)) ;
  177. // re-init slots we copied from
  178. memset(&m_pData[nIndex], 0, nCount * sizeof(void*)) ;
  179. }
  180. // insert new value in the gap
  181. ASSERT_BREAK(nIndex + nCount <= m_nSize) ;
  182. while (nCount--)
  183. {
  184. m_pData[nIndex++] = newElement ;
  185. }
  186. }
  187. void CHPtrArray::RemoveAt(int nIndex, int nCount)
  188. {
  189. ASSERT_BREAK(nIndex >= 0) ;
  190. ASSERT_BREAK(nCount >= 0) ;
  191. ASSERT_BREAK(nIndex + nCount <= m_nSize) ;
  192. // just remove a range
  193. int nMoveCount = m_nSize - (nIndex + nCount) ;
  194. if (nMoveCount)
  195. {
  196. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  197. nMoveCount * sizeof(void*)) ;
  198. }
  199. m_nSize -= nCount ;
  200. }
  201. void CHPtrArray::InsertAt(int nStartIndex, CHPtrArray* pNewArray)
  202. {
  203. ASSERT_BREAK(pNewArray != NULL) ;
  204. ASSERT_BREAK(nStartIndex >= 0) ;
  205. if (pNewArray->GetSize() > 0)
  206. {
  207. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize()) ;
  208. for (int i = 0 ; i < pNewArray->GetSize() ; i++)
  209. {
  210. SetAt(nStartIndex + i, pNewArray->GetAt(i)) ;
  211. }
  212. }
  213. }
  214. // Inline functions (from CArray)
  215. //===============================
  216. inline int CHPtrArray::GetSize() const {
  217. return m_nSize ;
  218. }
  219. inline int CHPtrArray::GetUpperBound() const {
  220. return m_nSize-1 ;
  221. }
  222. inline void CHPtrArray::RemoveAll() {
  223. SetSize(0, -1) ;
  224. return ;
  225. }
  226. inline void *CHPtrArray::GetAt(int nIndex) const {
  227. ASSERT_BREAK(nIndex >= 0 && nIndex < m_nSize) ;
  228. return m_pData[nIndex] ;
  229. }
  230. inline void CHPtrArray::SetAt(int nIndex, void * newElement) {
  231. ASSERT_BREAK(nIndex >= 0 && nIndex < m_nSize) ;
  232. m_pData[nIndex] = newElement ;
  233. return ;
  234. }
  235. inline void *&CHPtrArray::ElementAt(int nIndex) {
  236. ASSERT_BREAK(nIndex >= 0 && nIndex < m_nSize) ;
  237. return m_pData[nIndex] ;
  238. }
  239. inline const void **CHPtrArray::GetData() const {
  240. return (const void **) m_pData ;
  241. }
  242. inline void **CHPtrArray::GetData() {
  243. return (void **) m_pData ;
  244. }
  245. inline int CHPtrArray::Add(void *newElement) {
  246. int nIndex = m_nSize ;
  247. SetAtGrow(nIndex, newElement) ;
  248. return nIndex ;
  249. }
  250. inline void *CHPtrArray::operator[](int nIndex) const {
  251. return GetAt(nIndex) ;
  252. }
  253. inline void *&CHPtrArray::operator[](int nIndex) {
  254. return ElementAt(nIndex) ;
  255. }
  256. // Diagnostics
  257. //============
  258. #ifdef _DEBUG
  259. void CHPtrArray::AssertValid() const
  260. {
  261. if (m_pData == NULL)
  262. {
  263. ASSERT_BREAK(m_nSize == 0) ;
  264. ASSERT_BREAK(m_nMaxSize == 0) ;
  265. }
  266. else
  267. {
  268. ASSERT_BREAK(m_nSize >= 0) ;
  269. ASSERT_BREAK(m_nMaxSize >= 0) ;
  270. ASSERT_BREAK(m_nSize <= m_nMaxSize) ;
  271. }
  272. }
  273. #endif //_DEBUG