array_s.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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. #include "elements.h" // used for special creation
  29. static void ConstructElements(CString* pNewData, int nCount)
  30. {
  31. ASSERT(nCount >= 0);
  32. while (nCount--)
  33. {
  34. ConstructElement(pNewData);
  35. pNewData++;
  36. }
  37. }
  38. static void DestructElements(CString* pOldData, int nCount)
  39. {
  40. ASSERT(nCount >= 0);
  41. while (nCount--)
  42. {
  43. DestructElement(pOldData);
  44. pOldData++;
  45. }
  46. }
  47. static void CopyElements(CString* pDest, CString* pSrc, int nCount)
  48. {
  49. ASSERT(nCount >= 0);
  50. while (nCount--)
  51. {
  52. *pDest = *pSrc;
  53. ++pDest;
  54. ++pSrc;
  55. }
  56. }
  57. /////////////////////////////////////////////////////////////////////////////
  58. CStringArray::CStringArray()
  59. {
  60. m_pData = NULL;
  61. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  62. }
  63. CStringArray::~CStringArray()
  64. {
  65. ASSERT_VALID(this);
  66. DestructElements(m_pData, m_nSize);
  67. delete[] (BYTE*)m_pData;
  68. }
  69. void CStringArray::SetSize(int nNewSize, int nGrowBy)
  70. {
  71. ASSERT_VALID(this);
  72. ASSERT(nNewSize >= 0);
  73. if (nGrowBy != -1)
  74. m_nGrowBy = nGrowBy; // set new size
  75. if (nNewSize == 0)
  76. {
  77. // shrink to nothing
  78. DestructElements(m_pData, m_nSize);
  79. delete[] (BYTE*)m_pData;
  80. m_pData = NULL;
  81. m_nSize = m_nMaxSize = 0;
  82. }
  83. else if (m_pData == NULL)
  84. {
  85. // create one with exact size
  86. #ifdef SIZE_T_MAX
  87. ASSERT(nNewSize <= SIZE_T_MAX/sizeof(CString)); // no overflow
  88. #endif
  89. m_pData = (CString*) new BYTE[nNewSize * sizeof(CString)];
  90. ConstructElements(m_pData, nNewSize);
  91. m_nSize = m_nMaxSize = nNewSize;
  92. }
  93. else if (nNewSize <= m_nMaxSize)
  94. {
  95. // it fits
  96. if (nNewSize > m_nSize)
  97. {
  98. // initialize the new elements
  99. ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
  100. }
  101. else if (m_nSize > nNewSize) // destroy the old elements
  102. DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
  103. m_nSize = nNewSize;
  104. }
  105. else
  106. {
  107. // otherwise, grow array
  108. int nGrowBy = m_nGrowBy;
  109. if (nGrowBy == 0)
  110. {
  111. // heuristically determine growth when nGrowBy == 0
  112. // (this avoids heap fragmentation in many situations)
  113. nGrowBy = min(1024, max(4, m_nSize / 8));
  114. }
  115. int nNewMax;
  116. if (nNewSize < m_nMaxSize + nGrowBy)
  117. nNewMax = m_nMaxSize + nGrowBy; // granularity
  118. else
  119. nNewMax = nNewSize; // no slush
  120. ASSERT(nNewMax >= m_nMaxSize); // no wrap around
  121. #ifdef SIZE_T_MAX
  122. ASSERT(nNewMax <= SIZE_T_MAX/sizeof(CString)); // no overflow
  123. #endif
  124. CString* pNewData = (CString*) new BYTE[nNewMax * sizeof(CString)];
  125. // copy new data from old
  126. memcpy(pNewData, m_pData, m_nSize * sizeof(CString));
  127. // construct remaining elements
  128. ASSERT(nNewSize > m_nSize);
  129. ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
  130. // get rid of old stuff (note: no destructors called)
  131. delete[] (BYTE*)m_pData;
  132. m_pData = pNewData;
  133. m_nSize = nNewSize;
  134. m_nMaxSize = nNewMax;
  135. }
  136. }
  137. int CStringArray::Append(const CStringArray& src)
  138. {
  139. ASSERT_VALID(this);
  140. ASSERT(this != &src); // cannot append to itself
  141. int nOldSize = m_nSize;
  142. SetSize(m_nSize + src.m_nSize);
  143. CopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);
  144. return nOldSize;
  145. }
  146. void CStringArray::Copy(const CStringArray& src)
  147. {
  148. ASSERT_VALID(this);
  149. ASSERT(this != &src); // cannot append to itself
  150. SetSize(src.m_nSize);
  151. CopyElements(m_pData, src.m_pData, src.m_nSize);
  152. }
  153. void CStringArray::FreeExtra()
  154. {
  155. ASSERT_VALID(this);
  156. if (m_nSize != m_nMaxSize)
  157. {
  158. // shrink to desired size
  159. #ifdef SIZE_T_MAX
  160. ASSERT(m_nSize <= SIZE_T_MAX/sizeof(CString)); // no overflow
  161. #endif
  162. CString* pNewData = NULL;
  163. if (m_nSize != 0)
  164. {
  165. pNewData = (CString*) new BYTE[m_nSize * sizeof(CString)];
  166. // copy new data from old
  167. memcpy(pNewData, m_pData, m_nSize * sizeof(CString));
  168. }
  169. // get rid of old stuff (note: no destructors called)
  170. delete[] (BYTE*)m_pData;
  171. m_pData = pNewData;
  172. m_nMaxSize = m_nSize;
  173. }
  174. }
  175. /////////////////////////////////////////////////////////////////////////////
  176. void CStringArray::SetAtGrow(int nIndex, LPCTSTR newElement)
  177. {
  178. ASSERT_VALID(this);
  179. ASSERT(nIndex >= 0);
  180. if (nIndex >= m_nSize)
  181. SetSize(nIndex+1);
  182. m_pData[nIndex] = newElement;
  183. }
  184. void CStringArray::SetAtGrow(int nIndex, const CString& newElement)
  185. {
  186. ASSERT_VALID(this);
  187. ASSERT(nIndex >= 0);
  188. if (nIndex >= m_nSize)
  189. SetSize(nIndex+1);
  190. m_pData[nIndex] = newElement;
  191. }
  192. void CStringArray::InsertEmpty(int nIndex, int nCount)
  193. {
  194. ASSERT_VALID(this);
  195. ASSERT(nIndex >= 0); // will expand to meet need
  196. ASSERT(nCount > 0); // zero or negative size not allowed
  197. if (nIndex >= m_nSize)
  198. {
  199. // adding after the end of the array
  200. SetSize(nIndex + nCount); // grow so nIndex is valid
  201. }
  202. else
  203. {
  204. // inserting in the middle of the array
  205. int nOldSize = m_nSize;
  206. SetSize(m_nSize + nCount); // grow it to new size
  207. // shift old data up to fill gap
  208. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  209. (nOldSize-nIndex) * sizeof(CString));
  210. // re-init slots we copied from
  211. ConstructElements(&m_pData[nIndex], nCount);
  212. }
  213. // insert new value in the gap
  214. ASSERT(nIndex + nCount <= m_nSize);
  215. }
  216. void CStringArray::InsertAt(int nIndex, LPCTSTR newElement, int nCount)
  217. {
  218. // make room for new elements
  219. InsertEmpty(nIndex, nCount);
  220. // copy elements into the empty space
  221. CString temp = newElement;
  222. while (nCount--)
  223. m_pData[nIndex++] = temp;
  224. }
  225. void CStringArray::InsertAt(int nIndex, const CString& newElement, int nCount)
  226. {
  227. // make room for new elements
  228. InsertEmpty(nIndex, nCount);
  229. // copy elements into the empty space
  230. while (nCount--)
  231. m_pData[nIndex++] = newElement;
  232. }
  233. void CStringArray::RemoveAt(int nIndex, int nCount)
  234. {
  235. ASSERT_VALID(this);
  236. ASSERT(nIndex >= 0);
  237. ASSERT(nCount >= 0);
  238. ASSERT(nIndex + nCount <= m_nSize);
  239. // just remove a range
  240. int nMoveCount = m_nSize - (nIndex + nCount);
  241. DestructElements(&m_pData[nIndex], nCount);
  242. if (nMoveCount)
  243. memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
  244. nMoveCount * sizeof(CString));
  245. m_nSize -= nCount;
  246. }
  247. void CStringArray::InsertAt(int nStartIndex, CStringArray* pNewArray)
  248. {
  249. ASSERT_VALID(this);
  250. ASSERT(pNewArray != NULL);
  251. ASSERT_KINDOF(CStringArray, pNewArray);
  252. ASSERT_VALID(pNewArray);
  253. ASSERT(nStartIndex >= 0);
  254. if (pNewArray->GetSize() > 0)
  255. {
  256. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  257. for (int i = 0; i < pNewArray->GetSize(); i++)
  258. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  259. }
  260. }
  261. /////////////////////////////////////////////////////////////////////////////
  262. // Serialization
  263. void CStringArray::Serialize(CArchive& ar)
  264. {
  265. ASSERT_VALID(this);
  266. CObject::Serialize(ar);
  267. if (ar.IsStoring())
  268. {
  269. ar.WriteCount(m_nSize);
  270. for (int i = 0; i < m_nSize; i++)
  271. ar << m_pData[i];
  272. }
  273. else
  274. {
  275. DWORD nOldSize = ar.ReadCount();
  276. SetSize(nOldSize);
  277. for (int i = 0; i < m_nSize; i++)
  278. ar >> m_pData[i];
  279. }
  280. }
  281. /////////////////////////////////////////////////////////////////////////////
  282. // Diagnostics
  283. #ifdef _DEBUG
  284. void CStringArray::Dump(CDumpContext& dc) const
  285. {
  286. CObject::Dump(dc);
  287. dc << "with " << m_nSize << " elements";
  288. if (dc.GetDepth() > 0)
  289. {
  290. for (int i = 0; i < m_nSize; i++)
  291. dc << "\n\t[" << i << "] = " << m_pData[i];
  292. }
  293. dc << "\n";
  294. }
  295. void CStringArray::AssertValid() const
  296. {
  297. CObject::AssertValid();
  298. if (m_pData == NULL)
  299. {
  300. ASSERT(m_nSize == 0);
  301. ASSERT(m_nMaxSize == 0);
  302. }
  303. else
  304. {
  305. ASSERT(m_nSize >= 0);
  306. ASSERT(m_nMaxSize >= 0);
  307. ASSERT(m_nSize <= m_nMaxSize);
  308. ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(CString)));
  309. }
  310. }
  311. #endif //_DEBUG
  312. #ifdef AFX_INIT_SEG
  313. #pragma code_seg(AFX_INIT_SEG)
  314. #endif
  315. IMPLEMENT_SERIAL(CStringArray, CObject, 0)
  316. /////////////////////////////////////////////////////////////////////////////