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.

210 lines
4.3 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. SMALLARR.CPP
  5. Abstract:
  6. Small Array
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include <stdio.h>
  11. #include "smallarr.h"
  12. CSmallArrayBlob* CSmallArrayBlob::CreateBlob(int nInitialSize)
  13. {
  14. // Allocate enough space for the header, plus the data
  15. // ===================================================
  16. DWORD dwSize = sizeof(CSmallArrayBlob) - sizeof(void*) * ANYSIZE_ARRAY;
  17. dwSize += nInitialSize * sizeof(void*);
  18. CSmallArrayBlob* pBlob = (CSmallArrayBlob*)(new BYTE[dwSize]);
  19. if(pBlob == NULL)
  20. return NULL;
  21. // Initialize it appropriately
  22. // ===========================
  23. pBlob->Initialize(nInitialSize);
  24. return pBlob;
  25. }
  26. void CSmallArrayBlob::Initialize(int nInitialSize)
  27. {
  28. // It has already been allocated to be big enough
  29. // ==============================================
  30. m_nExtent = nInitialSize;
  31. m_nSize = 0;
  32. }
  33. CSmallArrayBlob* CSmallArrayBlob::Grow()
  34. {
  35. // Allocate a new array of twice our size
  36. // ======================================
  37. CSmallArrayBlob* pNew = CreateBlob(m_nExtent*2);
  38. if(pNew == NULL)
  39. return NULL;
  40. // Copy our data into it
  41. // =====================
  42. pNew->CopyData(this);
  43. // Delete ourselves!
  44. // =================
  45. delete this;
  46. return pNew;
  47. }
  48. void CSmallArrayBlob::CopyData(CSmallArrayBlob* pOther)
  49. {
  50. m_nSize = pOther->m_nSize;
  51. memcpy(m_apMembers, pOther->m_apMembers, sizeof(void*) * m_nSize);
  52. }
  53. CSmallArrayBlob* CSmallArrayBlob::EnsureExtent(int nDesired)
  54. {
  55. if(m_nExtent < nDesired)
  56. return Grow(); // will delete this!
  57. else
  58. return this;
  59. }
  60. CSmallArrayBlob* CSmallArrayBlob::InsertAt(int nIndex, void* pMember)
  61. {
  62. // Ensure there is enough space
  63. // ============================
  64. CSmallArrayBlob* pArray = EnsureExtent(m_nSize+1);
  65. if(pArray == NULL)
  66. return NULL;
  67. // Move the data forward to make room
  68. // ==================================
  69. if(pArray->m_nSize > nIndex)
  70. {
  71. memmove(pArray->m_apMembers + nIndex + 1, pArray->m_apMembers + nIndex,
  72. sizeof(void*) * (pArray->m_nSize - nIndex));
  73. }
  74. // Insert
  75. // ======
  76. pArray->m_apMembers[nIndex] = pMember;
  77. pArray->m_nSize++;
  78. return pArray;
  79. }
  80. void CSmallArrayBlob::SetAt(int nIndex, void* pMember, void** ppOld)
  81. {
  82. // Make sure we even have that index (sparse set)
  83. // ==============================================
  84. EnsureExtent(nIndex+1);
  85. if(nIndex >= m_nSize)
  86. m_nSize = nIndex+1;
  87. // Save old value
  88. // ==============
  89. if(ppOld)
  90. *ppOld = m_apMembers[nIndex];
  91. // Replace
  92. // =======
  93. m_apMembers[nIndex] = pMember;
  94. }
  95. CSmallArrayBlob* CSmallArrayBlob::RemoveAt(int nIndex, void** ppOld)
  96. {
  97. // Save old value
  98. // ==============
  99. if(ppOld)
  100. *ppOld = m_apMembers[nIndex];
  101. // Move the data back
  102. // ==================
  103. memcpy(m_apMembers + nIndex, m_apMembers + nIndex + 1,
  104. sizeof(void*) * (m_nSize - nIndex - 1));
  105. m_nSize--;
  106. // Ensure we are not too large
  107. // ===========================
  108. return ShrinkIfNeeded();
  109. }
  110. CSmallArrayBlob* CSmallArrayBlob::ShrinkIfNeeded()
  111. {
  112. if(m_nSize < m_nExtent / 4)
  113. return Shrink(); // will delete this!
  114. else
  115. return this;
  116. }
  117. CSmallArrayBlob* CSmallArrayBlob::Shrink()
  118. {
  119. // Allocate a new blob of half our size
  120. // ====================================
  121. CSmallArrayBlob* pNew = CreateBlob((m_nExtent+1)/2);
  122. if(pNew == NULL)
  123. {
  124. // Out of memory --- we'll just have to stay large
  125. // ===============================================
  126. return this;
  127. }
  128. // Copy our data
  129. // =============
  130. pNew->CopyData(this);
  131. delete this; // we are no longer needed
  132. return pNew;
  133. }
  134. void CSmallArrayBlob::Trim()
  135. {
  136. while(m_nSize > 0 && m_apMembers[m_nSize-1] == NULL)
  137. m_nSize--;
  138. }
  139. void CSmallArrayBlob::Sort()
  140. {
  141. qsort(m_apMembers, m_nSize, sizeof(void*), CSmallArrayBlob::CompareEls);
  142. }
  143. int __cdecl CSmallArrayBlob::CompareEls(const void* pelem1, const void* pelem2)
  144. {
  145. return *(DWORD_PTR*)pelem1 - *(DWORD_PTR*)pelem2;
  146. }
  147. void** CSmallArrayBlob::CloneData()
  148. {
  149. void** ppReturn = new void*[m_nSize];
  150. if (ppReturn)
  151. memcpy(ppReturn, m_apMembers, m_nSize * sizeof(void*));
  152. return ppReturn;
  153. }