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.
|
|
//
// saa.cpp
//
// CSharedAnchorArray
//
#include "private.h"
#include "saa.h"
#include "immxutil.h"
//+---------------------------------------------------------------------------
//
// _MergeSort
//
// NB: rgArrays is freed before the method exits.
// Caller must release the out array.
//
// perf: some possible optimizations:
// quick check if the arrays don't overlap
// find some way to anticipate dups
//----------------------------------------------------------------------------
/* static */ CSharedAnchorArray *CSharedAnchorArray::_MergeSort(CSharedAnchorArray **rgArrays, ULONG cArrays) { LONG l; IAnchor *pa; IAnchor **ppaDst; IAnchor **ppa1; IAnchor **ppaEnd1; IAnchor **ppa2; IAnchor **ppaEnd2; CSharedAnchorArray *prgAnchors1 = NULL; CSharedAnchorArray *prgAnchors2 = NULL; CSharedAnchorArray *prgAnchors = NULL; BOOL fRet = FALSE; // recursion
if (cArrays > 2) { if (cArrays == 3) { // avoid unnecessary mem alloc here
prgAnchors1 = rgArrays[0]; } else { prgAnchors1 = _MergeSort(rgArrays, cArrays / 2); } prgAnchors2 = _MergeSort(rgArrays + cArrays / 2, cArrays - cArrays / 2); } else { Assert(cArrays == 2); prgAnchors1 = rgArrays[0]; prgAnchors2 = rgArrays[1]; }
// check for out-of-mem after the recursion, so we at least free the entire source array
if (prgAnchors1 == NULL || prgAnchors2 == NULL) goto Exit;
// allocate some memory
// perf: we could do something complicated and do everything in place
if ((prgAnchors = new CSharedAnchorArray) == NULL) goto Exit;
if (prgAnchors1->Count() + prgAnchors2->Count() == 0) { Assert(!prgAnchors->Count()); fRet = TRUE; goto Exit; }
if (!prgAnchors->Append(prgAnchors1->Count() + prgAnchors2->Count())) goto Exit;
// the actual combination
ppaDst = prgAnchors->GetPtr(0); ppa1 = prgAnchors1->GetPtr(0); ppa2 = prgAnchors2->GetPtr(0); ppaEnd1 = prgAnchors1->GetPtr(prgAnchors1->Count()); ppaEnd2 = prgAnchors2->GetPtr(prgAnchors2->Count());
// do a one pass merge sort -- both prgAnchors1 and prgAnchors2 are sorted already
while (ppa1 < ppaEnd1 || ppa2 < ppaEnd2) { if (ppa1 < ppaEnd1) { if (ppa2 < ppaEnd2) { l = CompareAnchors(*ppa1, *ppa2); if (l < 0) { pa = *ppa1++; } else if (l > 0) { pa = *ppa2++; } else // equal
{ pa = *ppa1++; (*ppa2++)->Release(); } } else { pa = *ppa1++; } } else // ppa2 < ppaEnd2
{ pa = *ppa2++; }
*ppaDst++ = pa; }
// taking ownership, so no AddRef
// clear the elems counts so we don't Release in the destructors
prgAnchors1->SetCount(0); prgAnchors2->SetCount(0); // we might have removed dups, so calc a new size
prgAnchors->SetCount((int)(ppaDst - prgAnchors->GetPtr(0)));
fRet = TRUE;
Exit: if (prgAnchors1 != NULL) { prgAnchors1->_Release(); } if (prgAnchors2 != NULL) { prgAnchors2->_Release(); } if (!fRet) { if (prgAnchors != NULL) { prgAnchors->_Release(); } prgAnchors = NULL; }
return prgAnchors; }
|