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.

149 lines
3.8 KiB

  1. //
  2. // saa.cpp
  3. //
  4. // CSharedAnchorArray
  5. //
  6. #include "private.h"
  7. #include "saa.h"
  8. #include "immxutil.h"
  9. //+---------------------------------------------------------------------------
  10. //
  11. // _MergeSort
  12. //
  13. // NB: rgArrays is freed before the method exits.
  14. // Caller must release the out array.
  15. //
  16. // perf: some possible optimizations:
  17. // quick check if the arrays don't overlap
  18. // find some way to anticipate dups
  19. //----------------------------------------------------------------------------
  20. /* static */
  21. CSharedAnchorArray *CSharedAnchorArray::_MergeSort(CSharedAnchorArray **rgArrays, ULONG cArrays)
  22. {
  23. LONG l;
  24. IAnchor *pa;
  25. IAnchor **ppaDst;
  26. IAnchor **ppa1;
  27. IAnchor **ppaEnd1;
  28. IAnchor **ppa2;
  29. IAnchor **ppaEnd2;
  30. CSharedAnchorArray *prgAnchors1 = NULL;
  31. CSharedAnchorArray *prgAnchors2 = NULL;
  32. CSharedAnchorArray *prgAnchors = NULL;
  33. BOOL fRet = FALSE;
  34. // recursion
  35. if (cArrays > 2)
  36. {
  37. if (cArrays == 3)
  38. {
  39. // avoid unnecessary mem alloc here
  40. prgAnchors1 = rgArrays[0];
  41. }
  42. else
  43. {
  44. prgAnchors1 = _MergeSort(rgArrays, cArrays / 2);
  45. }
  46. prgAnchors2 = _MergeSort(rgArrays + cArrays / 2, cArrays - cArrays / 2);
  47. }
  48. else
  49. {
  50. Assert(cArrays == 2);
  51. prgAnchors1 = rgArrays[0];
  52. prgAnchors2 = rgArrays[1];
  53. }
  54. // check for out-of-mem after the recursion, so we at least free the entire source array
  55. if (prgAnchors1 == NULL || prgAnchors2 == NULL)
  56. goto Exit;
  57. // allocate some memory
  58. // perf: we could do something complicated and do everything in place
  59. if ((prgAnchors = new CSharedAnchorArray) == NULL)
  60. goto Exit;
  61. if (prgAnchors1->Count() + prgAnchors2->Count() == 0)
  62. {
  63. Assert(!prgAnchors->Count());
  64. fRet = TRUE;
  65. goto Exit;
  66. }
  67. if (!prgAnchors->Append(prgAnchors1->Count() + prgAnchors2->Count()))
  68. goto Exit;
  69. // the actual combination
  70. ppaDst = prgAnchors->GetPtr(0);
  71. ppa1 = prgAnchors1->GetPtr(0);
  72. ppa2 = prgAnchors2->GetPtr(0);
  73. ppaEnd1 = prgAnchors1->GetPtr(prgAnchors1->Count());
  74. ppaEnd2 = prgAnchors2->GetPtr(prgAnchors2->Count());
  75. // do a one pass merge sort -- both prgAnchors1 and prgAnchors2 are sorted already
  76. while (ppa1 < ppaEnd1 ||
  77. ppa2 < ppaEnd2)
  78. {
  79. if (ppa1 < ppaEnd1)
  80. {
  81. if (ppa2 < ppaEnd2)
  82. {
  83. l = CompareAnchors(*ppa1, *ppa2);
  84. if (l < 0)
  85. {
  86. pa = *ppa1++;
  87. }
  88. else if (l > 0)
  89. {
  90. pa = *ppa2++;
  91. }
  92. else // equal
  93. {
  94. pa = *ppa1++;
  95. (*ppa2++)->Release();
  96. }
  97. }
  98. else
  99. {
  100. pa = *ppa1++;
  101. }
  102. }
  103. else // ppa2 < ppaEnd2
  104. {
  105. pa = *ppa2++;
  106. }
  107. *ppaDst++ = pa;
  108. }
  109. // taking ownership, so no AddRef
  110. // clear the elems counts so we don't Release in the destructors
  111. prgAnchors1->SetCount(0);
  112. prgAnchors2->SetCount(0);
  113. // we might have removed dups, so calc a new size
  114. prgAnchors->SetCount((int)(ppaDst - prgAnchors->GetPtr(0)));
  115. fRet = TRUE;
  116. Exit:
  117. if (prgAnchors1 != NULL)
  118. {
  119. prgAnchors1->_Release();
  120. }
  121. if (prgAnchors2 != NULL)
  122. {
  123. prgAnchors2->_Release();
  124. }
  125. if (!fRet)
  126. {
  127. if (prgAnchors != NULL)
  128. {
  129. prgAnchors->_Release();
  130. }
  131. prgAnchors = NULL;
  132. }
  133. return prgAnchors;
  134. }