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.

264 lines
6.2 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: ArrayPtr.h
  4. //
  5. // Module: CMMON32.EXE
  6. //
  7. // Synopsis: Implement class CPtrArray, a array of void*, which grows dynamicly
  8. // This class is exactly the same as the one defined by MFC.
  9. // Help on the class also comes with vc help
  10. //
  11. // Copyright (c) 1998-1999 Microsoft Corporation
  12. //
  13. // Author: fengsun Created 2/17/98
  14. //
  15. //+----------------------------------------------------------------------------
  16. #include "cmmaster.h"
  17. #include "ArrayPtr.h"
  18. CPtrArray::CPtrArray()
  19. {
  20. m_pData = NULL;
  21. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  22. }
  23. CPtrArray::~CPtrArray()
  24. {
  25. ASSERT_VALID(this);
  26. delete [] (BYTE*)m_pData;
  27. }
  28. void CPtrArray::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  29. {
  30. ASSERT_VALID(this);
  31. MYDBGASSERT(nNewSize >= 0);
  32. if (nGrowBy != -1)
  33. {
  34. m_nGrowBy = nGrowBy; // set new size
  35. }
  36. if (nNewSize == 0)
  37. {
  38. // shrink to nothing
  39. delete [] (BYTE*)m_pData;
  40. m_pData = NULL;
  41. m_nSize = m_nMaxSize = 0;
  42. }
  43. else if (m_pData == NULL)
  44. {
  45. // create one with exact size
  46. m_pData = (void**) new BYTE[nNewSize * sizeof(void*)];
  47. if (m_pData)
  48. {
  49. memset(m_pData, 0, nNewSize * sizeof(void*)); // zero fill
  50. m_nSize = m_nMaxSize = nNewSize;
  51. }
  52. }
  53. else if (nNewSize <= m_nMaxSize)
  54. {
  55. // it fits
  56. if (m_pData)
  57. {
  58. if (nNewSize > m_nSize)
  59. {
  60. void* pElement = m_pData[m_nSize];
  61. if (pElement)
  62. {
  63. // initialize the new elements
  64. memset(&pElement, 0, (nNewSize-m_nSize) * sizeof(void*));
  65. }
  66. }
  67. m_nSize = nNewSize;
  68. }
  69. }
  70. else
  71. {
  72. // Otherwise grow array
  73. int nNewMax;
  74. if (nNewSize < m_nMaxSize + m_nGrowBy)
  75. {
  76. nNewMax = m_nMaxSize + m_nGrowBy; // granularity
  77. }
  78. else
  79. {
  80. nNewMax = nNewSize; // no slush
  81. }
  82. void** pNewData = (void**) new BYTE[nNewMax * sizeof(void*)];
  83. if (pNewData && m_pData)
  84. {
  85. // copy new data from old
  86. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  87. // construct remaining elements
  88. MYDBGASSERT(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. }
  98. void CPtrArray::FreeExtra()
  99. {
  100. ASSERT_VALID(this);
  101. if (m_pData && (m_nSize != m_nMaxSize))
  102. {
  103. // shrink to desired size
  104. void** pNewData = NULL;
  105. if (m_nSize != 0)
  106. {
  107. pNewData = (void**) new BYTE[m_nSize * sizeof(void*)];
  108. if (pNewData)
  109. {
  110. // copy new data from old
  111. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  112. // get rid of old stuff (note: no destructors called)
  113. delete [] (BYTE*)m_pData;
  114. m_pData = pNewData;
  115. m_nMaxSize = m_nSize;
  116. }
  117. }
  118. else
  119. {
  120. // get rid of old stuff (note: no destructors called)
  121. delete [] (BYTE*)m_pData;
  122. m_pData = pNewData;
  123. m_nMaxSize = m_nSize;
  124. }
  125. }
  126. }
  127. /////////////////////////////////////////////////////////////////////////////
  128. void CPtrArray::SetAtGrow(int nIndex, void* newElement)
  129. {
  130. ASSERT_VALID(this);
  131. MYDBGASSERT(nIndex >= 0);
  132. if (nIndex >= m_nSize)
  133. {
  134. SetSize(nIndex+1);
  135. }
  136. if (m_pData)
  137. {
  138. m_pData[nIndex] = newElement;
  139. }
  140. }
  141. void CPtrArray::InsertAt(int nIndex, void* newElement, int nCount /*=1*/)
  142. {
  143. ASSERT_VALID(this);
  144. MYDBGASSERT(nIndex >= 0); // will expand to meet need
  145. MYDBGASSERT(nCount > 0); // zero or negative size not allowed
  146. if (nIndex >= m_nSize)
  147. {
  148. // adding after the end of the array
  149. SetSize(nIndex + nCount); // grow so nIndex is valid
  150. }
  151. else
  152. {
  153. // inserting in the middle of the array
  154. int nOldSize = m_nSize;
  155. SetSize(m_nSize + nCount); // grow it to new size
  156. // shift old data up to fill gap
  157. if (m_pData)
  158. {
  159. CmMoveMemory(&m_pData[nIndex+nCount], &m_pData[nIndex], (nOldSize-nIndex) * sizeof(void*));
  160. // re-init slots we copied from
  161. memset(&m_pData[nIndex], 0, nCount * sizeof(void*));
  162. }
  163. }
  164. // insert new value in the gap
  165. MYDBGASSERT(nIndex + nCount <= m_nSize);
  166. while (m_pData && nCount--)
  167. {
  168. m_pData[nIndex++] = newElement;
  169. }
  170. }
  171. void CPtrArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  172. {
  173. ASSERT_VALID(this);
  174. MYDBGASSERT(nIndex >= 0);
  175. MYDBGASSERT(nCount >= 0);
  176. MYDBGASSERT(nIndex + nCount <= m_nSize);
  177. if ((NULL == m_pData) || (nCount < 0) || (nIndex < 0) || ((nIndex + nCount) > m_nSize))
  178. {
  179. return;
  180. }
  181. // just remove a range
  182. int nMoveCount = m_nSize - (nIndex + nCount);
  183. if (nMoveCount)
  184. {
  185. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount], nMoveCount * sizeof(void*));
  186. }
  187. m_nSize -= nCount;
  188. }
  189. void CPtrArray::InsertAt(int nStartIndex, CPtrArray* pNewArray)
  190. {
  191. ASSERT_VALID(this);
  192. MYDBGASSERT(pNewArray != NULL);
  193. ASSERT_VALID(pNewArray);
  194. MYDBGASSERT(nStartIndex >= 0);
  195. if (pNewArray && (pNewArray->GetSize() > 0))
  196. {
  197. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  198. for (int i = 0; i < pNewArray->GetSize(); i++)
  199. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  200. }
  201. }
  202. /////////////////////////////////////////////////////////////////////////////
  203. // Diagnostics
  204. #ifdef DEBUG
  205. void CPtrArray::AssertValid() const
  206. {
  207. if (m_pData == NULL)
  208. {
  209. MYDBGASSERT(m_nSize == 0 && m_nMaxSize == 0);
  210. }
  211. else
  212. {
  213. MYDBGASSERT(m_nSize >= 0);
  214. MYDBGASSERT(m_nMaxSize >= 0);
  215. MYDBGASSERT(m_nSize <= m_nMaxSize);
  216. MYDBGASSERT(!IsBadReadPtr(m_pData, m_nMaxSize * sizeof(void*)));
  217. }
  218. }
  219. #endif