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.

261 lines
6.5 KiB

  1. /*++
  2. Copyright (C) 1992-2001 Microsoft Corporation
  3. Module Name:
  4. ARRAY_S.CPP
  5. Abstract:
  6. History:
  7. --*/
  8. // This is a part of the Microsoft Foundation Classes C++ library.
  9. // Copyright (C) 1992-1993 Microsoft Corporation
  10. // All rights reserved.
  11. //
  12. // This source code is only intended as a supplement to the
  13. // Microsoft Foundation Classes Reference and Microsoft
  14. // QuickHelp and/or WinHelp documentation provided with the library.
  15. // See these sources for detailed information regarding the
  16. // Microsoft Foundation Classes product.
  17. /////////////////////////////////////////////////////////////////////////////
  18. //
  19. // Implementation of parameterized Array
  20. //
  21. /////////////////////////////////////////////////////////////////////////////
  22. // NOTE: we allocate an array of 'm_nMaxSize' elements, but only
  23. // the current size 'm_nSize' contains properly constructed
  24. // objects.
  25. #include "precomp.h"
  26. #define ASSERT_VALID(x)
  27. #define ASSERT(x)
  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. pOldData->Empty();
  44. pOldData++;
  45. }
  46. }
  47. /////////////////////////////////////////////////////////////////////////////
  48. CStringArray::CStringArray()
  49. {
  50. m_pData = NULL;
  51. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  52. }
  53. CStringArray::~CStringArray()
  54. {
  55. ASSERT_VALID(this);
  56. DestructElements(m_pData, m_nSize);
  57. delete (BYTE*)m_pData;
  58. }
  59. void CStringArray::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  60. {
  61. ASSERT_VALID(this);
  62. ASSERT(nNewSize >= 0);
  63. if (nGrowBy != -1)
  64. m_nGrowBy = nGrowBy; // set new size
  65. if (nNewSize == 0)
  66. {
  67. // shrink to nothing
  68. DestructElements(m_pData, m_nSize);
  69. delete (BYTE*)m_pData;
  70. m_pData = NULL;
  71. m_nSize = m_nMaxSize = 0;
  72. }
  73. else if (m_pData == NULL)
  74. {
  75. // create one with exact size
  76. #ifdef SIZE_T_MAX
  77. ASSERT((long)nNewSize * sizeof(CString) <= SIZE_T_MAX); // no overflow
  78. #endif
  79. m_pData = (CString*) new BYTE[nNewSize * sizeof(CString)];
  80. ConstructElements(m_pData, nNewSize);
  81. m_nSize = m_nMaxSize = nNewSize;
  82. }
  83. else if (nNewSize <= m_nMaxSize)
  84. {
  85. // it fits
  86. if (nNewSize > m_nSize)
  87. {
  88. // initialize the new elements
  89. ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
  90. }
  91. else if (m_nSize > nNewSize) // destroy the old elements
  92. DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
  93. m_nSize = nNewSize;
  94. }
  95. else
  96. {
  97. // Otherwise grow array
  98. int nNewMax;
  99. if (nNewSize < m_nMaxSize + m_nGrowBy)
  100. nNewMax = m_nMaxSize + m_nGrowBy; // granularity
  101. else
  102. nNewMax = nNewSize; // no slush
  103. #ifdef SIZE_T_MAX
  104. ASSERT((long)nNewMax * sizeof(CString) <= SIZE_T_MAX); // no overflow
  105. #endif
  106. CString* pNewData = (CString*) new BYTE[nNewMax * sizeof(CString)];
  107. // copy new data from old
  108. memcpy(pNewData, m_pData, m_nSize * sizeof(CString));
  109. // construct remaining elements
  110. ASSERT(nNewSize > m_nSize);
  111. ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
  112. // get rid of old stuff (note: no destructors called)
  113. delete (BYTE*)m_pData;
  114. m_pData = pNewData;
  115. m_nSize = nNewSize;
  116. m_nMaxSize = nNewMax;
  117. }
  118. }
  119. void CStringArray::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((long)m_nSize * sizeof(CString) <= SIZE_T_MAX); // no overflow
  127. #endif
  128. CString* pNewData = NULL;
  129. if (m_nSize != 0)
  130. {
  131. pNewData = (CString*) new BYTE[m_nSize * sizeof(CString)];
  132. // copy new data from old
  133. memcpy(pNewData, m_pData, m_nSize * sizeof(CString));
  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 CStringArray::SetAtGrow(int nIndex, const char* 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 CStringArray::InsertAt(int nIndex, const char* newElement, int nCount /*=1*/)
  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(CString));
  168. // re-init slots we copied from
  169. ConstructElements(&m_pData[nIndex], nCount);
  170. }
  171. // insert new value in the gap
  172. ASSERT(nIndex + nCount <= m_nSize);
  173. while (nCount--)
  174. m_pData[nIndex++] = newElement;
  175. }
  176. void CStringArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  177. {
  178. ASSERT_VALID(this);
  179. ASSERT(nIndex >= 0);
  180. ASSERT(nCount >= 0);
  181. ASSERT(nIndex + nCount <= m_nSize);
  182. // just remove a range
  183. int nMoveCount = m_nSize - (nIndex + nCount);
  184. DestructElements(&m_pData[nIndex], nCount);
  185. if (nMoveCount)
  186. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  187. nMoveCount * sizeof(CString));
  188. m_nSize -= nCount;
  189. }
  190. void CStringArray::InsertAt(int nStartIndex, CStringArray* pNewArray)
  191. {
  192. ASSERT_VALID(this);
  193. ASSERT(pNewArray != NULL);
  194. ASSERT(pNewArray->IsKindOf(RUNTIME_CLASS(CStringArray)));
  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. }