STATIC LPHSXTABLE | hb_hsxTable( void )
static LPHSXTABLE hb_hsxTable( void )
{
return ( LPHSXTABLE ) hb_stackGetTSD( &s_hsxTable );
}
/* the conversion table for ASCII alpha pairs */
static const BYTE hb_hsxHashArray[] = {
/* A B C D E F G H I J K L M N O P Q R S T U W V X Y Z */
/* A */ 7,102,222,185, 19, 48,167, 4,173, 4, 79,251,194,250, 7,187, 7,251,209,249, 41,101, 39, 29, 71, 40,
/* B */ 156, 3, 7, 7,149, 7, 7, 7,172, 7, 7,100, 7, 7,148, 7, 7,107, 38, 7,126, 7, 7, 7, 7, 7,
/* C */ 234, 7, 38, 7,229, 7, 7,208,145, 7,116,106, 7, 7,253, 7, 7,166, 40,237,129, 7, 7, 7, 63, 4,
/* D */ 125, 4, 4, 29,253, 7, 28, 7,226, 7, 7, 3, 3, 4,128, 7, 7,124, 44, 4,115, 7, 4, 7, 37, 7,
/* E */ 193, 37,236,198,114, 94,105, 3, 44, 7, 4,245,159,251, 93,151, 36,248,253,252, 36, 70, 28,147, 19, 4,
/* F */ 92, 7, 7, 7,123, 78, 7, 7,180, 7, 7,150, 7, 7,122, 7, 7,104, 4, 35, 55, 7, 7, 7, 7, 7,
/* G */ 121, 7, 7, 7,195, 7, 2, 86, 77, 7, 7, 85, 2, 76, 55, 7, 7,179, 27, 4, 54, 7, 7, 7, 63, 7,
/* H */ 197, 7, 7, 7,228, 7, 7, 7,164, 7, 7, 18, 4, 1,220, 7, 7, 99, 7, 62, 35, 7, 7, 7,169, 7,
/* I */ 192, 98,250,207,155,143,158, 1, 7, 7, 1,212,163,248,250, 97, 7,178,225,252,142,120, 7, 4, 7, 84,
/* J */ 4, 7, 7, 7, 34, 7, 7, 6, 6, 6, 6, 6, 6, 6, 15, 6, 6, 6, 6, 6, 34, 6, 6, 6, 6, 6,
/* K */ 15, 6, 6, 6,135, 6, 6, 6, 69, 6, 6, 4, 6, 14, 14, 6, 6, 6, 14, 6, 6, 6, 6, 6, 27, 6,
/* L */ 253, 4, 13, 62,251, 18, 4, 6,255, 6, 26,213, 17, 6,238, 13, 6, 6, 83,162,154, 12, 6, 6,134, 6,
/* M */ 216, 54, 6, 6,254, 6, 6, 6,231, 6, 6, 6, 68, 12,223,140, 6, 6, 4, 6,146, 6, 6, 6, 4, 6,
/* N */ 230, 6,204,202,252, 53,246, 6,227, 4, 53, 4, 4, 43,205, 4, 6, 11,201,251, 75, 52, 11, 6, 33, 4,
/* O */ 74, 96,161,171, 33, 73,168, 17,133, 4, 10,243,244,248, 82,219, 6,250,210,215,191, 52,119, 51, 32, 4,
/* P */ 186, 6, 6, 6,232, 6, 6,224,160, 6, 6,190, 6, 6,217, 26, 6,189, 32, 90, 67, 6, 6, 6, 51, 6,
/* Q */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,111, 6, 6, 6, 6, 6, 6,
/* R */ 249, 89,117,113,250, 47,110, 47,252, 6, 46, 25,199,112,249,109, 6,139,183,144,138, 50, 10, 6,153, 6,
/* S */ 81, 6,175, 5,218, 9, 5,170,247, 5, 43, 66, 50, 16,206,177, 4, 5,176,252,182, 5, 9, 5, 61, 5,
/* T */ 242, 5, 16, 4,249, 5, 5,221,248, 5, 5, 25, 8, 5,241, 5, 5,250, 49,132,152, 5, 4, 5,181, 4,
/* U */ 80, 95, 88, 61, 60, 8, 46, 5, 60, 5, 5,214,196,184, 45,131, 5,203,188,174, 5, 5, 5, 4, 5, 5,
/* V */ 137, 5, 5, 5,200, 5, 5, 5,130, 5, 5, 5, 5, 5, 49, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5,
/* W */ 136, 5, 5, 5, 65, 5, 5, 31, 59, 5, 4, 4, 5, 23, 58, 5, 5, 4, 4, 5, 5, 5, 5, 5, 5, 5,
/* X */ 4, 5, 23, 5, 31, 5, 5, 5, 24, 5, 5, 5, 5, 5, 22, 22, 5, 5, 5, 45, 5, 5, 5, 5, 30, 5,
/* Y */ 30, 21, 42, 72, 21, 5, 4, 5, 4, 4, 4,127, 20,103, 20, 87, 4, 64,108, 4, 4, 4, 4, 4, 4, 4,
/* Z */ 42, 4, 4, 4, 56, 4, 4, 4, 24, 4, 4, 4, 4, 4, 41, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4 };
| hsx.c | 368 |
STATIC VOID | hb_hsxHashStr( BYTE * pStr, ULONG ulLen, BYTE * pKey, int iKeySize, BOOL fNoCase, int iFilter, BOOL fUseHash )
static void hb_hsxHashStr( BYTE * pStr, ULONG ulLen, BYTE * pKey, int iKeySize,
BOOL fNoCase, int iFilter, BOOL fUseHash )
{
int c1, c2, iBitNum, iKeyBits = iKeySize << 3;
memset( pKey, '\0', iKeySize );
#if 0
/* This code keeps the strict CFTS behavior which stops string
manipulating at first chr(0) character */
if( pStr && ulLen-- && ( c1 = *pStr++ ) != 0 )
{
while( ulLen-- && ( c2 = *pStr++ ) != 0 )
{
#else
/* This version can work well with embedded 0 characters */
if( pStr && ulLen-- )
{
c1 = *pStr++;
while( ulLen-- )
{
c2 = *pStr++;
#endif
iBitNum = hb_hsxHashVal( c1, c2, iKeyBits, fNoCase, iFilter, fUseHash );
if( iBitNum-- )
{
pKey[ iBitNum >> 3 ] |= 0x80 >> ( iBitNum & 7 );
}
c1 = c2;
}
}
}
static int hb_hsxStrCmp( BYTE * pSub, ULONG ulSub, BYTE * pStr, ULONG ulLen,
BOOL fNoCase, int iFilter )
{
BOOL fResult = FALSE;
BYTE c1, c2;
ULONG ul;
if( ulSub == 0 )
return HSX_SUCCESSFALSE;
while( !fResult && ulLen >= ulSub )
{
fResult = TRUE;
for( ul = 0; fResult && ul < ulSub; ul++ )
{
c1 = pSub[ ul ];
c2 = pStr[ ul ];
if( fNoCase )
{
#ifndef HB_CDP_SUPPORT_OFF
PHB_CODEPAGE cdp;
if( iFilter == 3 && ( cdp = hb_vmCDP() )->nChars )
{
c1 = ( BYTE ) cdp->s_upper[ c1 ];
c2 = ( BYTE ) cdp->s_upper[ c2 ];
}
else
#endif
{
if( c1 >= 'a' && c1 <= 'z' )
c1 -= 'a' - 'A';
if( c2 >= 'a' && c2 <= 'z' )
c2 -= 'a' - 'A';
}
}
#if 0
/* This code is for strict CftsVeri() behavior - uncomment if necessary
but it's IMHO bug */
if( iFilter == 1 )
{
c1 &= 0x7F;
if( c1 < 0x20 || c1 == 0x7f ) c1 = ' ';
c2 &= 0x7F;
if( c2 < 0x20 || c2 == 0x7f ) c2 = ' ';
}
#elif defined( HB_CDP_SUPPORT_OFF )
HB_SYMBOL_UNUSED( iFilter );
#endif
fResult = ( c1 == c2 );
}
--ulLen;
++pStr;
}
return fResult ? HSX_SUCCESS : HSX_SUCCESSFALSE;
}
static LPHSXINFO hb_hsxGetPointer( int iHandle )
{
LPHSXTABLE pTable = hb_hsxTable();
return ( iHandle >=0 && iHandle < pTable->iHandleSize ) ?
pTable->handleArray[ iHandle ] : NULL;
}
static int hb_hsxCompile( char * szExpr, PHB_ITEM * pExpr )
{
AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
*pExpr = NULL;
if( pArea )
{
if( SELF_COMPILE( pArea, ( BYTE * ) szExpr ) == FAILURE )
return HSX_BADPARMS;
*pExpr = pArea->valResult;
pArea->valResult = NULL;
}
else
{
HB_MACRO_PTR pMacro = hb_macroCompile( szExpr );
if( !pMacro )
return HSX_BADPARMS;
*pExpr = hb_itemPutPtr( NULL, ( void * ) pMacro );
}
return HSX_SUCCESS;
}
static int hb_hsxEval( int iHandle, PHB_ITEM pExpr, BYTE *pKey, BOOL *fDeleted )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iResult = HSX_SUCCESS;
BYTE * pStr;
ULONG ulLen;
if( ! pHSX )
return HSX_BADHANDLE;
if( !pExpr )
pExpr = pHSX->pKeyItem;
if( !pExpr )
return HSX_BADPARMS;
if( hb_itemType( pExpr ) & HB_IT_STRING )
{
pStr = ( BYTE * ) hb_itemGetCPtr( pExpr );
ulLen = hb_itemGetCLen( pExpr );
if( fDeleted )
*fDeleted = FALSE;
}
else
{
int iArea = 0;
PHB_ITEM pItem;
if( pHSX->iArea != 0 )
{
iArea = hb_rddGetCurrentWorkAreaNumber();
if( iArea != pHSX->iArea )
hb_rddSelectWorkAreaNumber( pHSX->iArea );
else
iArea = 0;
}
pItem = hb_vmEvalBlockOrMacro( pExpr );
pStr = ( BYTE * ) hb_itemGetCPtr( pItem );
ulLen = hb_itemGetCLen( pItem );
if( fDeleted )
{
AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
if( !pArea )
*fDeleted = FALSE;
else if( SELF_DELETED( pArea, fDeleted ) == FAILURE )
iResult = HSX_RDDFAILURE;
}
if( iArea )
hb_rddSelectWorkAreaNumber( iArea );
if( hb_vmRequestQuery() )
iResult = HSX_BADPARMS;
}
if( iResult == HSX_SUCCESS )
hb_hsxHashStr( pStr, ulLen, pKey, pHSX->uiRecordSize, pHSX->fIgnoreCase,
pHSX->iFilterType, pHSX->fUseHash );
return iResult;
}
static void hb_hsxGetRecCount( LPHSXINFO pHSX )
{
pHSX->ulRecCount = ( ULONG ) ( ( hb_fileSize( pHSX->pFile ) -
HSXHEADER_LEN ) / pHSX->uiRecordSize );
}
static int hb_hsxHdrFlush( int iHandle )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
if( ! pHSX )
return HSX_BADHANDLE;
if( pHSX->fHdrChanged )
{
BYTE headrBuf[ HSXHEADER_LEN ];
LPHSXHEADER pHeader = ( LPHSXHEADER ) headrBuf;
USHORT uiBits = 0, uiSize = pHSX->uiRecordSize;
while( uiSize >>= 1 )
uiBits++;
HB_PUT_LE_UINT32( pHeader->recCount, pHSX->ulRecCount );
HB_PUT_LE_UINT32( pHeader->recSize, ( UINT32 ) pHSX->uiRecordSize );
HB_PUT_LE_UINT32( pHeader->recSizeBits, ( UINT32 ) uiBits );
HB_PUT_LE_UINT16( pHeader->ignoreCase, pHSX->fIgnoreCase ? 1 : 0 );
HB_PUT_LE_UINT16( pHeader->filterType, pHSX->iFilterType );
HB_PUT_LE_UINT32( pHeader->hashLetters, pHSX->fUseHash ? 1 : 0 );
memset( pHeader->keyExpression, 0, HSXKEYEXP_LEN + 1 );
if( pHSX->szKeyExpr )
hb_strncpy( ( char * ) pHeader->keyExpression, pHSX->szKeyExpr, HSXKEYEXP_LEN );
if( hb_fileWriteAt( pHSX->pFile, headrBuf, HSXHEADER_LEN, 0 ) != HSXHEADER_LEN )
return HSX_BADHDRWRITE;
pHSX->fHdrChanged = FALSE;
pHSX->fFlush = TRUE;
}
return HSX_SUCCESS;
}
static int hb_hsxFlush( int iHandle )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
if( ! pHSX )
return HSX_BADHANDLE;
if( pHSX->fChanged )
{
HB_FOFFSET fOffset;
ULONG ulSize;
fOffset = ( HB_FOFFSET ) HSXHEADER_LEN +
( HB_FOFFSET ) ( pHSX->ulFirstRec - 1 ) *
( HB_FOFFSET ) pHSX->uiRecordSize;
ulSize = pHSX->ulBufRec * pHSX->uiRecordSize;
if( hb_fileWriteAt( pHSX->pFile, pHSX->pBuffer, ulSize, fOffset ) != ulSize )
return HSX_BADWRITE;
pHSX->fChanged = FALSE;
pHSX->fFlush = TRUE;
}
return HSX_SUCCESS;
}
static int hb_hsxFlushAll( int iHandle )
{
int iRetVal;
iRetVal = hb_hsxFlush( iHandle );
if( iRetVal == HSX_SUCCESS )
iRetVal = hb_hsxHdrFlush( iHandle );
return iRetVal;
}
static int hb_hsxHdrRead( int iHandle )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
BYTE headrBuf[ HSXHEADER_LEN ];
LPHSXHEADER pHeader = ( LPHSXHEADER ) headrBuf;
int iResult = HSX_SUCCESS;
if( ! pHSX )
return HSX_BADHANDLE;
if( hb_fileReadAt( pHSX->pFile, headrBuf, HSXHEADER_LEN, 0 ) != HSXHEADER_LEN )
return HSX_BADREAD;
pHSX->ulRecCount = HB_GET_LE_UINT32( pHeader->recCount );
pHSX->uiRecordSize = HB_GET_LE_UINT32( pHeader->recSize );
pHSX->fIgnoreCase = HB_GET_LE_UINT16( pHeader->ignoreCase ) != 0;
pHSX->iFilterType = HB_GET_LE_UINT16( pHeader->filterType );
pHSX->fUseHash = HB_GET_LE_UINT32( pHeader->hashLetters ) != 0;
if( pHeader->keyExpression[0] >= ' ' )
{
headrBuf[ HSXHEADER_LEN - 1 ] = '\0';
pHSX->szKeyExpr = hb_strdup( ( char * ) pHeader->keyExpression );
iResult = hb_hsxCompile( pHSX->szKeyExpr, &pHSX->pKeyItem );
}
/* update the record counter */
hb_hsxGetRecCount( pHSX );
return iResult;
}
static int hb_hsxRead( int iHandle, ULONG ulRecord, BYTE ** pRecPtr )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
BOOL fCount = pHSX->fShared;
if( ! pHSX )
return HSX_BADHANDLE;
if( ulRecord > pHSX->ulRecCount && fCount )
{
hb_hsxGetRecCount( pHSX );
fCount = FALSE;
}
if( ulRecord == 0 || ulRecord > pHSX->ulRecCount )
return HSX_RECBOUND;
if( pHSX->ulFirstRec == 0 || ulRecord < pHSX->ulFirstRec ||
ulRecord >= pHSX->ulFirstRec + pHSX->ulBufRec )
{
HB_FOFFSET fOffset;
ULONG ulSize, ulFirst;
int iRetVal;
if( ( iRetVal = hb_hsxFlush( iHandle ) ) != HSX_SUCCESS )
return iRetVal;
ulFirst = ulRecord;
if( pHSX->fWrLocked && pHSX->fShared )
pHSX->ulBufRec = 1;
else if( ulFirst + pHSX->ulBufSize - 1 <= pHSX->ulRecCount )
pHSX->ulBufRec = pHSX->ulBufSize;
else
{
if( fCount )
hb_hsxGetRecCount( pHSX );
pHSX->ulBufRec = HB_MIN( pHSX->ulBufSize, pHSX->ulRecCount - ulFirst + 1 );
}
fOffset = ( HB_FOFFSET ) HSXHEADER_LEN +
( HB_FOFFSET ) ( ulFirst - 1 ) *
( HB_FOFFSET ) pHSX->uiRecordSize;
ulSize = pHSX->ulBufRec * pHSX->uiRecordSize;
if( hb_fileReadAt( pHSX->pFile, pHSX->pBuffer, ulSize, fOffset ) != ulSize )
{
pHSX->ulFirstRec = pHSX->ulBufRec = 0;
return HSX_BADREAD;
}
pHSX->ulFirstRec = ulFirst;
}
*pRecPtr = pHSX->pBuffer + ( ulRecord - pHSX->ulFirstRec ) * pHSX->uiRecordSize;
return HSX_SUCCESS;
}
static int hb_hsxAppend( int iHandle, ULONG * pulRecNo, BYTE **pRecPtr )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
if( ! pHSX )
return HSX_BADHANDLE;
if( pHSX->ulFirstRec == 0 || pHSX->ulBufRec == pHSX->ulBufSize ||
pHSX->ulFirstRec + pHSX->ulBufRec != pHSX->ulRecCount + 1 )
{
int iRetVal;
if( ( iRetVal = hb_hsxFlush( iHandle ) ) != HSX_SUCCESS )
return iRetVal;
*pulRecNo = pHSX->ulFirstRec = ++pHSX->ulRecCount;
pHSX->ulBufRec = 1;
}
else
{
pHSX->ulBufRec++;
*pulRecNo = ++pHSX->ulRecCount;
}
*pRecPtr = pHSX->pBuffer + ( pHSX->ulBufRec - 1 ) * pHSX->uiRecordSize;
pHSX->fHdrChanged = TRUE;
return HSX_SUCCESS;
}
static int hb_hsxUpdate( int iHandle, ULONG ulRecord, BYTE **pRecPtr )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
if( ! pHSX )
return HSX_BADHANDLE;
if( ulRecord > pHSX->ulRecCount )
{
/* this is intentional - when HSX index is bound with workarea
* then all updates should be synced by WA locks and it should
* be save to use REPLACE called from GOCOLD() method instead of
* ADD for newly appended records */
if( pHSX->iArea != 0 )
pHSX->ulRecCount = ulRecord;
else if( pHSX->fShared )
hb_hsxGetRecCount( pHSX );
}
if( ulRecord == 0 || ulRecord > pHSX->ulRecCount )
return HSX_RECBOUND;
if( pHSX->ulFirstRec == 0 || ulRecord < pHSX->ulFirstRec ||
ulRecord >= pHSX->ulFirstRec + pHSX->ulBufRec )
{
int iRetVal;
if( ( iRetVal = hb_hsxFlush( iHandle ) ) != HSX_SUCCESS )
return iRetVal;
pHSX->ulFirstRec = ulRecord;
pHSX->ulBufRec = 1;
}
*pRecPtr = pHSX->pBuffer + ( ulRecord - pHSX->ulFirstRec ) * pHSX->uiRecordSize;
return HSX_SUCCESS;
}
static int hb_hsxLock( int iHandle, int iAction, ULONG ulRecord )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iRetVal = HSX_SUCCESS, iRet;
BOOL fResult;
HB_SYMBOL_UNUSED( ulRecord );
if( ! pHSX )
return HSX_BADHANDLE;
if( pHSX->fReadonly )
{
switch( iAction )
{
case HSX_WRITELOCK:
case HSX_UPDATELOCK:
case HSX_APPENDLOCK:
case HSX_HDRWRITELOCK:
return HSX_LOCKFAILED;
}
}
/*
* When HSX is bound with with workarea it should be synced
* by WA locks to not cause additional overhead with repeated
* operations. hb_hsxAdd() should be called when WA APPEND_LOCK
* is set and hb_hsxReplace() inside GOCOLD() method
*/
if( pHSX->fShared && pHSX->iArea == 0 )
{
switch( iAction )
{
case HSX_READLOCK:
break;
case HSX_WRITELOCK:
case HSX_UPDATELOCK:
case HSX_APPENDLOCK:
for( ;; )
{
fResult = hb_fileLock( pHSX->pFile, HSX_HDRLOCKPOS, HSX_HDRLOCKSIZE,
FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT );
if( fResult )
break;
hb_releaseCPU();
}
if( iRetVal == HSX_SUCCESS )
{
/* discrad buffers in shared mode */
pHSX->ulFirstRec = pHSX->ulBufRec = 0;
if( iAction == HSX_APPENDLOCK )
hb_hsxGetRecCount( pHSX );
else if( iAction == HSX_WRITELOCK )
pHSX->fWrLocked = TRUE;
}
break;
case HSX_HDRREADLOCK:
for( ;; )
{
fResult = hb_fileLock( pHSX->pFile, HSX_HDRLOCKPOS, HSX_HDRLOCKSIZE,
FL_LOCK | FLX_SHARED | FLX_WAIT );
if( fResult )
break;
hb_releaseCPU();
}
break;
case HSX_HDRWRITELOCK:
for( ;; )
{
fResult = hb_fileLock( pHSX->pFile, HSX_HDRLOCKPOS, HSX_HDRLOCKSIZE,
FL_LOCK | FLX_EXCLUSIVE | FLX_WAIT );
if( fResult )
break;
hb_releaseCPU();
}
break;
case HSX_READUNLOCK:
break;
case HSX_WRITEUNLOCK:
case HSX_UPDATEUNLOCK:
case HSX_APPENDUNLOCK:
iRetVal = hb_hsxFlush( iHandle );
if( iAction == HSX_APPENDLOCK )
pHSX->fWrLocked = FALSE;
case HSX_HDRWRITEUNLOCK:
iRet = hb_hsxHdrFlush( iHandle );
if( iRetVal == HSX_SUCCESS )
iRetVal = iRet;
case HSX_HDRREADUNLOCK:
if( ! hb_fileLock( pHSX->pFile, HSX_HDRLOCKPOS, HSX_HDRLOCKSIZE,
FL_UNLOCK ) )
{
if( iRetVal == HSX_SUCCESS )
iRetVal = HSX_CANNOTUNLOCK;
}
break;
}
}
return iRetVal;
}
static int hb_hsxIfDel( int iHandle, ULONG ulRecord )
{
BYTE *pRecPtr;
int iRetVal, iRet;
iRetVal = hb_hsxLock( iHandle, HSX_READLOCK, ulRecord );
if( iRetVal == HSX_SUCCESS )
{
iRetVal = hb_hsxRead( iHandle, ulRecord, &pRecPtr );
if( iRetVal == HSX_SUCCESS )
iRetVal = *pRecPtr & 0x80 ? HSX_SUCCESS : HSX_SUCCESSFALSE;
}
iRet = hb_hsxLock( iHandle, HSX_READUNLOCK, ulRecord );
if( iRet != HSX_SUCCESS )
iRetVal = iRet;
return iRetVal;
}
static int hb_hsxDelete( int iHandle, ULONG ulRecord )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iRetVal, iRet;
if( ! pHSX )
return HSX_BADHANDLE;
iRetVal = hb_hsxLock( iHandle, HSX_UPDATELOCK, ulRecord );
if( iRetVal == HSX_SUCCESS )
{
BYTE *pRecPtr;
iRetVal = hb_hsxRead( iHandle, ulRecord, &pRecPtr );
if( iRetVal == HSX_SUCCESS )
{
if( *pRecPtr & 0x80 )
iRetVal = HSX_ISDELETED;
else
{
*pRecPtr |= 0x80;
pHSX->fChanged = TRUE;
iRetVal = HSX_SUCCESS;
}
}
iRet = hb_hsxLock( iHandle, HSX_UPDATEUNLOCK, ulRecord );
if( iRetVal == HSX_SUCCESS )
iRetVal = iRet;
}
return iRetVal;
}
static int hb_hsxUnDelete( int iHandle, ULONG ulRecord )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iRetVal, iRet;
if( ! pHSX )
return HSX_BADHANDLE;
iRetVal = hb_hsxLock( iHandle, HSX_UPDATELOCK, ulRecord );
if( iRetVal == HSX_SUCCESS )
{
BYTE *pRecPtr;
iRetVal = hb_hsxRead( iHandle, ulRecord, &pRecPtr );
if( iRetVal == HSX_SUCCESS )
{
if( ( *pRecPtr & 0x80 ) == 0 )
iRetVal = HSX_NOTDELETED;
else
{
*pRecPtr &= ~0x80;
pHSX->fChanged = TRUE;
iRetVal = HSX_SUCCESS;
}
}
iRet = hb_hsxLock( iHandle, HSX_UPDATEUNLOCK, ulRecord );
if( iRetVal == HSX_SUCCESS )
iRetVal = iRet;
}
return iRetVal;
}
static int hb_hsxReplace( int iHandle, ULONG ulRecord, PHB_ITEM pExpr, BOOL fDeleted )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iRetVal, iRet;
if( ! pHSX )
return HSX_BADHANDLE;
iRetVal = hb_hsxLock( iHandle, HSX_WRITELOCK, ulRecord );
if( iRetVal == HSX_SUCCESS )
{
BYTE * pRecPtr;
iRetVal = hb_hsxUpdate( iHandle, ulRecord, &pRecPtr );
if( iRetVal == HSX_SUCCESS )
{
iRetVal = hb_hsxEval( iHandle, pExpr, pRecPtr, pExpr ? NULL : &fDeleted );
if( iRetVal == HSX_SUCCESS )
{
if( fDeleted )
*pRecPtr |= 0x80;
pHSX->fChanged = TRUE;
}
}
iRet = hb_hsxLock( iHandle, HSX_WRITEUNLOCK, ulRecord );
if( iRetVal == HSX_SUCCESS )
iRetVal = iRet;
}
return iRetVal;
}
static int hb_hsxAdd( int iHandle, ULONG *pulRecNo, PHB_ITEM pExpr, BOOL fDeleted )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iRetVal, iRet;
if( ! pHSX )
return HSX_BADHANDLE;
if( !pExpr && !pHSX->pKeyItem )
return HSX_BADPARMS;
iRetVal = hb_hsxLock( iHandle, HSX_APPENDLOCK, 0 );
if( iRetVal == HSX_SUCCESS )
{
BYTE * pRecPtr;
ULONG ulRecNo;
iRetVal = hb_hsxAppend( iHandle, &ulRecNo, &pRecPtr );
if( iRetVal == HSX_SUCCESS )
{
iRetVal = hb_hsxEval( iHandle, pExpr, pRecPtr, pExpr ? NULL : &fDeleted );
if( iRetVal == HSX_SUCCESS )
{
if( fDeleted )
*pRecPtr |= 0x80;
pHSX->fChanged = TRUE;
if( pulRecNo )
*pulRecNo = ulRecNo;
}
}
iRet = hb_hsxLock( iHandle, HSX_APPENDUNLOCK, 0 );
if( iRetVal == HSX_SUCCESS )
iRetVal = iRet;
}
return iRetVal;
}
static int hb_hsxSeekSet( int iHandle, BYTE * pStr, ULONG ulLen )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iRetVal;
if( !pHSX )
return HSX_BADHANDLE;
iRetVal = hb_hsxFlushAll( iHandle );
if( iRetVal == HSX_SUCCESS )
{
if( pHSX->ulRecCount == 0 )
iRetVal = HSX_NORECS;
else
{
if( pHSX->pSearchVal )
hb_xfree( pHSX->pSearchVal );
pHSX->pSearchVal = ( BYTE * ) hb_xgrab( ulLen + 1 );
memcpy( pHSX->pSearchVal, pStr, ulLen );
pHSX->pSearchVal[ ulLen ] = '\0';
pHSX->ulSearch = ulLen;
if( ! pHSX->pSearchKey )
pHSX->pSearchKey = ( BYTE * ) hb_xgrab( pHSX->uiRecordSize );
hb_hsxHashStr( pStr, ulLen, pHSX->pSearchKey,
pHSX->uiRecordSize, pHSX->fIgnoreCase,
pHSX->iFilterType, pHSX->fUseHash );
pHSX->ulCurrRec = 0;
}
}
return iRetVal;
}
static int hb_hsxNext( int iHandle, ULONG * pulRecNo )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iRetVal, iRet;
*pulRecNo = 0;
if( ! pHSX )
return HSX_BADHANDLE;
iRetVal = hb_hsxLock( iHandle, HSX_READLOCK, 0 );
if( iRetVal == HSX_SUCCESS )
{
BYTE * pRecPtr;
int i;
while( pHSX->ulCurrRec < pHSX->ulRecCount )
{
iRetVal = hb_hsxRead( iHandle, ++pHSX->ulCurrRec, &pRecPtr );
if( iRetVal != HSX_SUCCESS )
break;
if( ! hb_setGetDeleted() || ( *pRecPtr & 0x80 ) == 0 ) /* Not deleted */
{
for( i = 0; i < pHSX->uiRecordSize; i++ )
{
if( ( pRecPtr[ i ] & pHSX->pSearchKey[ i ] ) != pHSX->pSearchKey[ i ] )
break;
}
if( i == pHSX->uiRecordSize )
{
*pulRecNo = pHSX->ulCurrRec;
break;
}
}
}
iRet = hb_hsxLock( iHandle, HSX_READUNLOCK, 0 );
if( iRetVal == HSX_SUCCESS )
iRetVal = iRet;
}
return iRetVal;
}
static LPHSXINFO hb_hsxNew( void )
{
LPHSXINFO pHSX;
int iHandle = 0;
LPHSXTABLE pTable = hb_hsxTable();
if( pTable->iHandleSize == 0 )
{
pTable->iHandleSize = HSX_HALLOC;
pTable->handleArray = ( LPHSXINFO * ) hb_xgrab( sizeof( LPHSXINFO ) * HSX_HALLOC );
memset( pTable->handleArray, 0, sizeof( LPHSXINFO ) * pTable->iHandleSize );
}
else
{
while( iHandle < pTable->iHandleSize )
{
if( pTable->handleArray[ iHandle ] == NULL )
break;
iHandle++;
}
if( iHandle == pTable->iHandleSize )
{
pTable->iHandleSize += HSX_HALLOC;
pTable->handleArray = ( LPHSXINFO * ) hb_xrealloc( pTable->handleArray,
sizeof( LPHSXINFO ) * pTable->iHandleSize );
memset( &pTable->handleArray[ iHandle ], 0, sizeof( LPHSXINFO ) * HSX_HALLOC );
}
}
pTable->handleArray[ iHandle ] = pHSX = ( LPHSXINFO ) hb_xgrab( sizeof( HSXINFO ) );
pTable->iHandleCount++;
memset( pHSX, 0, sizeof( HSXINFO ) );
pHSX->iHandle = iHandle;
pHSX->pFile = NULL;
return pHSX;
}
static void hb_hsxExpDestroy( PHB_ITEM pItem )
{
if( hb_itemType( pItem ) == HB_IT_POINTER )
hb_macroDelete( ( HB_MACRO_PTR ) hb_itemGetPtr( pItem ) );
hb_itemRelease( pItem );
}
static int hb_hsxVerify( int iHandle, BYTE * szText, ULONG ulLen,
BYTE * szSub, ULONG ulSub, int iType )
{
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
int iResult;
if( !szSub && pHSX )
{
szSub = pHSX->pSearchVal;
ulSub = pHSX->ulSearch;
}
if( !pHSX )
iResult = HSX_BADHANDLE;
else if( !szText || !szSub )
iResult = HSX_BADPARMS;
else if( ulSub > ulLen || ulSub == 0 )
/* !ulSub -> do not accept empty substrings as $ operator at runtime */
iResult = HSX_SUCCESSFALSE;
else
{
ULONG ul, ull;
switch( iType )
{
case HSX_VERIFY_BEGIN:
iResult = hb_hsxStrCmp( szSub, ulSub, szText, ulSub,
pHSX->fIgnoreCase, pHSX->iFilterType );
break;
case HSX_VERIFY_END:
iResult = hb_hsxStrCmp( szSub, ulSub, szText + ulLen - ulSub, ulSub,
pHSX->fIgnoreCase, pHSX->iFilterType );
break;
case HSX_VERIFY_AND:
iResult = HSX_SUCCESS;
for( ul = 0; ul < ulSub && iResult == HSX_SUCCESS; ul++ )
{
while( szSub[ ul ] == ' ' && ul < ulSub )
++ul;
ull = ul;
while( szSub[ ull ] != ' ' && ull < ulSub )
++ull;
iResult = hb_hsxStrCmp( &szSub[ ul ], ull - ul, szText, ulLen,
pHSX->fIgnoreCase, pHSX->iFilterType );
ul = ull;
}
break;
/*
case HSX_VERIFY_OR:
iResult = HSX_SUCCESSFALSE;
for( ul = 0; ul < ulSub && iResult == HSX_SUCCESSFALSE; ul++ )
{
while( szSub[ ul ] == ' ' && ul < ulSub )
++ul;
ull = ul;
while( szSub[ ull ] != ' ' && ull < ulSub )
++ull;
iResult = hb_hsxStrCmp( &szSub[ ul ], ull - ul, szText, ulLen,
pHSX->fIgnoreCase, pHSX->iFilterType );
ul = ull;
}
break;
*/
case HSX_VERIFY_PHRASE:
default:
iResult = hb_hsxStrCmp( szSub, ulSub, szText, ulLen,
pHSX->fIgnoreCase, pHSX->iFilterType );
}
}
return iResult;
}
static int hb_hsxDestroy( int iHandle )
{
LPHSXTABLE pTable = hb_hsxTable();
if( iHandle >=0 && iHandle < pTable->iHandleSize && pTable->handleArray[ iHandle ] != NULL )
{
LPHSXINFO pHSX = pTable->handleArray[ iHandle ];
int iRetVal = HSX_SUCCESS;
if( pHSX->pFile )
{
iRetVal = hb_hsxFlushAll( iHandle );
hb_fileClose( pHSX->pFile );
}
if( pHSX->szFileName )
hb_xfree( pHSX->szFileName );
if( pHSX->pSearchVal )
hb_xfree( pHSX->pSearchVal );
if( pHSX->pSearchKey )
hb_xfree( pHSX->pSearchKey );
if( pHSX->pBuffer )
hb_xfree( pHSX->pBuffer );
if( pHSX->szKeyExpr )
hb_xfree( pHSX->szKeyExpr );
if( pHSX->pKeyItem )
hb_hsxExpDestroy( pHSX->pKeyItem );
hb_xfree( pHSX );
pTable->handleArray[ iHandle ] = NULL;
if( --pTable->iHandleCount == 0 )
{
hb_xfree( pTable->handleArray );
pTable->iHandleSize = 0;
pTable->handleArray = NULL;
}
return iRetVal;
}
return HSX_BADHANDLE;
}
static int hb_hsxCreate( char * szFile, int iBufSize, int iKeySize,
BOOL fIgnoreCase, int iFilter, PHB_ITEM pExpr )
{
char szFileName[ _POSIX_PATH_MAX + 1 ], * szExpr = NULL;
PHB_ITEM pKeyExpr = NULL;
ULONG ulBufSize;
USHORT uiRecordSize;
LPHSXINFO pHSX;
PHB_FILE pFile;
int iRetVal;
if( !szFile || ! *szFile )
return HSX_BADPARMS;
hb_strncpy( szFileName, szFile, _POSIX_PATH_MAX );
if( iKeySize < 1 || iKeySize > HSXMAXKEY_SIZE )
iKeySize = HSXDEFKEY_SIZE;
if( iFilter < 1 || iFilter > 3 )
iFilter = HSXDEFFILTER;
ulBufSize = iBufSize * 1024;
if( ulBufSize == 0 )
ulBufSize = HSXDEFBUF_LEN;
else if( ulBufSize < HSXMINBUF_LEN )
ulBufSize = HSXMINBUF_LEN;
else if( ulBufSize > HSXMAXBUF_LEN )
ulBufSize = HSXMAXBUF_LEN;
uiRecordSize = ( USHORT ) 0x08 << iKeySize;
ulBufSize /= uiRecordSize;
if( ulBufSize == 0 )
ulBufSize = 1;
if( pExpr )
{
if( hb_itemGetCLen( pExpr ) > 0 )
{
szExpr = hb_itemGetCPtr( pExpr );
iRetVal = hb_hsxCompile( szExpr, &pKeyExpr );
if( iRetVal != HSX_SUCCESS )
return iRetVal;
}
else if( hb_itemType( pExpr ) == HB_IT_BLOCK )
pKeyExpr = hb_itemNew( pExpr );
}
pFile = hb_fileExtOpen( ( BYTE * ) szFileName, ( BYTE * ) HSX_FILEEXT,
FO_READWRITE | FO_EXCLUSIVE | FXO_TRUNCATE |
FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME,
NULL, NULL );
if( !pFile )
{
if( pKeyExpr )
hb_hsxExpDestroy( pKeyExpr );
return HSX_CREATEFAIL;
}
pHSX = hb_hsxNew();
pHSX->uiRecordSize = uiRecordSize;
pHSX->fIgnoreCase = fIgnoreCase;
pHSX->iFilterType = iFilter;
pHSX->fUseHash = fIgnoreCase && iKeySize == 2 && iFilter != 3;
pHSX->pFile = pFile;
pHSX->szFileName = hb_strdup( szFileName );
pHSX->fShared = FALSE;
pHSX->fReadonly = FALSE;
if( szExpr )
pHSX->szKeyExpr = hb_strdup( szExpr );
pHSX->pKeyItem = pKeyExpr;
pHSX->pBuffer = ( BYTE * ) hb_xalloc( ulBufSize * uiRecordSize );
if( pHSX->pBuffer == NULL )
{
hb_hsxDestroy( pHSX->iHandle );
return HSX_MEMERR;
}
pHSX->ulBufSize = ulBufSize;
pHSX->fHdrChanged = TRUE;
iRetVal = hb_hsxHdrFlush( pHSX->iHandle );
if( iRetVal != HSX_SUCCESS )
{
hb_hsxDestroy( pHSX->iHandle );
return iRetVal;
}
return pHSX->iHandle;
}
static int hb_hsxOpen( char * szFile, int iBufSize, int iMode )
{
char szFileName[ _POSIX_PATH_MAX + 1 ];
BOOL fShared, fReadonly;
PHB_FILE pFile;
ULONG ulBufSize;
USHORT uiFlags;
LPHSXINFO pHSX;
int iRetVal, iRet;
if( !szFile || ! *szFile )
return HSX_BADPARMS;
hb_strncpy( szFileName, szFile, _POSIX_PATH_MAX );
ulBufSize = iBufSize * 1024;
if( ulBufSize == 0 )
ulBufSize = HSXDEFBUF_LEN;
else if( ulBufSize < HSXMINBUF_LEN )
ulBufSize = HSXMINBUF_LEN;
else if( ulBufSize > HSXMAXBUF_LEN )
ulBufSize = HSXMAXBUF_LEN;
if( iMode < 0 || iMode > 3 )
iMode = HSXDEFOPENMODE;
fReadonly = ( iMode & 0x02 ) != 0;
fShared = ( iMode & 0x01 ) == 0;
if( hb_setGetAutoShare() == 2 )
fShared = FALSE;
uiFlags = ( fReadonly ? FO_READ : FO_READWRITE ) |
( fShared ? FO_DENYNONE : FO_EXCLUSIVE );
pFile = hb_fileExtOpen( ( BYTE * ) szFileName, ( BYTE * ) HSX_FILEEXT,
uiFlags | FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME,
NULL, NULL );
if( !pFile )
return HSX_OPENERR;
pHSX = hb_hsxNew();
pHSX->pFile = pFile;
pHSX->szFileName = hb_strdup( szFileName );
pHSX->fShared = fShared;
pHSX->fReadonly = fReadonly;
iRetVal = hb_hsxLock( pHSX->iHandle, HSX_HDRREADLOCK, 0 );
if( iRetVal == HSX_SUCCESS )
{
iRetVal = hb_hsxHdrRead( pHSX->iHandle );
iRet = hb_hsxLock( pHSX->iHandle, HSX_HDRREADUNLOCK, 0 );
if( iRetVal == HSX_SUCCESS )
iRetVal = iRet;
}
if( iRetVal != HSX_SUCCESS )
{
hb_hsxDestroy( pHSX->iHandle );
return iRetVal;
}
ulBufSize /= pHSX->uiRecordSize;
if( ulBufSize == 0 )
ulBufSize = 1;
pHSX->pBuffer = ( BYTE * ) hb_xalloc( ulBufSize * pHSX->uiRecordSize );
if( pHSX->pBuffer == NULL )
{
hb_hsxDestroy( pHSX->iHandle );
return HSX_MEMERR;
}
pHSX->ulBufSize = ulBufSize;
return pHSX->iHandle;
}
static int hb_hsxIndex( char * szFile, PHB_ITEM pExpr, int iKeySize, int iMode,
int iBufSize, BOOL fIgnoreCase, int iFilter )
{
int iRetVal = HSX_SUCCESS, iHandle;
ULONG ulRecNo = 0, ulRecCount = 0, ulNewRec, ulRec;
ERRCODE errCode;
AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
if( !pArea )
{
hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "HS_INDEX" );
return HSX_NOTABLE;
}
iHandle = hb_hsxCreate( szFile, iBufSize, iKeySize, fIgnoreCase, iFilter, pExpr );
if( iHandle < 0 )
return iHandle;
errCode = SELF_RECCOUNT( pArea, &ulRecCount );
if( errCode != FAILURE && ulRecCount )
{
errCode = SELF_RECNO( pArea, &ulRecNo );
if( errCode != FAILURE )
{
for( ulRec = 1; ulRec <= ulRecCount; ulRec++ )
{
errCode = SELF_GOTO( pArea, ulRec );
if( errCode == FAILURE )
break;
iRetVal = hb_hsxAdd( iHandle, &ulNewRec, NULL, FALSE );
if( iRetVal != HSX_SUCCESS )
break;
if( ulNewRec != ulRec )
{
iRetVal = HSX_RECBOUND;
break;
}
}
if( pArea->valResult )
{
hb_itemRelease( pArea->valResult );
pArea->valResult = NULL;
}
if( ulRecNo )
SELF_GOTO( pArea, ulRecNo );
}
}
hb_hsxDestroy( iHandle );
if( iRetVal != HSX_SUCCESS )
return iRetVal;
if( errCode == FAILURE )
return HSX_RDDFAILURE;
return hb_hsxOpen( szFile, iBufSize, iMode );
}
static int hb_hsxFilter( int iHandle, BYTE * pSeek, ULONG ulSeek,
PHB_ITEM pVerify, int iVerifyType )
{
AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
LPHSXINFO pHSX = hb_hsxGetPointer( iHandle );
BOOL fDestroyExpr = FALSE, fValid;
int iResult = HSX_SUCCESS;
ERRCODE errCode;
ULONG ulRecNo = 0, ulRec;
PHB_ITEM pItem;
if( !pHSX )
return HSX_BADHANDLE;
if( !pArea )
{
hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "HS_FILTER" );
return HSX_NOTABLE;
}
if( ! pVerify || hb_itemType( pVerify ) == HB_IT_NIL )
pVerify = pHSX->pKeyItem;
else
{
if( hb_itemGetCLen( pVerify ) > 0 )
{
iResult = hb_hsxCompile( hb_itemGetCPtr( pVerify ), &pVerify );
if( iResult != HSX_SUCCESS )
return HSX_BADPARMS;
fDestroyExpr = TRUE;
}
else if( hb_itemType( pVerify ) != HB_IT_BLOCK )
{
pVerify = NULL;
}
}
errCode = SELF_RECNO( pArea, &ulRecNo );
if( errCode != FAILURE )
iResult = hb_hsxSeekSet( iHandle, pSeek, ulSeek );
fValid = TRUE;
pItem = hb_itemNew( NULL );
while( iResult == HSX_SUCCESS && errCode != FAILURE )
{
iResult = hb_hsxNext( iHandle, &ulRec );
if( iResult != HSX_SUCCESS || ulRec == 0 )
break;
if( pVerify )
{
errCode = SELF_GOTO( pArea, ulRec );
if( errCode == FAILURE )
break;
errCode = SELF_EVALBLOCK( pArea, pVerify );
if( errCode == FAILURE )
break;
fValid = hb_hsxVerify( iHandle,
( BYTE * ) hb_itemGetCPtr( pArea->valResult ),
hb_itemGetCLen( pArea->valResult ),
pSeek, ulSeek, iVerifyType ) == HSX_SUCCESS;
}
if( fValid )
{
/* set record in WA RM filter */
hb_itemPutNInt( pItem, ulRec );
errCode = SELF_INFO( pArea, DBI_RM_ADD, pItem );
}
}
if( pArea->valResult )
{
hb_itemRelease( pArea->valResult );
pArea->valResult = NULL;
}
hb_itemRelease( pItem );
if( ulRecNo )
SELF_GOTO( pArea, ulRecNo );
if( fDestroyExpr )
hb_hsxExpDestroy( pVerify );
return errCode == FAILURE ? HSX_RDDFAILURE : iResult;
}
/* ************************************************************************ */
/* .prg level functions: HS_*() */
/* ************************************************************************ */
/* hs_Create( , , , , , )
-> nVal >=0 (OK: ), nVal < 0 (ERROR CODE)
Creates a new, empty HiPer-SEEK index file */
HB_FUNC( HS_CREATE )
{
hb_retni( hb_hsxCreate( hb_parc( 1 ), hb_parni( 2 ), hb_parni( 3 ),
hb_param( 4, HB_IT_LOGICAL ) == NULL || hb_parl( 4 ),
hb_parni( 5 ), hb_param( 6, HB_IT_ANY ) ) );
}
/* hs_Open( , , )
-> nVal >=0 (OK: ), nVal < 0 (ERROR CODE)
Opens an existing HiPer-SEEK index file */
HB_FUNC( HS_OPEN )
{
hb_retni( hb_hsxOpen( hb_parc( 1 ), hb_parni( 2 ),
hb_param( 3, HB_IT_NUMERIC ) ? hb_parni( 3 ) : HSXDEFOPENMODE ) );
}
/* hs_Close( ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
Closes a previously opened HiPer-SEEK index file */
HB_FUNC( HS_CLOSE )
{
if( hb_param( 1, HB_IT_NUMERIC ) )
hb_retni( hb_hsxDestroy( hb_parni( 1 ) ) );
else
hb_retni( HSX_BADPARMS );
}
/* hs_Index( , , , , , ,
) -> nVal >=0 (OK: ), nVal < 0 (ERROR CODE)
Creates and populates a new HiPer-SEEK index */
HB_FUNC( HS_INDEX )
{
hb_retni( hb_hsxIndex( hb_parc( 1 ), hb_param( 2, HB_IT_ANY ), hb_parni( 3 ),
hb_param( 4, HB_IT_NUMERIC ) ? hb_parni( 4 ) : HSXDEFOPENMODE,
hb_parni( 5 ),
hb_param( 6, HB_IT_LOGICAL ) == NULL || hb_parl( 6 ),
hb_parni( 7 ) ) );
}
/* hs_Add( , [], [lDel] ) -> nVal >= 1 (RECNO), nVal < 0 (ERROR CODE)
Adds a text string entry to a HiPer-SEEK index file */
HB_FUNC( HS_ADD )
{
if( hb_param( 1, HB_IT_NUMERIC ) )
{
ULONG ulRecNo;
int iRetVal;
iRetVal = hb_hsxAdd( hb_parni( 1 ), &ulRecNo,
hb_param( 2, HB_IT_BLOCK | HB_IT_STRING ),
hb_parl( 3 ) );
if( iRetVal == HSX_SUCCESS )
hb_retnint( ulRecNo );
else
hb_retni( iRetVal );
}
else
hb_retni( HSX_BADPARMS );
}
/* hs_Replace( , [], , [lDel] ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
Replaces current HiPer-SEEK index entry with a new value */
HB_FUNC( HS_REPLACE )
{
if( hb_param( 1, HB_IT_NUMERIC ) && hb_param( 3, HB_IT_NUMERIC ) )
hb_retni( hb_hsxReplace( hb_parni( 1 ), hb_parnl( 3 ),
hb_param( 2, HB_IT_BLOCK | HB_IT_STRING ),
hb_parl( 4 ) ) );
else
hb_retni( HSX_BADPARMS );
}
/* hs_IfDel( , ) -> nVal = {0|1} (DELETED), nVal < 0 (ERROR CODE)
Determines if a HiPer-SEEK record is marked as deleted */
HB_FUNC( HS_IFDEL )
{
if( hb_param( 1, HB_IT_NUMERIC ) && hb_param( 2, HB_IT_NUMERIC ) )
hb_retni( hb_hsxIfDel( hb_parni( 1 ), hb_parnl( 2 ) ) );
else
hb_retni( HSX_BADPARMS );
}
/* hs_Delete( , ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
Deletes specifed index record from HiPer-SEEK index file */
HB_FUNC( HS_DELETE )
{
if( hb_param( 1, HB_IT_NUMERIC ) && hb_param( 2, HB_IT_NUMERIC ) )
hb_retni( hb_hsxDelete( hb_parni( 1 ), hb_parnl( 2 ) ) );
else
hb_retni( HSX_BADPARMS );
}
/* hs_Undelete( , ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
Unmarks the specified HiPer-SEEK record as being deleted */
HB_FUNC( HS_UNDELETE )
{
if( hb_param( 1, HB_IT_NUMERIC ) && hb_param( 2, HB_IT_NUMERIC ) )
hb_retni( hb_hsxUnDelete( hb_parni( 1 ), hb_parnl( 2 ) ) );
else
hb_retni( HSX_BADPARMS );
}
/* hs_KeyCount( ) -> nVal >= 0 (RECCOUNT), nVal < 0 (ERROR CODE)
Returns the number of entries in a HiPer-SEEK index */
HB_FUNC( HS_KEYCOUNT )
{
if( hb_param( 1, HB_IT_NUMERIC ) )
{
LPHSXINFO pHSX = hb_hsxGetPointer( hb_parni( 1 ) );
if( pHSX )
{
if( pHSX->fShared )
hb_hsxGetRecCount( pHSX );
hb_retnint( pHSX->ulRecCount );
}
else
hb_retni( HSX_BADHANDLE );
}
else
hb_retni( HSX_BADPARMS );
}
/* hs_Set( , ) -> nVal = 1 (OK), nVal < 0 (ERROR CODE)
Sets up parameters for a subsequent hs_Next() call */
HB_FUNC( HS_SET )
{
BYTE * pStr = ( BYTE * ) hb_parc( 2 );
int iRetVal = HSX_BADPARMS;
if( pStr && hb_param( 1, HB_IT_NUMERIC ) )
iRetVal = hb_hsxSeekSet( hb_parni( 1 ), pStr, hb_parclen( 2 ) );
hb_retni( iRetVal );
}
/* hs_Filter( , , [xRealExp], [nBufSize], [nOpenMode] ) -> nRecMatch
Sets a WA RM filter using a HiPer-SEEK index */
HB_FUNC( HS_FILTER )
{
BYTE * szText = ( BYTE * ) hb_parc( 2 ), * pBuff = NULL;
ULONG ulLen = hb_parclen( 2 ), ulRecords = 0, ull, ul;
int iHandle = -1, iResult = HSX_BADPARMS;
BOOL fNew = FALSE, fToken = TRUE;
if( hb_parclen( 1 ) > 0 )
{
if( ulLen > 0 )
{
iHandle = hb_hsxOpen( hb_parc( 1 ), hb_parni( 4 ),
hb_param( 5, HB_IT_NUMERIC ) ? hb_parni( 5 ) : HSXDEFOPENMODE );
if( iHandle >= 0 )
fNew = TRUE;
else
iResult = iHandle;
}
}
else if( hb_param( 1, HB_IT_NUMERIC ) )
{
LPHSXINFO pHSX = hb_hsxGetPointer( hb_parni( 1 ) );
if( ! pHSX )
iResult = HSX_BADHANDLE;
else
{
iHandle = pHSX->iHandle;
if( !szText )
{
ulLen = pHSX->ulSearch;
if( ulLen && pHSX->pSearchVal )
{
pBuff = ( BYTE * ) hb_xgrab( ulLen + 1 );
memcpy( pBuff, pHSX->pSearchVal, ulLen );
pBuff[ ulLen ] = '\0';
szText = pBuff;
fToken = FALSE;
}
}
}
}
if( iHandle >= 0 && ulLen > 0 )
{
PHB_ITEM pItem = hb_itemNew( NULL );
AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
if( !pArea )
{
hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, "HS_FILTER" );
iResult = HSX_NOTABLE;
}
/* create empty workarea RM filter */
else if( SELF_INFO( pArea, DBI_RM_CREATE, pItem ) == FAILURE )
iResult = HSX_RDDFAILURE;
else
{
/* to be SIX compatible divide given text on space delimited tokens */
if( fToken )
{
iResult = HSX_SUCCESS;
for( ul = 0; ul < ulLen && iResult == HSX_SUCCESS; ul++ )
{
while( szText[ ul ] == ' ' && ul < ulLen )
++ul;
ull = ul;
while( szText[ ull ] != ' ' && ull < ulLen )
++ull;
iResult = hb_hsxFilter( iHandle, &szText[ ul ], ull - ul,
hb_param( 3, HB_IT_ANY ), HSX_VERIFY_PHRASE );
ul = ull;
}
}
else
{
iResult = hb_hsxFilter( iHandle, szText, ulLen,
hb_param( 3, HB_IT_ANY ),
HSX_VERIFY_PHRASE );
}
}
if( iResult == HSX_SUCCESS )
{
hb_itemPutNI( pItem, 0 );
if( SELF_INFO( pArea, DBI_RM_COUNT, pItem ) == FAILURE )
iResult = HSX_RDDFAILURE;
else
ulRecords = hb_itemGetNL( pItem );
}
hb_itemRelease( pItem );
if( fNew )
hb_hsxDestroy( iHandle );
}
if( pBuff )
hb_xfree( pBuff );
if( iResult != HSX_SUCCESS )
hb_retni( iResult );
else
hb_retnint( ulRecords );
}
/* hs_Next( ) -> nVal >= 0 (RECNO), nVal < 0 (ERROR CODE)
Searches a HiPer-SEEK index file for first/next match */
HB_FUNC( HS_NEXT )
{
ULONG ulRecNo = 0;
int iRetVal = HSX_BADPARMS;
if( hb_param( 1, HB_IT_NUMERIC ) )
iRetVal = hb_hsxNext( hb_parni( 1 ), &ulRecNo );
if( iRetVal == HSX_SUCCESS )
hb_retnint( ulRecNo );
else
hb_retni( iRetVal );
}
/* hs_Verify( , , , )
-> nVal = {0|1} (VERIFIED), nVal < 0 (ERROR CODE)
hs_Verify( , ) -> lOK
Verifies hs_Next() hit against code block expression */
HB_FUNC( HS_VERIFY )
{
if( hb_param( 1, HB_IT_NUMERIC ) )
{
int iHandle = hb_parni( 1 );
PHB_ITEM pExpr = hb_param( 2, HB_IT_BLOCK );
BYTE * szText = NULL;
ULONG ulLen = 0;
LPHSXINFO pHSX;
pHSX = hb_hsxGetPointer( iHandle );
if( !pHSX )
{
hb_retni( HSX_BADHANDLE );
return;
}
if( pExpr )
pExpr = hb_vmEvalBlockOrMacro( pExpr );
else
{
pExpr = hb_param( 2, HB_IT_STRING );
if( !pExpr && pHSX->pKeyItem )
pExpr = hb_vmEvalBlockOrMacro( pHSX->pKeyItem );
}
if( pExpr )
{
szText = ( BYTE * ) hb_itemGetCPtr( pExpr );
ulLen = hb_itemGetCLen( pExpr );
}
hb_retni( hb_hsxVerify( hb_parni( 1 ), szText, ulLen,
( BYTE * ) hb_parc( 3 ), hb_parclen( 3 ),
hb_parni( 4 ) ) );
}
else
{
PHB_ITEM pExpr = hb_param( 1, HB_IT_BLOCK );
BYTE * szSub = ( BYTE * ) hb_parc( 2 ), * szText = NULL;
ULONG ulSub = hb_parclen( 2 ), ulLen = 0;
BOOL fIgnoreCase = hb_parl( 3 );
if( ulSub )
{
pExpr = pExpr ? hb_vmEvalBlockOrMacro( pExpr ) : hb_param( 2, HB_IT_STRING );
if( pExpr )
{
szText = ( BYTE * ) hb_itemGetCPtr( pExpr );
ulLen = hb_itemGetCLen( pExpr );
}
}
hb_retl( ulLen && ulSub && hb_hsxStrCmp( szSub, ulSub, szText, ulLen,
fIgnoreCase, 3 ) );
}
}
/* hs_Version() -> */
HB_FUNC( HS_VERSION )
{
static const char szVer[] = "HiPer-SEEK / FTS library emulation";
char * pszHBVersion, * pszVersion;
pszHBVersion = hb_verHarbour();
pszVersion = hb_xstrcat( NULL, szVer, ": ", pszHBVersion );
hb_retclen_buffer( pszVersion, strlen( pszVersion ) );
hb_xfree( pszHBVersion );
}
| hsx.c | 449 |