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.

286 lines
6.3 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /*********************************************************************************************
  3. *
  4. *
  5. * Module Name:
  6. *
  7. * Ptrarray.cpp
  8. *
  9. * Abstract:
  10. * This is file has implementation of CPtrArray class borrowed from MFC
  11. *
  12. * Author:
  13. *
  14. *
  15. * Revision:
  16. *
  17. *
  18. ************************************************************************************************/
  19. #include "stdafx.h"
  20. #include "PtrArray.h"
  21. #include <windows.h>
  22. #include <assert.h>
  23. CPtrArray::CPtrArray()
  24. {
  25. m_pData = NULL;
  26. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  27. }
  28. CPtrArray::~CPtrArray()
  29. {
  30. delete[] (BYTE*)m_pData;
  31. }
  32. void CPtrArray::SetSize(int nNewSize, int nGrowBy)
  33. {
  34. assert(nNewSize >= 0);
  35. if (nGrowBy != -1)
  36. m_nGrowBy = nGrowBy; // set new size
  37. if (nNewSize == 0)
  38. {
  39. // shrink to nothing
  40. delete[] (BYTE*)m_pData;
  41. m_pData = NULL;
  42. m_nSize = m_nMaxSize = 0;
  43. }
  44. else if (m_pData == NULL)
  45. {
  46. // create one with exact size
  47. #ifdef SIZE_T_MAX
  48. assert(nNewSize <= SIZE_T_MAX/sizeof(void*)); // no overflow
  49. #endif
  50. m_pData = (void**) new BYTE[nNewSize * sizeof(void*)];
  51. if( m_pData != NULL )
  52. {
  53. memset(m_pData, 0, nNewSize * sizeof(void*)); // zero fill
  54. m_nSize = m_nMaxSize = nNewSize;
  55. }
  56. else
  57. {
  58. m_nSize = m_nMaxSize = 0;
  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. nNewMax = m_nMaxSize + nGrowBy; // granularity
  84. else
  85. nNewMax = nNewSize; // no slush
  86. assert(nNewMax >= m_nMaxSize); // no wrap around
  87. #ifdef SIZE_T_MAX
  88. assert(nNewMax <= SIZE_T_MAX/sizeof(void*)); // no overflow
  89. #endif
  90. void** pNewData = (void**) new BYTE[nNewMax * sizeof(void*)];
  91. // copy new data from old
  92. if( pNewData != NULL )
  93. {
  94. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  95. // construct remaining elements
  96. assert(nNewSize > m_nSize);
  97. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  98. // get rid of old stuff (note: no destructors called)
  99. delete[] (BYTE*)m_pData;
  100. m_pData = pNewData;
  101. m_nSize = nNewSize;
  102. m_nMaxSize = nNewMax;
  103. }
  104. }
  105. }
  106. int CPtrArray::Append(const CPtrArray& src)
  107. {
  108. assert(this != &src); // cannot append to itself
  109. int nOldSize = m_nSize;
  110. SetSize(m_nSize + src.m_nSize);
  111. memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(void*));
  112. return nOldSize;
  113. }
  114. void CPtrArray::Copy(const CPtrArray& src)
  115. {
  116. assert(this != &src); // cannot append to itself
  117. SetSize(src.m_nSize);
  118. if( m_pData != NULL )
  119. {
  120. memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(void*));
  121. }
  122. }
  123. void CPtrArray::FreeExtra()
  124. {
  125. if (m_nSize != m_nMaxSize)
  126. {
  127. // shrink to desired size
  128. #ifdef SIZE_T_MAX
  129. assert(m_nSize <= SIZE_T_MAX/sizeof(void*)); // no overflow
  130. #endif
  131. void** pNewData = NULL;
  132. if (m_nSize != 0)
  133. {
  134. pNewData = (void**) new BYTE[m_nSize * sizeof(void*)];
  135. // copy new data from old
  136. if( pNewData != NULL )
  137. {
  138. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  139. }
  140. else
  141. {
  142. m_nSize = 0;
  143. }
  144. }
  145. // get rid of old stuff (note: no destructors called)
  146. delete[] (BYTE*)m_pData;
  147. m_pData = pNewData;
  148. m_nMaxSize = m_nSize;
  149. }
  150. }
  151. /////////////////////////////////////////////////////////////////////////////
  152. void CPtrArray::SetAtGrow(int nIndex, void* newElement)
  153. {
  154. assert(nIndex >= 0);
  155. if (nIndex >= m_nSize)
  156. {
  157. SetSize(nIndex+1);
  158. }
  159. if( m_pData != NULL )
  160. {
  161. m_pData[nIndex] = newElement;
  162. }
  163. }
  164. void CPtrArray::InsertAt(int nIndex, void* newElement, int nCount)
  165. {
  166. assert(nIndex >= 0); // will expand to meet need
  167. assert(nCount > 0); // zero or negative size not allowed
  168. if (nIndex >= m_nSize)
  169. {
  170. // adding after the end of the array
  171. SetSize(nIndex + nCount); // grow so nIndex is valid
  172. }
  173. else
  174. {
  175. // inserting in the middle of the array
  176. int nOldSize = m_nSize;
  177. SetSize(m_nSize + nCount); // grow it to new size
  178. // shift old data up to fill gap
  179. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  180. (nOldSize-nIndex) * sizeof(void*));
  181. // re-init slots we copied from
  182. memset(&m_pData[nIndex], 0, nCount * sizeof(void*));
  183. }
  184. // insert new value in the gap
  185. assert(nIndex + nCount <= m_nSize);
  186. while (nCount--)
  187. m_pData[nIndex++] = newElement;
  188. }
  189. void CPtrArray::RemoveAt(int nIndex, int nCount)
  190. {
  191. assert(nIndex >= 0);
  192. assert(nCount >= 0);
  193. assert(nIndex + nCount <= m_nSize);
  194. // just remove a range
  195. int nMoveCount = m_nSize - (nIndex + nCount);
  196. if (nMoveCount)
  197. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  198. nMoveCount * sizeof(void*));
  199. m_nSize -= nCount;
  200. }
  201. void CPtrArray::InsertAt(int nStartIndex, CPtrArray* pNewArray)
  202. {
  203. assert(pNewArray != NULL);
  204. assert(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. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  210. }
  211. }
  212. int CPtrArray::GetSize() const
  213. { return m_nSize; }
  214. int CPtrArray::GetUpperBound() const
  215. { return m_nSize-1; }
  216. void CPtrArray::RemoveAll()
  217. { SetSize(0); }
  218. void* CPtrArray::GetAt(int nIndex) const
  219. { assert(nIndex >= 0 && nIndex < m_nSize);
  220. return m_pData[nIndex]; }
  221. void CPtrArray::SetAt(int nIndex, void* newElement)
  222. { assert(nIndex >= 0 && nIndex < m_nSize);
  223. m_pData[nIndex] = newElement; }
  224. void*& CPtrArray::ElementAt(int nIndex)
  225. { assert(nIndex >= 0 && nIndex < m_nSize);
  226. return m_pData[nIndex]; }
  227. const void** CPtrArray::GetData() const
  228. { return (const void**)m_pData; }
  229. void** CPtrArray::GetData()
  230. { return (void**)m_pData; }
  231. int CPtrArray::Add(void* newElement)
  232. { int nIndex = m_nSize;
  233. SetAtGrow(nIndex, newElement);
  234. return nIndex; }
  235. void* CPtrArray::operator[](int nIndex) const
  236. { return GetAt(nIndex); }
  237. void*& CPtrArray::operator[](int nIndex)
  238. { return ElementAt(nIndex); }