mirror of https://github.com/lianthony/NT4.0
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.
410 lines
11 KiB
410 lines
11 KiB
/*****************************************************************************
|
|
* *
|
|
* BTKEY.C *
|
|
* *
|
|
* Copyright (C) Microsoft Corporation 1989, 1990. *
|
|
* All Rights reserved. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Module Intent *
|
|
* *
|
|
* Functions to deal with (i.e. size, compare) keys of all types. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Testing Notes *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Current Owner: JohnSc *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Released by Development: long, long ago *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Revision History: Created 05/11/89 by JohnSc
|
|
*
|
|
* 08/21/90 JohnSc autodocified
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <orkin.h>
|
|
#include <string.h>
|
|
#include "_mvfs.h"
|
|
#include "imvfs.h"
|
|
|
|
#include "btpriv.h"
|
|
// _subsystem( btree );
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Macros *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
|
|
#define StCopy(st1, st2) (ST)QvCopy( (st1), (st2), (LONG)*(st2) )
|
|
|
|
#define CbLenSt(st) ((WORD)*(st))
|
|
|
|
|
|
#if 0
|
|
// Commented out because it's not used. Will need thought about compression.
|
|
/***************************************************************************\
|
|
*
|
|
- Function: RcGetKey( pq, keyOld, pKey, kt )
|
|
-
|
|
* Status: API needs work
|
|
*
|
|
* Purpose: Copy a key, taking into account the previous key.
|
|
*
|
|
* ASSUMES
|
|
*
|
|
* args IN: pq - find the key here
|
|
* keyOld - the old key to use
|
|
* kt - key type
|
|
*
|
|
* PROMISES
|
|
*
|
|
* returns:
|
|
* args OUT: pq - now points past end of key gotten
|
|
* pKey - destination buffer key is expanded into
|
|
*
|
|
* Notes: It's not clear we want this function.
|
|
* We probably don't need to copy stuff around this much.
|
|
*
|
|
\***************************************************************************/
|
|
_hidden RC
|
|
RcGetKey( pq, keyOld, pKey, kt )
|
|
QV *pq;
|
|
KEY keyOld, *pKey;
|
|
KT kt;
|
|
{
|
|
BYTE cbSave;
|
|
|
|
|
|
switch ( kt )
|
|
{
|
|
case KT_SZ:
|
|
case KT_SZMIN:
|
|
case KT_SZI:
|
|
lstrcpy( (SZ)*pKey, (SZ)*pq );
|
|
*(QB)pq += lstrlen( (SZ)*pq );
|
|
break;
|
|
|
|
case KT_LONG:
|
|
// *pKey = *((KEY *)(*pq))++;
|
|
// *(LONG FAR *)(*pKey) = *( oh fuck it.
|
|
|
|
break;
|
|
|
|
case KT_SZDEL:
|
|
case KT_SZDELMIN:
|
|
cbSave = **(QB *)pq;
|
|
QvCopy( (QV)*pKey, (QV)keyOld, cbSave );
|
|
lstrcpy( (SZ)*pKey + cbSave, *(SZ *)pq + 1 );
|
|
*(QB *)pq += 1 + lstrlen( *(SZ *)pq + 1 );
|
|
break;
|
|
|
|
case KT_ST:
|
|
case KT_STMIN:
|
|
StCopy( (ST)*pKey, (ST)*pq );
|
|
*(QB *)pq += 1 + CbLenSt( *(ST *)pq + 1 );
|
|
break;
|
|
|
|
case KT_STDEL:
|
|
case KT_STDELMIN:
|
|
cbSave = **(QB *)pq;
|
|
QvCopy( (QV)*pKey, (QV)keyOld, cbSave );
|
|
StCopy( (ST)*pKey + cbSave, *(ST *)pq + 1 );
|
|
*(QB)pq += 1 + CbLenSt( (ST)pKey + 1 );
|
|
break;
|
|
|
|
default:
|
|
return rcUnimplemented;
|
|
break;
|
|
}
|
|
return rcSuccess;
|
|
}
|
|
#endif
|
|
/***************************************************************************\
|
|
*
|
|
- Function: WCmpKey( key1, key2, qbthr )
|
|
-
|
|
* Purpose: Compare two keys.
|
|
*
|
|
* ASSUMES
|
|
* args IN: key1, key2 - the UNCOMPRESSED keys to compare
|
|
* qbthr->bth.rgchFormat[0] - key type
|
|
* [qbthr->??? - other info ???]
|
|
* state IN: [may someday use state if comparing compressed keys]
|
|
*
|
|
* PROMISES
|
|
* returns: -1 if key1 < key2; 0 if key1 == key2; 1 if key1 > key2
|
|
* args OUT: [if comparing compressed keys, change state in qbthr->???]
|
|
* state OUT:
|
|
*
|
|
* Notes: Might be best to have this routine assume keys are expanded
|
|
* and do something else to compare keys in the scan routines.
|
|
* We're assuming fixed length keys are SZs. Alternative
|
|
* would be to use a memcmp() function.
|
|
*
|
|
\***************************************************************************/
|
|
_private INT
|
|
WCmpKey( key1, key2, qbthr)
|
|
KEY key1, key2;
|
|
QBTHR qbthr;
|
|
{
|
|
INT w;
|
|
KT kt = (KT)qbthr->bth.rgchFormat[ 0 ];
|
|
LONG l1, l2;
|
|
|
|
|
|
switch ( kt )
|
|
{
|
|
case KT_SZDEL: // assume keys have been expanded for delta codeds
|
|
case KT_SZDELMIN:
|
|
case KT_SZ:
|
|
case KT_SZMIN:
|
|
case '1': case '2': case '3': case '4': case '5': // assume null term
|
|
case '6': case '7': case '8': case '9': case 'a':
|
|
case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
w = strcmp( (SZ)key1, (SZ)key2 );
|
|
break;
|
|
|
|
case KT_SZI:
|
|
w = WCmpiSz( (SZ)key1, (SZ)key2, qbthr->qbLigatures );
|
|
break;
|
|
|
|
case KT_SZISCAND:
|
|
w = WCmpiScandSz( (SZ)key1, (SZ)key2 );
|
|
break;
|
|
|
|
case KT_ST:
|
|
case KT_STMIN:
|
|
case KT_STDEL:
|
|
case KT_STDELMIN:
|
|
w = WCmpSt( (ST)key1, (ST)key2 );
|
|
break;
|
|
|
|
case KT_LONG:
|
|
l1 = *(LONG FAR *)key1;
|
|
l2 = *(LONG FAR *)key2;
|
|
if ( l1 < l2 )
|
|
w = -1;
|
|
else if ( l2 < l1 )
|
|
w = 1;
|
|
else
|
|
w = 0;
|
|
break;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
/***************************************************************************\
|
|
*
|
|
- Function: CbSizeKey( key, qbthr, fCompressed )
|
|
-
|
|
* Purpose: Return the key size (compressed or un-) in bytes
|
|
*
|
|
* ASSUMES
|
|
* args IN: key
|
|
* qbthr
|
|
* fCompressed - TRUE to get the compressed size,
|
|
* FALSE to get the uncompressed size.
|
|
*
|
|
* PROMISES
|
|
* returns: size of the key in bytes
|
|
*
|
|
* Note: It's impossible to tell how much suffix was discarded for
|
|
* the KT_*MIN key types.
|
|
*
|
|
\***************************************************************************/
|
|
_private INT
|
|
CbSizeKey( key, qbthr, fCompressed )
|
|
KEY key;
|
|
QBTHR qbthr;
|
|
BOOL fCompressed;
|
|
{
|
|
INT cb;
|
|
KT kt = (KT)qbthr->bth.rgchFormat[ 0 ];
|
|
|
|
|
|
switch( kt )
|
|
{
|
|
case KT_SZMIN:
|
|
case KT_SZ:
|
|
case KT_SZI:
|
|
case KT_SZISCAND:
|
|
cb = lstrlen( (SZ)key ) + 1;
|
|
break;
|
|
|
|
case KT_SZDEL:
|
|
case KT_SZDELMIN:
|
|
if ( fCompressed )
|
|
{
|
|
cb = 1 + lstrlen( (SZ)key + 1 ) + 1;
|
|
}
|
|
else
|
|
{
|
|
cb = *(QB)key + lstrlen( (SZ)key + 1 ) + 1;
|
|
}
|
|
break;
|
|
|
|
case KT_ST:
|
|
case KT_STMIN:
|
|
case KT_STI:
|
|
cb = CbLenSt( (ST)key ) + 1/* ? */;
|
|
break;
|
|
|
|
case KT_STDEL:
|
|
case KT_STDELMIN:
|
|
if ( fCompressed )
|
|
{
|
|
cb = 1 + CbLenSt( (ST)key + 1 );
|
|
}
|
|
else
|
|
{
|
|
cb = *(QB)key + CbLenSt( (ST)key + 1 ) + 1;
|
|
}
|
|
break;
|
|
|
|
case KT_LONG:
|
|
cb = sizeof( LONG );
|
|
break;
|
|
|
|
case '1': case '2': case '3': case '4': case '5':
|
|
case '6': case '7': case '8': case '9':
|
|
cb = kt - '0';
|
|
break;
|
|
|
|
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
cb = kt - 'a' + 10;
|
|
break;
|
|
}
|
|
|
|
return cb;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
- Function: FIsPrefix( hbt, key1, key2 )
|
|
-
|
|
* Purpose: Determines whether string key1 is a prefix of key2.
|
|
*
|
|
* ASSUMES
|
|
* args IN: hbt - handle to a btree with string keys
|
|
* key1, key2 - not compressed
|
|
* state IN:
|
|
*
|
|
* PROMISES
|
|
* returns: TRUE if the string key1 is a prefix of the string key2
|
|
* FALSE if it isn't or if hbt doesn't contain string keys
|
|
* globals OUT: rcBtreeError
|
|
*
|
|
* Bugs: Doesn't work on STs yet
|
|
* +++
|
|
*
|
|
* Method: temporarily shortens the second string so it can
|
|
* compare prefixes
|
|
*
|
|
\***************************************************************************/
|
|
_public BOOL FAR PASCAL
|
|
FIsPrefix( hbt, key1, key2)
|
|
HBT hbt;
|
|
KEY key1, key2;
|
|
{
|
|
QBTHR qbthr;
|
|
INT cb1, cb2;
|
|
CHAR c;
|
|
KT kt;
|
|
BOOL f;
|
|
|
|
|
|
assert( hbt != NULL );
|
|
qbthr = QLockGh( hbt );
|
|
assert( qbthr != NULL );
|
|
|
|
kt = (KT)qbthr->bth.rgchFormat[ 0 ];
|
|
|
|
switch( kt )
|
|
{
|
|
case KT_SZMIN:
|
|
case KT_SZ:
|
|
case KT_SZI:
|
|
case KT_SZISCAND:
|
|
case KT_SZDEL:
|
|
case KT_SZDELMIN:
|
|
/* both keys assumed to have been decompressed */
|
|
cb1 = lstrlen( (SZ)key1 );
|
|
cb2 = lstrlen( (SZ)key2 );
|
|
SetBtreeErrorRc(rcSuccess);
|
|
break;
|
|
|
|
case KT_ST:
|
|
case KT_STMIN:
|
|
case KT_STI:
|
|
case KT_STDEL:
|
|
case KT_STDELMIN:
|
|
/* STs unimplemented */
|
|
SetBtreeErrorRc(rcUnimplemented);
|
|
UnlockGh( hbt );
|
|
return FALSE;
|
|
break;
|
|
|
|
case KT_LONG:
|
|
case '1': case '2': case '3': case '4': case '5':
|
|
case '6': case '7': case '8': case '9':
|
|
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
default:
|
|
/* prefix doesn't make sense */
|
|
SetBtreeErrorRc(rcInvalid);
|
|
UnlockGh( hbt );
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
if ( cb1 > cb2 )
|
|
{
|
|
UnlockGh( hbt );
|
|
return FALSE;
|
|
}
|
|
|
|
c = ((SZ)key2)[ cb1 ];
|
|
((SZ)key2)[ cb1 ] = '\0';
|
|
|
|
switch ( kt )
|
|
{
|
|
case KT_SZMIN:
|
|
case KT_SZ:
|
|
case KT_SZDEL:
|
|
case KT_SZDELMIN:
|
|
f = !strcmp( (SZ)key1, (SZ)key2 );
|
|
break;
|
|
|
|
case KT_SZI:
|
|
f = !WCmpiSz( (SZ)key1, (SZ)key2, qbthr->qbLigatures );
|
|
break;
|
|
|
|
case KT_SZISCAND:
|
|
f = !WCmpiScandSz( (SZ)key1, (SZ)key2 );
|
|
break;
|
|
|
|
default:
|
|
assert(FALSE);
|
|
break;
|
|
}
|
|
|
|
((SZ)key2)[ cb1 ] = c;
|
|
|
|
UnlockGh( hbt );
|
|
return f;
|
|
}
|
|
|
|
/* EOF */
|