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.

292 lines
6.7 KiB

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1995 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. /////////////////////////////////////////////////////////////////////////////
  11. //
  12. // Implementation of parameterized Array
  13. //
  14. /////////////////////////////////////////////////////////////////////////////
  15. // NOTE: we allocate an array of 'm_nMaxSize' elements, but only
  16. // the current size 'm_nSize' contains properly constructed
  17. // objects.
  18. #include "stdafx.h"
  19. SZTHISFILE
  20. #include "ARRAY_P.INL"
  21. /////////////////////////////////////////////////////////////////////////////
  22. CPtrArray::CPtrArray()
  23. {
  24. m_pData = NULL;
  25. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  26. }
  27. CPtrArray::~CPtrArray()
  28. {
  29. // ASSERT_VALID(this);
  30. delete[] (BYTE*)m_pData;
  31. }
  32. void CPtrArray::SetSize(int nNewSize, int nGrowBy)
  33. {
  34. // ASSERT_VALID(this);
  35. ASSERT_(nNewSize >= 0);
  36. if (nGrowBy != -1)
  37. m_nGrowBy = nGrowBy; // set new size
  38. if (nNewSize == 0)
  39. {
  40. // shrink to nothing
  41. delete[] (BYTE*)m_pData;
  42. m_pData = NULL;
  43. m_nSize = m_nMaxSize = 0;
  44. }
  45. else if (m_pData == NULL)
  46. {
  47. // create one with exact size
  48. #ifdef SIZE_T_MAX
  49. ASSERT_(nNewSize <= SIZE_T_MAX/sizeof(void*)); // no overflow
  50. #endif
  51. m_pData = (void**) new BYTE[nNewSize * sizeof(void*)];
  52. memset(m_pData, 0, nNewSize * sizeof(void*)); // zero fill
  53. m_nSize = m_nMaxSize = nNewSize;
  54. }
  55. else if (nNewSize <= m_nMaxSize)
  56. {
  57. // it fits
  58. if (nNewSize > m_nSize)
  59. {
  60. // initialize the new elements
  61. memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  62. }
  63. m_nSize = nNewSize;
  64. }
  65. else
  66. {
  67. // otherwise, grow array
  68. int nGrowBy = m_nGrowBy;
  69. if (nGrowBy == 0)
  70. {
  71. // heuristically determine growth when nGrowBy == 0
  72. // (this avoids heap fragmentation in many situations)
  73. nGrowBy = min(1024, max(4, m_nSize / 8));
  74. }
  75. int nNewMax;
  76. if (nNewSize < m_nMaxSize + nGrowBy)
  77. nNewMax = m_nMaxSize + nGrowBy; // granularity
  78. else
  79. nNewMax = nNewSize; // no slush
  80. ASSERT_(nNewMax >= m_nMaxSize); // no wrap around
  81. #ifdef SIZE_T_MAX
  82. ASSERT_(nNewMax <= SIZE_T_MAX/sizeof(void*)); // no overflow
  83. #endif
  84. void** pNewData = (void**) new BYTE[nNewMax * sizeof(void*)];
  85. // copy new data from old
  86. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  87. // construct remaining elements
  88. ASSERT_(nNewSize > m_nSize);
  89. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  90. // get rid of old stuff (note: no destructors called)
  91. delete[] (BYTE*)m_pData;
  92. m_pData = pNewData;
  93. m_nSize = nNewSize;
  94. m_nMaxSize = nNewMax;
  95. }
  96. }
  97. int CPtrArray::Append(const CPtrArray& src)
  98. {
  99. // ASSERT_VALID(this);
  100. ASSERT_(this != &src); // cannot append to itself
  101. int nOldSize = m_nSize;
  102. SetSize(m_nSize + src.m_nSize);
  103. memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(void*));
  104. return nOldSize;
  105. }
  106. void CPtrArray::Copy(const CPtrArray& src)
  107. {
  108. // ASSERT_VALID(this);
  109. ASSERT_(this != &src); // cannot append to itself
  110. SetSize(src.m_nSize);
  111. memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(void*));
  112. }
  113. void CPtrArray::FreeExtra()
  114. {
  115. // ASSERT_VALID(this);
  116. if (m_nSize != m_nMaxSize)
  117. {
  118. // shrink to desired size
  119. #ifdef SIZE_T_MAX
  120. ASSERT_(m_nSize <= SIZE_T_MAX/sizeof(void*)); // no overflow
  121. #endif
  122. void** pNewData = NULL;
  123. if (m_nSize != 0)
  124. {
  125. pNewData = (void**) new BYTE[m_nSize * sizeof(void*)];
  126. // copy new data from old
  127. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  128. }
  129. // get rid of old stuff (note: no destructors called)
  130. delete[] (BYTE*)m_pData;
  131. m_pData = pNewData;
  132. m_nMaxSize = m_nSize;
  133. }
  134. }
  135. /////////////////////////////////////////////////////////////////////////////
  136. void CPtrArray::SetAtGrow(int nIndex, void* newElement)
  137. {
  138. // ASSERT_VALID(this);
  139. ASSERT_(nIndex >= 0);
  140. if (nIndex >= m_nSize)
  141. SetSize(nIndex+1);
  142. m_pData[nIndex] = newElement;
  143. }
  144. void CPtrArray::InsertAt(int nIndex, void* newElement, int nCount)
  145. {
  146. // ASSERT_VALID(this);
  147. ASSERT_(nIndex >= 0); // will expand to meet need
  148. ASSERT_(nCount > 0); // zero or negative size not allowed
  149. if (nIndex >= m_nSize)
  150. {
  151. // adding after the end of the array
  152. SetSize(nIndex + nCount); // grow so nIndex is valid
  153. }
  154. else
  155. {
  156. // inserting in the middle of the array
  157. int nOldSize = m_nSize;
  158. SetSize(m_nSize + nCount); // grow it to new size
  159. // shift old data up to fill gap
  160. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  161. (nOldSize-nIndex) * sizeof(void*));
  162. // re-init slots we copied from
  163. memset(&m_pData[nIndex], 0, nCount * sizeof(void*));
  164. }
  165. // insert new value in the gap
  166. ASSERT_(nIndex + nCount <= m_nSize);
  167. while (nCount--)
  168. m_pData[nIndex++] = newElement;
  169. }
  170. void CPtrArray::RemoveAt(int nIndex, int nCount)
  171. {
  172. // ASSERT_VALID(this);
  173. ASSERT_(nIndex >= 0);
  174. ASSERT_(nCount >= 0);
  175. ASSERT_(nIndex + nCount <= m_nSize);
  176. // just remove a range
  177. int nMoveCount = m_nSize - (nIndex + nCount);
  178. if (nMoveCount)
  179. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  180. nMoveCount * sizeof(void*));
  181. m_nSize -= nCount;
  182. }
  183. void CPtrArray::InsertAt(int nStartIndex, CPtrArray* pNewArray)
  184. {
  185. // ASSERT_VALID(this);
  186. ASSERT_(pNewArray != NULL);
  187. // ASSERT_KINDOF(CPtrArray, pNewArray);
  188. // ASSERT_VALID(pNewArray);
  189. ASSERT_(nStartIndex >= 0);
  190. if (pNewArray->GetSize() > 0)
  191. {
  192. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  193. for (int i = 0; i < pNewArray->GetSize(); i++)
  194. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  195. }
  196. }
  197. /////////////////////////////////////////////////////////////////////////////
  198. // Diagnostics
  199. /*
  200. #ifdef _DEBUG
  201. void CPtrArray::Dump(CDumpContext& dc) const
  202. {
  203. CObject::Dump(dc);
  204. dc << "with " << m_nSize << " elements";
  205. if (dc.GetDepth() > 0)
  206. {
  207. for (int i = 0; i < m_nSize; i++)
  208. dc << "\n\t[" << i << "] = " << m_pData[i];
  209. }
  210. dc << "\n";
  211. }
  212. void CPtrArray::AssertValid() const
  213. {
  214. CObject::AssertValid();
  215. if (m_pData == NULL)
  216. {
  217. ASSERT_(m_nSize == 0);
  218. ASSERT_(m_nMaxSize == 0);
  219. }
  220. else
  221. {
  222. ASSERT_(m_nSize >= 0);
  223. ASSERT_(m_nMaxSize >= 0);
  224. ASSERT_(m_nSize <= m_nMaxSize);
  225. ASSERT_(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(void*)));
  226. }
  227. }
  228. #endif //_DEBUG
  229. #ifdef AFX_INIT_SEG
  230. #pragma code_seg(AFX_INIT_SEG)
  231. #endif
  232. IMPLEMENT_DYNAMIC(CPtrArray, CObject)
  233. */
  234. /////////////////////////////////////////////////////////////////////////////