/******************************************************************************
 *                                                                            *
 *  BTKTSZIS.C                                                                *
 *                                                                            *
 *  Copyright (C) Microsoft Corporation 1989 - 1994.                          *
 *  All Rights reserved.                                                      *
 *                                                                            *
 ******************************************************************************
 *                                                                            *
 *  Module Intent                                                             *
 *                                                                            *
 *  Functions for SZISCAND (0-terminated case insensitive Scandinavian        *
 *  string keys.                                                              *
 *                                                                            *
 ******************************************************************************
 *                                                                            *
 *  Current Owner:  BinhN                                                     *
 *                                                                            *
 ******************************************************************************/

static char s_aszModule[] = __FILE__;	/* For error report */

#include <mvopsys.h>
#include <misc.h>
#include <iterror.h>
#include <orkin.h>
#include <wrapstor.h>
#include <_mvutil.h>


/***************************************************************************
 *
 *	@doc	INTERNAL
 *
 *	@func	BK FAR PASCAL | BkScanSziScandInternal |
 *		Scan an internal node for a 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
 *		qbthr->qCache  bk's block will be cached
 *
 *	@parm	QW | qiKey |
 *		address of an int or NULL to not get it
 *
 *	@rdesc	bk of subtree that might contain key; bkNil on error
 *		qiKey         - index into rgbBlock of first key >= key
 *		Side Effects:   bk's block will be cached
 *
 ***************************************************************************/

PUBLIC BK FAR PASCAL BkScanSziScandInternal(BK bk, KEY key, SHORT wLevel,
	QBTHR qbthr, QW qiKey, PHRESULT phr)
{
	QCB qcb;
	QB  q;
	SHORT cKeys;

	if ((qcb = QFromBk(bk, wLevel, qbthr, phr)) == NULL)
	{
		return bkNil;
	}
	q     = qcb->db.rgbBlock;
	cKeys = qcb->db.cKeys;
	
	
	bk = (BK)GETLONG(q);
	q += sizeof(BK);

	while (cKeys-- > 0)
	{
		if (WCmpiScandSz((SZ)key, (SZ)q) >= 0)
		{
			q += STRLEN((SZ)q) + 1;
			bk = (BK)GETLONG(q);
			q += sizeof(BK);
		}
		else
			break;
	}

	if (qiKey != NULL)
	{
		*qiKey = (WORD)(q - (QB)qcb->db.rgbBlock);
	}

	return bk;
}

/***************************************************************************
 *
 *	@doc	INTERNAL
 *
 *	@func	HRESULT FAR PASCAL | RcScanSziScandLeaf |
 *		Scan a leaf node for a 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_SUCCESS if found; ERR_NOTEXIST if not found
 *		NOTE: 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 RcScanSziScandLeaf(BK bk, KEY  key,
	SHORT wLevel, QBTHR qbthr, QV qRec, QBTPOS qbtpos)
{
	QCB   qcb;
	SZ    sz;
	SHORT   w, cKey;
	QB    qb;
	HRESULT    rc;
    HRESULT  errb;
	

	if ((qcb = QFromBk(bk, wLevel, qbthr, &errb)) == NULL)
	{
		return errb;
	}
	
	rc = E_NOTEXIST;

	sz = qcb->db.rgbBlock + 2 * sizeof(BK);

	for (cKey = 0; cKey < qcb->db.cKeys; cKey++)
	{
		w = WCmpiScandSz((SZ)key, sz);

		if (w > 0) /* still looking for key */
		{
			sz += STRLEN(sz) + 1;
			sz += CbSizeRec(sz, qbthr);
		}
		else if (w < 0) /* key not found */
		{
			break;
		}
		else /* matched the key */
		{
			if (qRec != NULL)
			{
				qb = (QB)sz + STRLEN(sz) + 1;
				QVCOPY(qRec, qb, (LONG)CbSizeRec(qb, qbthr));
			}

			rc = S_OK;
			break;
		}
	}

	if (qbtpos != NULL)
	{
		qbtpos->bk   = bk;
		qbtpos->cKey = cKey;
		qbtpos->iKey = (int)((QB)sz - (QB)qcb->db.rgbBlock);
	}

	return rc;
}

/* EOF */