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.

220 lines
5.1 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. m_nGrowBy = nGrowBy; // set new size
  34. if (nNewSize == 0)
  35. {
  36. // shrink to nothing
  37. delete [] (BYTE*)m_pData;
  38. m_pData = NULL;
  39. m_nSize = m_nMaxSize = 0;
  40. }
  41. else if (m_pData == NULL)
  42. {
  43. // create one with exact size
  44. m_pData = (void**) new BYTE[nNewSize * sizeof(void*)];
  45. if (m_pData)
  46. {
  47. memset(m_pData, 0, nNewSize * sizeof(void*)); // zero fill
  48. m_nSize = m_nMaxSize = nNewSize;
  49. }
  50. }
  51. else if (nNewSize <= m_nMaxSize)
  52. {
  53. // it fits
  54. if (nNewSize > m_nSize)
  55. {
  56. // initialize the new elements
  57. memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  58. }
  59. m_nSize = nNewSize;
  60. }
  61. else
  62. {
  63. // Otherwise grow array
  64. int nNewMax;
  65. if (nNewSize < m_nMaxSize + m_nGrowBy)
  66. nNewMax = m_nMaxSize + m_nGrowBy; // granularity
  67. else
  68. nNewMax = nNewSize; // no slush
  69. void** pNewData = (void**) new BYTE[nNewMax * sizeof(void*)];
  70. // copy new data from old
  71. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  72. // construct remaining elements
  73. MYDBGASSERT(nNewSize > m_nSize);
  74. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  75. // get rid of old stuff (note: no destructors called)
  76. delete [] (BYTE*)m_pData;
  77. m_pData = pNewData;
  78. m_nSize = nNewSize;
  79. m_nMaxSize = nNewMax;
  80. }
  81. }
  82. void CPtrArray::FreeExtra()
  83. {
  84. ASSERT_VALID(this);
  85. if (m_nSize != m_nMaxSize)
  86. {
  87. // shrink to desired size
  88. void** pNewData = NULL;
  89. if (m_nSize != 0)
  90. {
  91. pNewData = (void**) new BYTE[m_nSize * sizeof(void*)];
  92. // copy new data from old
  93. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  94. }
  95. // get rid of old stuff (note: no destructors called)
  96. delete [] (BYTE*)m_pData;
  97. m_pData = pNewData;
  98. m_nMaxSize = m_nSize;
  99. }
  100. }
  101. /////////////////////////////////////////////////////////////////////////////
  102. void CPtrArray::SetAtGrow(int nIndex, void* newElement)
  103. {
  104. ASSERT_VALID(this);
  105. MYDBGASSERT(nIndex >= 0);
  106. if (nIndex >= m_nSize)
  107. SetSize(nIndex+1);
  108. m_pData[nIndex] = newElement;
  109. }
  110. void CPtrArray::InsertAt(int nIndex, void* newElement, int nCount /*=1*/)
  111. {
  112. ASSERT_VALID(this);
  113. MYDBGASSERT(nIndex >= 0); // will expand to meet need
  114. MYDBGASSERT(nCount > 0); // zero or negative size not allowed
  115. if (nIndex >= m_nSize)
  116. {
  117. // adding after the end of the array
  118. SetSize(nIndex + nCount); // grow so nIndex is valid
  119. }
  120. else
  121. {
  122. // inserting in the middle of the array
  123. int nOldSize = m_nSize;
  124. SetSize(m_nSize + nCount); // grow it to new size
  125. // shift old data up to fill gap
  126. CmMoveMemory(&m_pData[nIndex+nCount], &m_pData[nIndex],
  127. (nOldSize-nIndex) * sizeof(void*));
  128. // re-init slots we copied from
  129. memset(&m_pData[nIndex], 0, nCount * sizeof(void*));
  130. }
  131. // insert new value in the gap
  132. MYDBGASSERT(nIndex + nCount <= m_nSize);
  133. while (nCount--)
  134. m_pData[nIndex++] = newElement;
  135. }
  136. void CPtrArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  137. {
  138. ASSERT_VALID(this);
  139. MYDBGASSERT(nIndex >= 0);
  140. MYDBGASSERT(nCount >= 0);
  141. MYDBGASSERT(nIndex + nCount <= m_nSize);
  142. // just remove a range
  143. int nMoveCount = m_nSize - (nIndex + nCount);
  144. if (nMoveCount)
  145. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  146. nMoveCount * sizeof(void*));
  147. m_nSize -= nCount;
  148. }
  149. void CPtrArray::InsertAt(int nStartIndex, CPtrArray* pNewArray)
  150. {
  151. ASSERT_VALID(this);
  152. MYDBGASSERT(pNewArray != NULL);
  153. ASSERT_VALID(pNewArray);
  154. MYDBGASSERT(nStartIndex >= 0);
  155. if (pNewArray->GetSize() > 0)
  156. {
  157. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  158. for (int i = 0; i < pNewArray->GetSize(); i++)
  159. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  160. }
  161. }
  162. /////////////////////////////////////////////////////////////////////////////
  163. // Diagnostics
  164. #ifdef DEBUG
  165. void CPtrArray::AssertValid() const
  166. {
  167. if (m_pData == NULL)
  168. {
  169. MYDBGASSERT(m_nSize == 0 && m_nMaxSize == 0);
  170. }
  171. else
  172. {
  173. MYDBGASSERT(m_nSize >= 0);
  174. MYDBGASSERT(m_nMaxSize >= 0);
  175. MYDBGASSERT(m_nSize <= m_nMaxSize);
  176. MYDBGASSERT(!IsBadReadPtr(m_pData, m_nMaxSize * sizeof(void*)));
  177. }
  178. }
  179. #endif