array_w.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 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. #ifdef AFX_COLL_SEG
  20. #pragma code_seg(AFX_COLL_SEG)
  21. #endif
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26. #define new DEBUG_NEW
  27. /////////////////////////////////////////////////////////////////////////////
  28. CWordArray::CWordArray()
  29. {
  30. m_pData = NULL;
  31. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  32. }
  33. CWordArray::~CWordArray()
  34. {
  35. ASSERT_VALID(this);
  36. delete[] (BYTE*)m_pData;
  37. }
  38. void CWordArray::SetSize(int nNewSize, int nGrowBy)
  39. {
  40. ASSERT_VALID(this);
  41. ASSERT(nNewSize >= 0);
  42. if (nGrowBy != -1)
  43. m_nGrowBy = nGrowBy; // set new size
  44. if (nNewSize == 0)
  45. {
  46. // shrink to nothing
  47. delete[] (BYTE*)m_pData;
  48. m_pData = NULL;
  49. m_nSize = m_nMaxSize = 0;
  50. }
  51. else if (m_pData == NULL)
  52. {
  53. // create one with exact size
  54. #ifdef SIZE_T_MAX
  55. ASSERT(nNewSize <= SIZE_T_MAX/sizeof(WORD)); // no overflow
  56. #endif
  57. m_pData = (WORD*) new BYTE[nNewSize * sizeof(WORD)];
  58. memset(m_pData, 0, nNewSize * sizeof(WORD)); // zero fill
  59. m_nSize = m_nMaxSize = nNewSize;
  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(WORD));
  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(WORD)); // no overflow
  89. #endif
  90. WORD* pNewData = (WORD*) new BYTE[nNewMax * sizeof(WORD)];
  91. // copy new data from old
  92. memcpy(pNewData, m_pData, m_nSize * sizeof(WORD));
  93. // construct remaining elements
  94. ASSERT(nNewSize > m_nSize);
  95. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(WORD));
  96. // get rid of old stuff (note: no destructors called)
  97. delete[] (BYTE*)m_pData;
  98. m_pData = pNewData;
  99. m_nSize = nNewSize;
  100. m_nMaxSize = nNewMax;
  101. }
  102. }
  103. int CWordArray::Append(const CWordArray& src)
  104. {
  105. ASSERT_VALID(this);
  106. ASSERT(this != &src); // cannot append to itself
  107. int nOldSize = m_nSize;
  108. SetSize(m_nSize + src.m_nSize);
  109. memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(WORD));
  110. return nOldSize;
  111. }
  112. void CWordArray::Copy(const CWordArray& src)
  113. {
  114. ASSERT_VALID(this);
  115. ASSERT(this != &src); // cannot append to itself
  116. SetSize(src.m_nSize);
  117. memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(WORD));
  118. }
  119. void CWordArray::FreeExtra()
  120. {
  121. ASSERT_VALID(this);
  122. if (m_nSize != m_nMaxSize)
  123. {
  124. // shrink to desired size
  125. #ifdef SIZE_T_MAX
  126. ASSERT(m_nSize <= SIZE_T_MAX/sizeof(WORD)); // no overflow
  127. #endif
  128. WORD* pNewData = NULL;
  129. if (m_nSize != 0)
  130. {
  131. pNewData = (WORD*) new BYTE[m_nSize * sizeof(WORD)];
  132. // copy new data from old
  133. memcpy(pNewData, m_pData, m_nSize * sizeof(WORD));
  134. }
  135. // get rid of old stuff (note: no destructors called)
  136. delete[] (BYTE*)m_pData;
  137. m_pData = pNewData;
  138. m_nMaxSize = m_nSize;
  139. }
  140. }
  141. /////////////////////////////////////////////////////////////////////////////
  142. void CWordArray::SetAtGrow(int nIndex, WORD newElement)
  143. {
  144. ASSERT_VALID(this);
  145. ASSERT(nIndex >= 0);
  146. if (nIndex >= m_nSize)
  147. SetSize(nIndex+1);
  148. m_pData[nIndex] = newElement;
  149. }
  150. void CWordArray::InsertAt(int nIndex, WORD newElement, int nCount)
  151. {
  152. ASSERT_VALID(this);
  153. ASSERT(nIndex >= 0); // will expand to meet need
  154. ASSERT(nCount > 0); // zero or negative size not allowed
  155. if (nIndex >= m_nSize)
  156. {
  157. // adding after the end of the array
  158. SetSize(nIndex + nCount); // grow so nIndex is valid
  159. }
  160. else
  161. {
  162. // inserting in the middle of the array
  163. int nOldSize = m_nSize;
  164. SetSize(m_nSize + nCount); // grow it to new size
  165. // shift old data up to fill gap
  166. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  167. (nOldSize-nIndex) * sizeof(WORD));
  168. // re-init slots we copied from
  169. memset(&m_pData[nIndex], 0, nCount * sizeof(WORD));
  170. }
  171. // insert new value in the gap
  172. ASSERT(nIndex + nCount <= m_nSize);
  173. // copy elements into the empty space
  174. while (nCount--)
  175. m_pData[nIndex++] = newElement;
  176. }
  177. void CWordArray::RemoveAt(int nIndex, int nCount)
  178. {
  179. ASSERT_VALID(this);
  180. ASSERT(nIndex >= 0);
  181. ASSERT(nCount >= 0);
  182. ASSERT(nIndex + nCount <= m_nSize);
  183. // just remove a range
  184. int nMoveCount = m_nSize - (nIndex + nCount);
  185. if (nMoveCount)
  186. memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
  187. nMoveCount * sizeof(WORD));
  188. m_nSize -= nCount;
  189. }
  190. void CWordArray::InsertAt(int nStartIndex, CWordArray* pNewArray)
  191. {
  192. ASSERT_VALID(this);
  193. ASSERT(pNewArray != NULL);
  194. ASSERT_KINDOF(CWordArray, pNewArray);
  195. ASSERT_VALID(pNewArray);
  196. ASSERT(nStartIndex >= 0);
  197. if (pNewArray->GetSize() > 0)
  198. {
  199. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  200. for (int i = 0; i < pNewArray->GetSize(); i++)
  201. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  202. }
  203. }
  204. /////////////////////////////////////////////////////////////////////////////
  205. // Serialization
  206. void CWordArray::Serialize(CArchive& ar)
  207. {
  208. ASSERT_VALID(this);
  209. CObject::Serialize(ar);
  210. if (ar.IsStoring())
  211. {
  212. ar.WriteCount(m_nSize);
  213. #ifdef _AFX_BYTESWAP
  214. if (!ar.IsByteSwapping())
  215. #endif
  216. ar.Write(m_pData, m_nSize * sizeof(WORD));
  217. #ifdef _AFX_BYTESWAP
  218. else
  219. {
  220. // write each item individually so that it will be byte-swapped
  221. for (int i = 0; i < m_nSize; i++)
  222. ar << m_pData[i];
  223. }
  224. #endif
  225. }
  226. else
  227. {
  228. DWORD nOldSize = ar.ReadCount();
  229. SetSize(nOldSize);
  230. ar.Read(m_pData, m_nSize * sizeof(WORD));
  231. #ifdef _AFX_BYTESWAP
  232. if (ar.IsByteSwapping())
  233. {
  234. for (int i = 0; i < m_nSize; i++)
  235. _AfxByteSwap(m_pData[i], (BYTE*)&m_pData[i]);
  236. }
  237. #endif
  238. }
  239. }
  240. /////////////////////////////////////////////////////////////////////////////
  241. // Diagnostics
  242. #ifdef _DEBUG
  243. void CWordArray::Dump(CDumpContext& dc) const
  244. {
  245. CObject::Dump(dc);
  246. dc << "with " << m_nSize << " elements";
  247. if (dc.GetDepth() > 0)
  248. {
  249. for (int i = 0; i < m_nSize; i++)
  250. dc << "\n\t[" << i << "] = " << m_pData[i];
  251. }
  252. dc << "\n";
  253. }
  254. void CWordArray::AssertValid() const
  255. {
  256. CObject::AssertValid();
  257. if (m_pData == NULL)
  258. {
  259. ASSERT(m_nSize == 0);
  260. ASSERT(m_nMaxSize == 0);
  261. }
  262. else
  263. {
  264. ASSERT(m_nSize >= 0);
  265. ASSERT(m_nMaxSize >= 0);
  266. ASSERT(m_nSize <= m_nMaxSize);
  267. ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(WORD)));
  268. }
  269. }
  270. #endif //_DEBUG
  271. #ifdef AFX_INIT_SEG
  272. #pragma code_seg(AFX_INIT_SEG)
  273. #endif
  274. IMPLEMENT_SERIAL(CWordArray, CObject, 0)
  275. /////////////////////////////////////////////////////////////////////////////