windows-nt/Source/XPSP1/NT/enduser/stuff/itircl/common/btree/btktext.cpp
2020-09-26 16:20:57 +08:00

296 lines
7.2 KiB
C++

/*****************************************************************************
* *
* BTKTEXT.C *
* *
* Copyright (C) Microsoft Corporation 1997. *
* All Rights reserved. *
* *
******************************************************************************
* *
* Module Intent *
* *
* Functions for external sort keys. *
* *
******************************************************************************
* *
* Current Owner: BillA *
* *
*****************************************************************************/
static char s_aszModule[] = __FILE__; /* For error report */
#include <mvopsys.h>
#ifdef _MAC
#include <winnls.h>
#endif
#include <orkin.h>
#include <string.h>
#include <misc.h>
#include <iterror.h>
#include <itsort.h>
#include <wrapstor.h>
#include <mvdbcs.h>
#include <mvsearch.h>
#include <_mvutil.h>
#include "common.h"
/***************************************************************************
*
* @doc INTERNAL
*
* @func BK FAR PASCAL | BkScanExtSortInternal |
* Scan an internal node for an external sort key and return child BK.
*
* @parm BK | bk |
* BK of internal node to scan
*
* @parm KEY | key |
* key to search for
*
* @parm SHORT | wLevel |
* level of btree bk lives on
*
* @parm QBTHR | qbthr |
* btree header containing cache, and btree specs
*
* @parm QW | qiKey |
* address of an int or NULL to not get it
*
* @rdesc bk of subtree that might contain key; bkNil on error
* args OUT: qbthr->qCache - bk's block will be cached
* qiKey - index into rgbBlock of first key >= key
*
* Side Effects: bk's block will be cached
*
***************************************************************************/
PUBLIC BK FAR PASCAL BkScanExtSortInternal(BK bk, KEY key, SHORT wLevel,
QBTHR qbthr, QW qiKey, LPVOID lpv)
{
QCB qcb; // Pointer to cache block
QB qb; // Pointer to block buffer
SHORT cKeys; // Number of keys in the block
if ((qcb = QFromBk(bk, wLevel, qbthr, (PHRESULT) lpv)) == NULL)
{
return bkNil;
}
qb = qcb->db.rgbBlock; // Block buffer
cKeys = qcb->db.cKeys; // Number of keys in the block
bk = (BK)GETLONG(qb); // Get leaf block number
qb += sizeof(DWORD);
while (cKeys-- > 0)
{
LONG lResult;
// NOTE (billa): This won't work on the Mac unless a method is added
// to IITSortKey to swap dwords and words if necessary. Mikkya
// made an explicit decision to omit this from the initial
// version of IITSortKey (6/4/97).
if (qbthr->pITSortKey == NULL ||
FAILED(qbthr->pITSortKey->Compare((LPCVOID) key, (LPCVOID) qb,
&lResult, NULL)))
{
return bkNil;
}
if (lResult >= 0)
{
DWORD cbKey;
if (qbthr->pITSortKey == NULL ||
FAILED(qbthr->pITSortKey->GetSize((LPCVOID) qb, &cbKey)))
{
return bkNil;
}
qb += cbKey;
bk = (BK)GETLONG(qb);
qb += sizeof(DWORD);
}
else
break;
}
if (qiKey != NULL)
{
*qiKey = (WORD)(qb - (QB)qcb->db.rgbBlock);
}
return bk;
}
/***************************************************************************
*
* @doc INTERNAL
*
* @func HRESULT FAR PASCAL | RcScanExtSortLeaf |
* Scan a leaf node for an external sort key and copy the associated data.
*
* @parm BK | bk |
* the leaf block
*
* @parm KEY | key |
* the key we're looking for
*
* @parm SHORT | wLevel |
* the level of leaves (unnecessary)
*
* @parm QBTHR | qbthr |
* the btree header
*
* @parm QV | qRec |
* if found, record gets copied into this buffer
*
* @parm QTPOS | qbtpos |
* pos of first key >= key goes here
*
* @rdesc ERR_SUCESS if found; ERR_NOTEXIST if not found
* If we are scanning for a key greater than any key in this
* block, the pos returned will be invalid and will point just
* past the last valid key in this block.
*
***************************************************************************/
PUBLIC HRESULT FAR PASCAL RcScanExtSortLeaf(BK bk, KEY key, SHORT wLevel,
QBTHR qbthr, QV qRec, QBTPOS qbtpos)
{
QCB qcb;
QB qb;
HRESULT rc;
SHORT i;
SHORT cKeys; // Number of keys in the block
QB qbSaved = NULL;
DWORD cbLength, cbLengthSaved = 0;
HRESULT errb;
if ((qcb = QFromBk(bk, wLevel, qbthr, &errb)) == NULL)
{
return errb;
}
rc = E_NOTEXIST;
qb = qcb->db.rgbBlock + 2 * sizeof(BK);
cKeys = qcb->db.cKeys;
for (i= 0; i < cKeys; i++)
{
LONG lResult;
// NOTE (billa): This won't work on the Mac unless a method is added
// to IITSortKey to swap dwords and words if necessary. Mikkya
// made an explicit decision to omit this from the initial
// version of IITSortKey (6/4/97).
if (qbthr->pITSortKey == NULL ||
FAILED(qbthr->pITSortKey->GetSize((LPCVOID) qb, &cbLength)) ||
FAILED(qbthr->pITSortKey->Compare((LPCVOID) key, (LPCVOID) qb,
&lResult, NULL)))
{
return rc;
}
if (lResult > 0) /* still looking for key */
{
qb += cbLength;
qb += CbSizeRec(qb, qbthr);
}
else if (lResult < 0) /* key not found */
{
break;
}
else /* matched the key */
{
if (qRec != NULL)
{
qb += cbLength;
QVCOPY(qRec, qb, (LONG)CbSizeRec(qb, qbthr));
}
rc = S_OK;
break;
}
}
if (qbtpos != NULL)
{
qbtpos->bk = bk;
qbtpos->cKey = i;
qbtpos->iKey = (int)(qb - (QB)qcb->db.rgbBlock);
}
return rc;
}
PUBLIC VOID EXPORT_API PASCAL FAR BtreeSetExtSort(HBT hbt,
IITSortKey *pITSortKey)
{
if (hbt != NULL && pITSortKey != NULL)
{
QBTHR qbthr;
qbthr = (QBTHR) _GLOBALLOCK(hbt);
if (qbthr->pITSortKey != NULL)
qbthr->pITSortKey->Release();
(qbthr->pITSortKey = pITSortKey)->AddRef();
_GLOBALUNLOCK(hbt);
}
else
{
ITASSERT(FALSE);
}
}
PUBLIC VOID EXPORT_API PASCAL FAR BtreeGetExtSort(HBT hbt,
IITSortKey **ppITSortKey)
{
if (ppITSortKey != NULL)
{
// Set to NULL in case we can't set it properly because the hbt is NULL.
*ppITSortKey = NULL;
if (hbt != NULL)
{
QBTHR qbthr;
qbthr = (QBTHR) _GLOBALLOCK(hbt);
if ((*ppITSortKey = qbthr->pITSortKey) != NULL)
(*ppITSortKey)->AddRef();
_GLOBALUNLOCK(hbt);
}
else
{
ITASSERT(FALSE);
}
}
else
{
ITASSERT(FALSE);
}
}
/* EOF */