/* b4block.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */ #include "d4all.h" #ifdef __TURBOC__ #pragma hdrstop #endif /* __TURBOC__ */ short S4FUNCTION x4reverseShort( const void *val ) { unsigned char out[2] ; const unsigned char *atVal ; atVal = (const unsigned char *)val ; #ifdef E4PARM_LOW if ( val == 0 ) { error4( 0, e4parm, E90439 ) ; return 0 ; } #endif out[0] = atVal[1] ; out[1] = atVal[0] ; return (*(short *)out ) ; } S4LONG x4reverseLong( const void *val ) { unsigned char out[4] ; unsigned const char *atVal ; atVal = (const unsigned char *)val ; #ifdef E4PARM_LOW if ( val == 0 ) { error4( 0, e4parm, E90439 ) ; return 0 ; } #endif #ifdef S4BYTEORDER_2301 out[0] = atVal[2] ; out[1] = atVal[3] ; out[2] = atVal[0] ; out[3] = atVal[1] ; #else out[0] = atVal[3] ; out[1] = atVal[2] ; out[2] = atVal[1] ; out[3] = atVal[0] ; #endif return *(S4LONG *)out ; } #ifndef S4CLIENT int b4calcBlanks( const unsigned char *keyVal, const int len, const unsigned char pChar ) { int a ; #ifdef E4PARM_LOW if ( keyVal == 0 || len < 0 ) return error4( 0, e4parm, E90438 ) ; #endif for ( a = len ; a > 0; a-- ) if ( keyVal[a-1] != pChar ) return ( len - a ) ; return len ; /* all blanks */ } #endif /* S4CLIENT */ #ifndef S4INDEX_OFF #ifndef S4CLIENT B4BLOCK *b4alloc( TAG4FILE *t4, const long fb ) { B4BLOCK *b4 ; #ifdef S4CLIPPER short offset ; int i ; #endif /* S4CLIPPER */ #ifdef E4PARM_LOW if ( t4 == 0 ) { error4( 0, e4parm, E90438 ) ; return 0 ; } #endif #ifdef S4CLIPPER b4 = (B4BLOCK *)mem4alloc2( t4->blockMemory, t4->codeBase ) ; #else b4 = (B4BLOCK *)mem4alloc2( t4->indexFile->blockMemory, t4->codeBase ) ; #endif if ( b4 == 0 ) { error4( t4->codeBase, e4memory, E90438 ) ; return 0 ; } b4->tag = t4 ; b4->fileBlock = fb ; #ifdef S4CLIPPER offset = ( b4->tag->header.keysMax + 2 + (( b4->tag->header.keysMax / 2) * 2 != b4->tag->header.keysMax ) ) * sizeof(short) ; for ( i = 0 ; i <= b4->tag->header.keysMax ; i++ ) b4->pointers[i] = (short)(( b4->tag->header.groupLen * i )) + offset ; b4->data = (B4KEY_DATA *) ((char *)&b4->nKeys + b4->pointers[0]) ; /* first entry */ #endif /* S4CLIPPER */ #ifdef S4FOX /* b4->builtKey = (B4KEY_DATA *)u4allocEr( t4->codeBase, (long)sizeof(long) + t4->header.keyLen + 1 ) ; */ b4->builtKey = (B4KEY_DATA *)mem4alloc2( t4->builtKeyMemory, t4->codeBase ) ; b4->builtOn = -1 ; #endif /* S4FOX */ return b4 ; } int b4free( B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif #ifdef S4FOX #ifdef E4ANALYZE if ( b4->changed ) return error4( b4->tag->codeBase, e4info, E90438 ) ; #endif mem4free( b4->tag->builtKeyMemory, b4->builtKey ) ; #endif /* S4FOX */ #ifdef S4CLIPPER mem4free( b4->tag->blockMemory, b4 ) ; #else mem4free( b4->tag->indexFile->blockMemory, b4 ) ; #endif return 0 ; } #ifdef S4MDX /* S4MDX */ #ifndef S4OFF_WRITE int b4flush( B4BLOCK *b4 ) { int rc ; INDEX4FILE *i4 ; TAG4FILE *t4file ; #ifdef S4BYTE_SWAP char *swap, *swapPtr ; int i ; S4LONG longVal ; short shortVal ; #endif /* S4BYTE_SWAP */ #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif if ( b4->changed ) { #ifdef E4INDEX_VERIFY if ( b4verify( b4 ) == -1 ) error4describe( b4->tag->codeBase, e4index, E90438, b4->tag->alias, 0, 0 ) ; #endif t4file = b4->tag ; i4 = t4file->indexFile ; #ifdef S4BYTE_SWAP swap = (char *)u4allocEr( t4file->codeBase, t4file->indexFile->header.blockRw ) ; if ( swap == 0 ) return error4stack( t4file->codeBase, e4memory, E90438 ) ; memcpy( (void *)swap, (void *)&b4->nKeys, t4file->indexFile->header.blockRw ) ; /* position swapPtr at beginning of B4KEY's */ swapPtr = swap ; swapPtr += 6 + sizeof(short) ; /* move through all B4KEY's to swap 'long' */ for ( i = 0 ; i < (*(short *)swap) ; i++ ) { longVal = x4reverseLong( (void *)swapPtr ) ; memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ; swapPtr += t4file->header.groupLen ; } /* mark lastPointer */ if ( !b4leaf( b4 ) ) { longVal = x4reverseLong( (void *)swapPtr ) ; memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ; } /* swap the numKeys value */ shortVal = x4reverseShort( (void *)swap ) ; memcpy( swap, (void *) &shortVal, sizeof(short) ) ; #ifndef S4OFF_OPTIMIZE i4->readBlockTag = t4file ; #endif rc = file4write( &i4->file, (long)b4->fileBlock*I4MULTIPLY, swap, i4->header.blockRw ) ; #ifndef S4OFF_OPTIMIZE i4->readBlockTag = 0 ; #endif u4free( swap ) ; #else #ifndef S4OFF_OPTIMIZE i4->readBlockTag = t4file ; #endif rc = file4write( &i4->file, (long)b4->fileBlock*I4MULTIPLY, &b4->nKeys, i4->header.blockRw ) ; #ifndef S4OFF_OPTIMIZE i4->readBlockTag = 0 ; #endif #endif /* S4BYTE_SWAP */ if ( rc < 0 ) return error4stack( t4file->codeBase, rc, E90438 ) ; b4->changed = 0 ; } return 0 ; } #endif /* S4OFF_WRITE */ /* S4MDX */ #ifndef S4INLINE void b4goEof( B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) { error4( 0, e4parm_null, E90438 ) ; return ; } #endif b4->keyOn = b4numKeys( b4 ) ; } #endif /* S4INLINE */ /* S4MDX */ #ifndef S4OFF_WRITE int b4insert( B4BLOCK *b4, const void *k, const long r ) { #ifdef S464BIT S4LONG tempR ; #endif int leftLen ; B4KEY_DATA *dataPtr, *nextPtr ; #ifdef E4PARM_LOW if ( b4 == 0 || k == 0 || r <= 0L ) return error4( b4->tag->codeBase, e4parm, E90438 ) ; #endif dataPtr = b4key( b4, b4->keyOn ) ; nextPtr = b4key( b4, b4->keyOn+1 ) ; leftLen = b4->tag->indexFile->header.blockRw - ( b4->keyOn + 1 ) * b4->tag->header.groupLen - sizeof(short) - sizeof(char[6]) ; #ifdef E4ANALYZE if ( b4->keyOn < 0 || b4->keyOn > b4numKeys( b4 ) || leftLen < 0 ) return error4( b4->tag->codeBase, e4info, E90438 ) ; #endif c4memmove( nextPtr, dataPtr, leftLen ) ; b4->nKeys++ ; memcpy( dataPtr->value, k, b4->tag->header.keyLen ) ; #ifdef S464BIT tempR = (S4LONG) r ; memcpy( (void *)&dataPtr->num, (void *)&tempR, sizeof(tempR) ) ; #else memcpy( (void *)&dataPtr->num, (void *)&r, sizeof(r) ) ; #endif b4->changed = 1 ; return 0 ; } #endif /* S4OFF_WRITE */ /* S4MDX */ /* based on the actual stored-data (from file) only, determine whether or not a leaf. Used by file optimization routines */ int b4dataLeaf( void *data, TAG4FILE *tag ) { short nKeys ; char *info ; #ifdef E4PARM_LOW if ( data == 0 || tag == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif nKeys = * ((short *)data) ; info = (char *)data + ( sizeof( short ) + 6 ) ; return ( ((B4KEY_DATA *)((char *)info + tag->header.groupLen * nKeys))->num == 0L ) ; } /* S4MDX */ #ifndef S4INLINE B4KEY_DATA *b4key( const B4BLOCK *b4, const int iKey ) { #ifdef E4PARM_LOW if ( b4 == 0 || iKey < 0 ) { error4( 0, e4parm, E90438 ) ; return 0 ; } #endif return (B4KEY_DATA *)((char *)&b4->info.num + b4->tag->header.groupLen * iKey) ; } /* S4MDX */ unsigned char *b4keyKey( B4BLOCK *b4, const int iKey ) { #ifdef E4PARM_LOW if ( b4 == 0 || iKey < 0 ) { error4( 0, e4parm, E90438 ) ; return 0 ; } #endif return (unsigned char *)(((B4KEY_DATA *)((char *)&b4->info.num + b4->tag->header.groupLen * iKey ))->value ) ; } /* S4MDX */ int b4lastpos( const B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif return ( ( b4leaf( b4 ) ) ? ( b4numKeys( b4 ) - 1 ) : ( b4numKeys( b4 ) ) ) ; } /* S4MDX */ int b4leaf( const B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif return( b4key( b4, b4numKeys( b4 ) )->num == 0L ) ; } /* S4MDX */ long b4recNo( const B4BLOCK *b4, const int i ) { #ifdef E4PARM_LOW if ( b4 == 0 || i < 0 ) return error4( 0, e4parm, E90438 ) ; #endif return b4key( b4, i )->num ; } #endif /* S4INLINE */ /* S4MDX */ #ifndef S4OFF_WRITE int b4remove( B4BLOCK *b4 ) { B4KEY_DATA *keyCur, *keyNext ; int leftLen ; #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif keyCur = b4key( b4, b4->keyOn ) ; keyNext = b4key( b4, b4->keyOn + 1 ) ; leftLen = b4->tag->indexFile->header.blockRw - sizeof( b4->nKeys ) - sizeof( b4->dummy ) - ( b4->keyOn + 1 ) * b4->tag->header.groupLen ; #ifdef E4ANALYZE if ( b4->keyOn < 0 || b4->keyOn > b4lastpos( b4 ) ) return error4( b4->tag->codeBase, e4info, E90438 ) ; #endif if ( leftLen > 0 ) c4memmove( keyCur, keyNext, leftLen ) ; b4->nKeys-- ; b4->changed = 1 ; if ( b4leaf( b4 ) ) memset( b4keyKey( b4, b4numKeys( b4 ) ), 0, b4->tag->header.keyLen ) ; #ifdef E4ANALYZE else if ( b4numKeys( b4 ) < b4->tag->header.keysMax ) memset( b4keyKey( b4, b4numKeys( b4 ) ), 0, b4->tag->header.keyLen ) ; #endif return 0 ; } #endif /* S4OFF_WRITE */ /* S4MDX */ int b4seek( B4BLOCK *b4, const char *searchValue, const int len ) { int rc, keyLower, keyUpper, saveRc, keyCur ; S4CMP_FUNCTION *cmp; #ifdef E4PARM_LOW if ( b4 == 0 || searchValue == 0 || len < 0 ) return error4( 0, e4parm, E90438 ) ; #endif /* keyCur must be between keyLower and keyUpper */ keyLower = -1 ; keyUpper = b4numKeys( b4 ) ; cmp = b4->tag->cmp ; if ( keyUpper == 0 ) { b4->keyOn = 0 ; return r4after ; } saveRc = 1 ; for( ;; ) /* Repeat until the key is found */ { keyCur = (keyUpper + keyLower) / 2 ; rc = (*cmp)( b4keyKey(b4,keyCur), searchValue, len ) ; if ( rc >= 0 ) { keyUpper = keyCur ; saveRc = rc ; } else keyLower = keyCur ; if ( keyLower >= (keyUpper-1) ) /* then there is no exact match */ { b4->keyOn = keyUpper ; if ( saveRc ) return r4after ; return 0 ; } } } /* S4MDX */ int b4skip( B4BLOCK *b4, const long n ) { int numLeft ; #ifdef E4PARM_LOW if ( b4 == 0 ) { error4( 0, e4parm_null, E90438 ) ; return 0 ; } #endif if ( n > 0 ) { numLeft = b4numKeys( b4 ) - b4->keyOn ; if ( b4leaf( b4 ) ) if ( numLeft != 0 ) numLeft -- ; } else numLeft = -b4->keyOn ; if ( ( n <= 0L ) ? ( (long)numLeft <= n ) : ( (long)numLeft >= n) ) { b4->keyOn = b4->keyOn + (int)n ; return (int)n ; } else { b4->keyOn = b4->keyOn + numLeft ; return numLeft ; } } #endif /* S4MDX */ #ifdef S4FOX /* S4FOX */ void b4leafInit( B4BLOCK *b4 ) { TAG4FILE *t4 ; int tLen ; unsigned int cLen, keyLen ; unsigned long ff, rLen ; #ifdef E4PARM_LOW if ( b4 == 0 ) { error4( 0, e4parm_null, E90438 ) ; return ; } #endif t4 = b4->tag ; keyLen = (unsigned int)t4->header.keyLen ; ff = 0xFFFFFFFFL ; for ( cLen = 0 ; keyLen ; keyLen >>= 1, cLen++ ) ; b4->nodeHdr.trailCntLen = b4->nodeHdr.dupCntLen = (unsigned char)cLen ; b4->nodeHdr.trailByteCnt = (unsigned char)((unsigned char)0xFF >> (8 - cLen % 8) ) ; b4->nodeHdr.dupByteCnt = b4->nodeHdr.trailByteCnt ; rLen = (unsigned long)dfile4recCount( b4->tag->indexFile->dataFile, -2L ) ; for ( cLen = 0 ; rLen ; rLen>>=1, cLen++ ) ; b4->nodeHdr.recNumLen = (unsigned char) (cLen + (( 8 - ( 2 * (unsigned int)b4->nodeHdr.trailCntLen % 8 )) % 8)) ; if ( b4->nodeHdr.recNumLen < 12 ) b4->nodeHdr.recNumLen = 12 ; for( tLen = b4->nodeHdr.recNumLen + b4->nodeHdr.trailCntLen + b4->nodeHdr.dupCntLen ; (tLen / 8)*8 != tLen ; tLen++, b4->nodeHdr.recNumLen++ ) ; /* make at an 8-bit offset */ rLen = ff >> ( sizeof(long)*8 - b4->nodeHdr.recNumLen ) ; memcpy( (void *)&b4->nodeHdr.recNumMask[0], (void *)&rLen, sizeof(long) ) ; b4->nodeHdr.infoLen = (unsigned char)((unsigned int)(b4->nodeHdr.recNumLen + b4->nodeHdr.trailCntLen + b4->nodeHdr.dupCntLen) / 8) ; b4->nodeHdr.freeSpace = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - sizeof( B4NODE_HEADER ) ; } /* S4FOX */ int b4calcDups( const unsigned char *ptr1, const unsigned char *ptr2, const int len ) { int a ; #ifdef E4PARM_LOW if ( ptr1 == 0 || ptr2 == 0 || len < 0 ) return error4( 0, e4parm, E90438 ) ; #endif for ( a = 0 ; a < len; a++ ) if ( ptr1[a] != ptr2[a] ) return a ; return len ; /* all duplicates */ } /* S4FOX */ long x4recNo( const B4BLOCK *b4, const int numInBlock ) { #ifdef S4DATA_ALIGN unsigned long longPtr ; unsigned long longVal ; #else unsigned long * lPtr ; #ifdef S4DO_BYTEORDER unsigned long longTemp ; #endif #endif #ifdef E4PARM_LOW if ( b4 == 0 || numInBlock < 0 ) return error4( 0, e4parm, E90439 ) ; #endif #ifdef S4DATA_ALIGN memcpy( (void *)&longPtr , b4->data + numInBlock * b4->nodeHdr.infoLen , sizeof(long) ) ; #ifdef S4DO_BYTEORDER longPtr = (unsigned long)x4reverseLong( (void *)&longPtr ) ; #endif memcpy( (void *)&longVal , (void *)&b4->nodeHdr.recNumMask[0], sizeof(unsigned long) ) ; return ( longPtr & longVal ) ; #else #ifdef S4DO_BYTEORDER longTemp = *(unsigned long *)( b4->data + numInBlock * b4->nodeHdr.infoLen ) ; longTemp = (unsigned long)x4reverseLong( (void *)&longTemp ) ; return ( longTemp & *(unsigned long *)&b4->nodeHdr.recNumMask[0] ) ; #else lPtr = (unsigned long *)( b4->data + numInBlock * b4->nodeHdr.infoLen ) ; return ( *lPtr & *(unsigned long *)&b4->nodeHdr.recNumMask[0] ) ; #endif #endif } /* S4FOX */ int x4dupCnt( const B4BLOCK *b4, const int numInBlock ) { int pos ; #ifdef S4DATA_ALIGN unsigned long longPtr ; #else unsigned long *lPtr ; #ifdef S4DO_BYTEORDER unsigned long longVal ; #endif #endif #ifdef E4PARM_LOW if ( b4 == 0 || numInBlock < 0 ) return error4( 0, e4parm, E90439 ) ; #endif if ( b4->nodeHdr.infoLen > 4 ) /* > size of long, so must do careful shifting and copying */ { #ifdef E4ANALYZE if ( b4->nodeHdr.recNumLen <= 16 ) return error4( b4->tag->codeBase, e4info, E80401 ) ; #endif #ifdef S4DATA_ALIGN memcpy( (void *)&longPtr , b4->data + numInBlock * b4->nodeHdr.infoLen + 2, sizeof(long) ) ; #else lPtr = (unsigned long *)( b4->data + numInBlock * b4->nodeHdr.infoLen + 2 ) ; #endif pos = b4->nodeHdr.recNumLen - 16 ; } else { #ifdef S4DATA_ALIGN memcpy( (void *)&longPtr , b4->data + numInBlock * b4->nodeHdr.infoLen , sizeof(long) ) ; #else lPtr = (unsigned long *)( b4->data + numInBlock * b4->nodeHdr.infoLen ) ; #endif pos = b4->nodeHdr.recNumLen ; } #ifdef S4DATA_ALIGN #ifdef S4DO_BYTEORDER longPtr = x4reverseLong( (void *)&longPtr ) ; #endif return (int)( ( longPtr >> pos ) & b4->nodeHdr.dupByteCnt ) ; #else #ifdef S4DO_BYTEORDER longVal = *lPtr ; longVal = x4reverseLong( (void *)&longVal) ; return (int)( ( longVal >> pos ) & b4->nodeHdr.dupByteCnt ) ; #else return (int)( ( *lPtr >> pos ) & b4->nodeHdr.dupByteCnt ) ; #endif #endif } /* S4FOX */ int x4trailCnt( const B4BLOCK *b4, const int numInBlock ) { int pos ; #ifdef S4DATA_ALIGN unsigned long longPtr ; #else unsigned long *lPtr ; #ifdef S4DO_BYTEORDER unsigned long longVal ; #endif #endif #ifdef E4PARM_LOW if ( b4 == 0 || numInBlock < 0 ) return error4( 0, e4parm, E90439 ) ; #endif if ( b4->nodeHdr.infoLen > 4 ) /* > size of long, so must do careful shifting and copying */ { #ifdef E4ANALYZE if ( b4->nodeHdr.recNumLen <= 16 ) return error4( b4->tag->codeBase, e4info, E90438 ) ; #endif #ifdef S4DATA_ALIGN memcpy( (void *)&longPtr , b4->data + numInBlock * b4->nodeHdr.infoLen + 2, sizeof(long) ) ; #else lPtr = (unsigned long *)( b4->data + numInBlock * b4->nodeHdr.infoLen + 2 ) ; #endif pos = b4->nodeHdr.recNumLen - 16 + b4->nodeHdr.dupCntLen ; } else { #ifdef S4DATA_ALIGN memcpy( (void *)&longPtr , b4->data + numInBlock * b4->nodeHdr.infoLen , sizeof(long) ) ; #else lPtr = (unsigned long *)( b4->data + numInBlock * b4->nodeHdr.infoLen ) ; #endif pos = b4->nodeHdr.recNumLen + b4->nodeHdr.dupCntLen; } #ifdef S4DATA_ALIGN #ifdef S4DO_BYTEORDER longPtr = x4reverseLong( (void *)&longPtr ) ; #endif return (int)( ( longPtr >> pos ) & b4->nodeHdr.trailByteCnt ) ; #else #ifdef S4DO_BYTEORDER longVal = *lPtr ; longVal = x4reverseLong( (void *)&longVal) ; return (int)( ( longVal >> pos ) & b4->nodeHdr.trailByteCnt ) ; #endif return (int)( ( *lPtr >> pos ) & b4->nodeHdr.trailByteCnt ) ; #endif } /* S4FOX */ #ifndef S4OFF_WRITE int x4putInfo( const B4NODE_HEADER *b4nodeHdr, void *buffer, const long rec, const int trail, const int dupCnt ) { int pos ; #ifdef S4DO_BYTEORDER #ifndef S4DATA_ALIGN long longTemp ; #endif #endif #ifdef S4DATA_ALIGN char unixBuf[6] ; char unixBuf2[4] ; long longVal, longTemp ; int doShift = 0 ; #else unsigned char *buf ; unsigned long *lPtr ; #endif #ifdef E4PARM_LOW if ( b4nodeHdr == 0 || buffer == 0 || rec < 0 || trail < 0 || dupCnt < 0 ) return error4( 0, e4parm, E90439 ) ; #endif #ifdef S4DATA_ALIGN memset( unixBuf, 0, 6 ) ; memcpy( (void *)&longTemp , (void *)&b4nodeHdr->recNumMask[0], sizeof(long) ) ; longVal = rec & longTemp ; #ifdef S4DO_BYTEORDER longVal = x4reverseLong( (void *)&longVal ) ; #endif memcpy( unixBuf, (void *)&longVal, sizeof(long) ) ; #else buf = (unsigned char *) buffer ; lPtr = (unsigned long *)buf ; memset( buf, 0, 6 ) ; *lPtr = rec & *(long *)&b4nodeHdr->recNumMask[0] ; #ifdef S4DO_BYTEORDER *lPtr = x4reverseLong( (void *)lPtr ) ; #endif #endif if ( b4nodeHdr->infoLen > 4 ) /* > size of long, so must do careful shifting and copying */ { #ifdef E4ANALYZE if ( b4nodeHdr->recNumLen <= 16 ) return error4( 0, e4info, E80401 ) ; #endif #ifndef S4DATA_ALIGN lPtr = (unsigned long *)( buf + 2 ) ; /* start at new pos */ #else doShift = 1 ; #endif pos = b4nodeHdr->recNumLen - 16 ; } else pos = b4nodeHdr->recNumLen ; #ifdef S4DATA_ALIGN longVal = ((unsigned long)dupCnt) << pos ; pos += b4nodeHdr->dupCntLen ; longVal |= ((unsigned long)trail) << pos ; #ifdef S4DO_BYTEORDER longVal = x4reverseLong( (void *)&longVal ) ; #endif memcpy( unixBuf2, (void *)&longVal, sizeof(long) ) ; if (doShift) { unixBuf[2] |= unixBuf2[0] ; /* must OR bytes 2 and 3 of 'buf' */ unixBuf[3] |= unixBuf2[1] ; unixBuf[4] = unixBuf2[2] ; unixBuf[5] = unixBuf2[3] ; } else { unixBuf[0] |= unixBuf2[0] ; unixBuf[1] |= unixBuf2[1] ; unixBuf[2] |= unixBuf2[2] ; unixBuf[3] |= unixBuf2[3] ; } memcpy( (void *)buffer, unixBuf, 6 ) ; #else #ifdef S4DO_BYTEORDER longTemp = ((unsigned long)dupCnt) << pos ; pos += b4nodeHdr->dupCntLen ; longTemp |= ((unsigned long)trail) << pos ; longTemp = x4reverseLong( (void *)&longTemp ) ; *lPtr |= longTemp ; #else *lPtr |= ((unsigned long)dupCnt) << pos ; pos += b4nodeHdr->dupCntLen ; *lPtr |= ((unsigned long)trail) << pos ; #endif #endif return 0 ; } /* S4FOX */ int b4insertLeaf( B4BLOCK *b4, const void *vkeyData, const long rec ) { int leftBlanks, rightBlanks, leftDups, rightDups, leftLen, rightLen, reqdLen, movLen, oldRec, rc, oldRightDups, extraDups, saveDups ; unsigned char buffer[6], iLen ; unsigned char *keyData ; char *infoPos, a, b ; int keyLen ; unsigned int recLen ; unsigned long mask ; #ifdef E4PARM_LOW if ( b4 == 0 || vkeyData == 0 || rec < 0L ) return error4( 0, e4parm, E90438 ) ; #endif iLen = b4->nodeHdr.infoLen ; keyData = (unsigned char *)vkeyData ; keyLen = b4->tag->header.keyLen ; b4->builtOn = -1 ; /* if the record is > than the mask, must reset the block with new parameters: */ b = sizeof( long ) * 8 ; mask = 0x01L << (b-1) ; /* set leftmost bit */ for( recLen = 0, a = 0 ; a < b ; a++ ) { if ( rec & mask ) { recLen = (unsigned int)((int)b - a) ; break ; } mask >>= 1 ; } while ( recLen > b4->nodeHdr.recNumLen ) { oldRec = b4->keyOn ; saveDups = b4->curDupCnt ; rc = b4reindex( b4 ) ; if (rc ) return rc ; iLen = b4->nodeHdr.infoLen ; b4top( b4 ) ; b4skip( b4, (long)oldRec ) ; b4->curDupCnt = saveDups ; } if ( b4->tag->indexFile->dataFile->version != 0x30 && b4->tag->codeBase->compatibility == 26 ) { /* FoxPro 2.6 always has no blanks if filters exist (at least for character tags */ if ( b4->tag->filter != 0 ) leftBlanks = 0 ; else leftBlanks = b4calcBlanks( keyData, keyLen, b4->tag->pChar ) ; } else leftBlanks = b4calcBlanks( keyData, keyLen, b4->tag->pChar ) ; if ( b4numKeys( b4 ) == 0 ) { if( b4->nodeHdr.freeSpace == 0 ) /* block needs initialization */ { b4leafInit( b4 ) ; iLen = b4->nodeHdr.infoLen ; } leftDups = 0 ; reqdLen = keyLen - leftBlanks ; b4->keyOn = 0 ; b4->curPos = ((char *)&b4->header) + B4BLOCK_SIZE - reqdLen ; memcpy( b4->curPos, keyData, (unsigned int)reqdLen ) ; /* key */ x4putInfo( &b4->nodeHdr, buffer, rec, leftBlanks, 0 ) ; memcpy( b4->data, (void *)buffer, iLen ) ; } else { if ( b4->keyOn == b4numKeys( b4 ) ) /* at end */ { leftDups = b4->curDupCnt ; reqdLen = keyLen - leftBlanks - b4->curDupCnt ; if ( (int)b4->nodeHdr.freeSpace < ( reqdLen + (int)iLen ) ) /* no room to add */ return 1 ; b4->curPos -= reqdLen ; memcpy( b4->curPos, keyData + b4->curDupCnt, (unsigned int)reqdLen ) ; /* key */ x4putInfo( &b4->nodeHdr, buffer, rec, leftBlanks, leftDups ) ; memcpy( b4->data + b4->keyOn * iLen , (void *)buffer, iLen ) ; } else { rightBlanks = x4trailCnt( b4, b4->keyOn ) ; if ( b4->keyOn == 0 ) /* insert at top */ { oldRightDups = 0 ; rightDups = b4calcDups( keyData, (unsigned char *)b4->curPos, keyLen - ( rightBlanks > leftBlanks ? rightBlanks : leftBlanks ) ) ; extraDups = rightDups ; leftDups = 0 ; } else /* insert in middle of block */ { oldRightDups = x4dupCnt( b4, b4->keyOn) ; extraDups = b4calcDups( keyData + oldRightDups, (unsigned char *)b4->curPos, keyLen - ( rightBlanks > leftBlanks ? rightBlanks : leftBlanks ) - oldRightDups ) ; rightDups = oldRightDups + extraDups ; leftDups = b4->curDupCnt ; } #ifdef E4ANALYZE_ALL if ( b4->tag->header.typeCode & 0x01 ) if ( leftDups == b4->tag->header.keyLen || rightDups == b4->tag->header.keyLen ) return error4( b4->tag->codeBase, e4info, E80402 ) ; #endif rightLen = keyLen - rightBlanks - rightDups ; leftLen = keyLen - leftDups - leftBlanks ; reqdLen = leftLen - extraDups ; #ifdef E4ANALYZE if ( reqdLen < 0 ) return error4( b4->tag->codeBase, e4info, E80401 ) ; #endif if ( (int)b4->nodeHdr.freeSpace < (reqdLen + (int)iLen) ) /* no room to add */ return 1 ; if ( reqdLen != 0 ) /* shift data over */ { movLen = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - iLen * b4numKeys( b4 ) - sizeof( B4NODE_HEADER ) - b4->nodeHdr.freeSpace - ( ( (char *)&b4->header ) + B4BLOCK_SIZE - b4->curPos ) ; #ifdef E4ANALYZE if ( movLen < 0 ) return error4( b4->tag->codeBase, e4info, E80401 ) ; #endif /* move and put keys */ c4memmove( b4->curPos - movLen - reqdLen, b4->curPos - movLen, (unsigned int)movLen ) ; } b4->curPos += ( keyLen - rightBlanks - oldRightDups ) ; memcpy( b4->curPos - leftLen - rightLen, b4->curPos - ( keyLen - rightDups - rightBlanks ), (unsigned int)rightLen ) ; b4->curPos -= leftLen ; memcpy( b4->curPos, keyData + leftDups, (unsigned int)leftLen ) ; /* move and put info */ infoPos = b4->data + ( b4->keyOn ) * iLen ; c4memmove( infoPos + iLen, infoPos, (unsigned int)(iLen * ( b4numKeys( b4 ) - b4->keyOn ) ) ) ; x4putInfo( &b4->nodeHdr, buffer, rec, leftBlanks, leftDups ) ; memcpy( infoPos, (void *)buffer, iLen ) ; x4putInfo( &b4->nodeHdr, buffer, x4recNo( b4, b4->keyOn + 1 ), rightBlanks, rightDups ) ; memcpy( infoPos + iLen, (void *)buffer, iLen ) ; } } b4->changed = 1 ; b4->header.nKeys++ ; b4->nodeHdr.freeSpace -= (short) (reqdLen + (int)iLen ) ; b4->curDupCnt = leftDups ; b4->curTrailCnt = leftBlanks ; return 0 ; } /* S4FOX */ /* returns 1 if unable to move keys around to make room */ static int b4insertBranchBalance( B4BLOCK *b4 ) { B4BLOCK *left, *right, *parent ; char *oPos, *nPos ; int gLen = b4->tag->header.keyLen + 2 * sizeof( long ) ; int rc ; if ( b4numKeys( b4 ) != 2 ) /* only perform in tight situations */ return 1; parent = (B4BLOCK *)l4prev( &b4->tag->blocks, b4 ) ; if ( parent == 0 ) /* no parent, so working on a root block, allow split */ return 1 ; if ( b4->keyOn == 0L ) /* try adding to right neighbor */ { if ( parent->keyOn == b4numKeys( parent ) - 1 ) /* parent doesn't share blocks */ return 1 ; if ( b4->header.rightNode == 0 ) /* no neighbor */ return 1 ; right = b4alloc( b4->tag, b4->header.rightNode ) ; if ( right == 0 ) return 1 ; rc = i4readBlock( &b4->tag->indexFile->file, b4->header.rightNode, 0, right ) ; if ( rc < 0 ) { b4free( right ) ; return 1 ; } if ( b4numKeys( right ) >= 2 ) /* already full */ { b4free( right ) ; return 1 ; } nPos = ((char *)&right->nodeHdr) + gLen * b4numKeys( right ) ; oPos = ((char *)&right->nodeHdr) ; memcpy( nPos, oPos, gLen * b4numKeys( right ) ) ; nPos = ((char *)&right->nodeHdr) ; oPos = ((char *)&b4->nodeHdr) + gLen * ( b4numKeys( b4 ) - 1 ) ; memcpy( nPos, oPos, gLen ) ; b4->header.nKeys-- ; right->header.nKeys++ ; nPos = ((char *)&parent->nodeHdr) + gLen * ( parent->keyOn ) ; oPos = ((char *)&b4->nodeHdr ) + gLen * ( b4numKeys( b4 ) - 1 ) ; memcpy( nPos, oPos, b4->tag->header.keyLen + sizeof( long ) ) ; parent->changed = 1 ; right->changed = 1 ; b4flush( right ) ; b4free( right ) ; } else /* try adding to left neighbor */ { if ( parent->keyOn == 0 ) /* parent doesn't share blocks */ return 1 ; if ( b4->header.leftNode == 0 ) /* no neighbor */ return 1 ; left = b4alloc( b4->tag, b4->header.leftNode ) ; if ( left == 0 ) return 1 ; rc = i4readBlock( &b4->tag->indexFile->file, b4->header.leftNode, 0, left ) ; if ( rc < 0 ) { b4free( left ) ; return 1 ; } if ( b4numKeys( left ) >= 2 ) /* already full */ { b4free( left ) ; return 1 ; } nPos = ((char *)&left->nodeHdr) + gLen * b4numKeys( left ) ; oPos = ((char *)&b4->nodeHdr) ; memcpy( nPos, oPos, gLen ) ; b4->header.nKeys-- ; nPos = ((char *)&b4->nodeHdr) ; oPos = ((char *)&b4->nodeHdr) + gLen * b4numKeys( b4 ) ; memcpy( nPos, oPos, gLen * b4numKeys( b4 ) ) ; b4->keyOn-- ; left->header.nKeys++ ; nPos = ((char *)&parent->nodeHdr) + gLen * ( parent->keyOn - 1 ) ; oPos = ((char *)&left->nodeHdr ) + gLen * ( b4numKeys( left ) - 1 ) ; memcpy( nPos, oPos, b4->tag->header.keyLen + sizeof( long ) ) ; parent->changed = 1 ; left->changed = 1 ; b4flush( left ) ; b4free( left ) ; } return 0 ; } /* S4FOX */ int b4insertBranch( B4BLOCK *b4, const void *k, const long r1, const long rin2, const char newFlag ) { int leftLen, moveLen, gLen ; char *dataPtr, *nextPtr ; long r, r2 ; gLen = b4->tag->header.keyLen + 2 * sizeof(long) ; #ifdef E4PARM_LOW if ( b4 == 0 || k == 0 || r1 <= 0L || rin2 < 0 ) return error4( b4->tag->codeBase, e4parm, E90438 ) ; #endif leftLen = B4BLOCK_SIZE - sizeof( b4->header ) - gLen * b4numKeys( b4 ) ; if ( leftLen < gLen ) /* not enough room */ { /* if only 2 keys in branch, try to do some swapping with neighbor */ if ( b4insertBranchBalance( b4 ) == 1 ) return 1 ; } dataPtr = ((char *)&b4->nodeHdr) + b4->keyOn * gLen ; nextPtr = dataPtr + gLen ; #ifdef E4ANALYZE if ( b4->keyOn < 0 || b4->keyOn > b4numKeys( b4 ) ) return error4( 0, e4info, E90438 ) ; #endif moveLen = gLen * ( b4numKeys( b4 ) - b4->keyOn ) ; c4memmove( nextPtr, dataPtr, (unsigned int)moveLen ) ; b4->header.nKeys++ ; memcpy( dataPtr, k, (unsigned int)b4->tag->header.keyLen ) ; memset( dataPtr + gLen - 2*sizeof(long), 0, sizeof(long) ) ; r2 = x4reverseLong( (void *)&rin2 ) ; memcpy( dataPtr + gLen - 2*sizeof(long), (void *)&r2, sizeof(long) ) ; r = x4reverseLong( (void *)&r1 ) ; if ( !newFlag && (b4->keyOn + 1) != b4numKeys( b4 ) ) memcpy( nextPtr + gLen - sizeof(long), (void *)&r, sizeof(long) ) ; else memcpy( dataPtr + gLen - sizeof(long), (void *)&r, sizeof(long) ) ; b4->changed = 1 ; return 0 ; } /* S4FOX */ #ifndef S4INLINE int b4insert( B4BLOCK *b4, const void *keyData, const long rec, const long rec2, const char newFlag ) { #ifdef E4PARM_LOW if ( b4 == 0 || keyData == 0 || rec <= 0L || rec2 < 0 ) return error4( 0, e4parm, E90438 ) ; #endif return ( b4leaf( b4 ) ? b4insertLeaf( b4, keyData, rec ) : b4insertBranch( b4, keyData, rec, rec2, newFlag ) ) ; } #endif /* S4FOX */ int b4reindex( B4BLOCK *b4 ) { int i, dupCnt, trail ; int niLen = b4->nodeHdr.infoLen + 1 ; unsigned char buffer[6] ; long rec ; int spaceReqd ; #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif spaceReqd = b4numKeys( b4 ) ; /* 1 byte extra for each record */ if ( spaceReqd > b4->nodeHdr.freeSpace ) /* not enough room */ return 1 ; for ( i = b4numKeys( b4 ) - 1 ; i >= 0 ; i-- ) { dupCnt = x4dupCnt( b4, i ) ; trail = x4trailCnt( b4, i ) ; rec = x4recNo( b4, i ) ; memset( b4->data + i * niLen, 0, (unsigned int)niLen ) ; b4->nodeHdr.recNumLen += 8 ; /* for the new info */ b4->nodeHdr.infoLen++ ; x4putInfo( &b4->nodeHdr, buffer, rec, trail, dupCnt ) ; b4->nodeHdr.recNumLen -= 8 ; /* to get the old info */ b4->nodeHdr.infoLen-- ; memcpy( b4->data + i * niLen, (void *)buffer, (unsigned int)niLen ) ; } memcpy( (void *)&rec, (void *)&b4->nodeHdr.recNumMask[0], sizeof(long) ) ; rec |= (0x000000FFL << b4->nodeHdr.recNumLen ) ; memcpy( (void *)&b4->nodeHdr.recNumMask[0], (void *)&rec, sizeof(long) ) ; b4->nodeHdr.infoLen++ ; b4->nodeHdr.recNumLen += 8 ; b4->nodeHdr.freeSpace -= b4numKeys( b4 ) ; return 0 ; } /* S4FOX */ int b4flush( B4BLOCK *b4 ) { int rc ; INDEX4FILE *i4 ; TAG4FILE *t4file ; #ifdef S4BYTE_SWAP char swap[B4BLOCK_SIZE] ; char *swapPtr ; int i ; S4LONG longVal ; short shortVal ; #endif #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif if ( b4->changed ) { t4file = b4->tag ; i4 = t4file->indexFile ; #ifdef S4BYTE_SWAP memcpy( (void *)swap, (void *)&b4->header.nodeAttribute, B4BLOCK_SIZE ) ; /* position at either B4NODE_HEADER (leaf) or data (branch) */ swapPtr = swap + 2 * sizeof( short) + 2 * sizeof(S4LONG) ; /* if block is a leaf */ if (b4->header.nodeAttribute >= 2 ) { /* swap B4NODE_HEADER members */ shortVal = x4reverseShort( (void *)swapPtr ) ; /* freeSpace */ memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ; swapPtr += sizeof(short) ; longVal = x4reverseLong( (void *)swapPtr ) ; /* recNumMask */ memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ; } else /* if block is a branch */ { shortVal = t4file->header.keyLen + sizeof(S4LONG) ; /* position swapPtr to end of first key expression */ swapPtr += t4file->header.keyLen ; /* move through all B4KEY's to swap 'long's */ for ( i = 0 ; i < (int)b4numKeys( b4 ) ; i++ ) { longVal = x4reverseLong( (void *)swapPtr ) ; memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ; swapPtr += sizeof(S4LONG) ; longVal = x4reverseLong( (void *)swapPtr ) ; memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ; swapPtr += shortVal ; } } /* reposition to B4STD_HEADER and swap members */ swapPtr = swap ; shortVal = x4reverseShort( (void *)swapPtr ) ; /* nodeAttribute */ memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ; swapPtr += sizeof(short) ; shortVal = x4reverseShort( (void *)swapPtr ) ; /* nKeys */ memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ; swapPtr += sizeof(short) ; longVal = x4reverseLong( (void *)swapPtr ) ; /* leftNode */ memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ; swapPtr += sizeof(S4LONG) ; longVal = x4reverseLong( (void *)swapPtr ) ; /* rightNode */ memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ; swapPtr += sizeof(S4LONG) ; #ifndef S4OFF_OPTIMIZE i4->readBlockTag = t4file ; #endif rc = file4write( &i4->file, (long)b4->fileBlock * I4MULTIPLY, swap, B4BLOCK_SIZE ) ; #ifndef S4OFF_OPTIMIZE i4->readBlockTag = 0 ; #endif #else #ifndef S4OFF_OPTIMIZE i4->readBlockTag = t4file ; #endif rc = file4write( &i4->file, (long)b4->fileBlock * I4MULTIPLY, &b4->header.nodeAttribute, B4BLOCK_SIZE ) ; #ifndef S4OFF_OPTIMIZE i4->readBlockTag = 0 ; #endif #endif if ( rc < 0 ) return rc ; b4->changed = 0 ; } return 0 ; } #endif /* S4OFF_WRITE */ #ifndef S4INLINE /* S4FOX */ int b4go( B4BLOCK *b4, const int iKey ) { #ifdef E4PARM_LOW if ( b4 == 0 || iKey < 0 ) return error4( 0, e4parm, E90438 ) ; #endif return b4skip( b4, iKey - b4->keyOn ) ; } #endif /* S4INLINE */ /* S4FOX */ int b4top( B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif b4->keyOn = 0 ; if ( b4leaf( b4 ) ) { b4->curDupCnt = 0 ; b4->curPos = ((char *)&b4->header) + B4BLOCK_SIZE - b4->tag->header.keyLen + x4trailCnt( b4, 0 ) ; } return 0 ; } /* S4FOX */ void b4goEof( B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) { error4( 0, e4parm_null, E90438 ) ; return ; } #endif b4->keyOn = b4numKeys( b4 ) ; b4->curPos = ((char *)&b4->header) + sizeof( B4STD_HEADER ) + sizeof( B4NODE_HEADER ) + b4numKeys( b4 ) * b4->nodeHdr.infoLen + b4->nodeHdr.freeSpace ; } /* S4FOX */ B4KEY_DATA *b4key( B4BLOCK *b4, const int iKey ) { int len, kLen ; char *val ; #ifdef E4PARM_LOW if ( b4 == 0 || iKey > b4numKeys( b4 ) || iKey < 0 ) { error4( 0, e4parm, E90438 ) ; return 0 ; } #endif if ( iKey == b4->builtOn ) /* already there! */ return b4->builtKey ; val = (char *)(&b4->builtKey->value[0]) ; kLen = b4->tag->header.keyLen ; if ( b4->header.nodeAttribute >= 2 ) /* leaf */ { if ( b4->builtOn > iKey || b4->builtOn == -1 ) { b4->builtOn = -1 ; b4->builtPos = ((char *)&b4->header) + B4BLOCK_SIZE ; } for ( ; b4->builtOn != iKey ; ) { b4->builtOn++ ; b4->curDupCnt = x4dupCnt( b4, b4->builtOn ) ; b4->curTrailCnt = x4trailCnt( b4, b4->builtOn ) ; len = kLen - b4->curDupCnt - b4->curTrailCnt ; #ifdef E4ANALYZE if (len < 0 || len > kLen || ( b4->builtPos - len ) < b4->data ) { error4( b4->tag->codeBase, e4info, E80401 ) ; return 0 ; } #endif b4->builtPos -= len ; memcpy( val + b4->curDupCnt, b4->builtPos, (unsigned int)len ) ; memset( val + kLen - b4->curTrailCnt, b4->tag->pChar, (unsigned int)b4->curTrailCnt ) ; } b4->builtKey->num = x4recNo( b4, iKey ) ; } else /* branch */ { memcpy( val, (((char *)&b4->nodeHdr) + iKey*(2*sizeof( long ) + kLen ) ), (unsigned int)kLen ) ; b4->builtKey->num = x4reverseLong( (void *)( ((unsigned char *)&b4->nodeHdr) + (iKey+1)*(2*sizeof(long) + kLen) - sizeof(long) ) ) ; } return b4->builtKey ; } /* S4FOX */ /* based on the actual stored-data (from file) only, determine whether or not a leaf. Used by file optimization routines */ #ifdef P4ARGS_USED #pragma argsused #endif int b4dataLeaf( void *data, TAG4FILE *tag ) { B4STD_HEADER *header ; #ifdef E4PARM_LOW if ( data == 0 || tag == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif header = (B4STD_HEADER *)data ; return( header->nodeAttribute >= 2 ) ; } #ifndef S4INLINE /* S4FOX */ unsigned char *b4keyKey( B4BLOCK *b4, const int iKey ) { #ifdef E4PARM_LOW if ( b4 == 0 ) { error4( 0, e4parm_null, E90438 ) ; return 0 ; } #endif return (unsigned char *)b4key( b4, iKey )->value ; } /* S4FOX */ int b4lastpos( const B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif return b4numKeys( b4 ) - 1 ; } /* S4FOX */ int b4leaf( const B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif return( b4->header.nodeAttribute >= 2 ) ; } #endif /* S4INLINE */ /* S4FOX */ long b4recNo( const B4BLOCK *b4, const int i ) { #ifdef E4PARM_LOW if ( b4 == 0 || i < 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif if ( b4->header.nodeAttribute >= 2 ) /* leaf */ return x4recNo( b4, i ) ; else /* branch */ return (unsigned long)x4reverseLong( (void *)(((unsigned char *)&b4->nodeHdr) + i * (2*sizeof(long) + b4->tag->header.keyLen) + b4->tag->header.keyLen ) ) ; } /* S4FOX */ #ifndef S4OFF_WRITE int b4brReplace( B4BLOCK *b4, const unsigned char *str, const long r ) { int keyLen ; char *putPl ; long rec ; #ifdef E4PARM_LOW if ( b4 == 0 || str == 0 || r < 0 ) return error4( 0, e4parm, E90438 ) ; #endif keyLen = b4->tag->header.keyLen ; putPl = ( (char *)&b4->nodeHdr ) + b4->keyOn * ( 2 * sizeof( long ) + keyLen ) ; memcpy( putPl, str, (unsigned int)keyLen ) ; memcpy( b4->builtKey->value, str, (unsigned int)keyLen ) ; memset( putPl + keyLen, 0, sizeof(long) ) ; rec = x4reverseLong( (void *)&r ) ; memcpy( putPl + keyLen, (void *)&rec, sizeof(long) ) ; b4->changed = 1 ; return 0 ; } #endif /* S4OFF_WRITE */ /* S4FOX */ int b4rBrseek( B4BLOCK *b4, const char *searchValue, const int len, const long recNo ) { int rc, keyLen ; #ifdef S4DO_BYTEORDER long longVal, lrecNo ; #endif #ifdef E4ANALYZE_ALL long swapped ; #endif #ifdef E4PARM_LOW if ( b4 == 0 || searchValue == 0 || len < 0 ) return error4( 0, e4parm, E90438 ) ; #endif #ifdef E4ANALYZE_ALL /* incoming rec is swapped, so unswap it to see if it is valid */ swapped = recNo ; swapped = x4reverseShort( &swapped ) ; if ( swapped < 0 ) return error4( 0, e4parm, E90438 ) ; #endif rc = b4seek( b4, searchValue, len ) ; keyLen = b4->tag->header.keyLen ; if ( rc == 0 ) /* string matches, so search on recNo */ for(;;) { #ifdef S4DO_BYTEORDER lrecNo = x4reverseLong( (void *)&recNo ) ; longVal = x4reverseLong( (void *)(((char *)&b4->nodeHdr) + b4->keyOn * ( 2 * sizeof(long) + keyLen) + keyLen ) ) ; if ( c4memcmp( (void *)&lrecNo, (void *)&longVal, sizeof(long) ) <= 0 #else if ( c4memcmp( (void *)&recNo, ((char *)&b4->nodeHdr) + b4->keyOn * ( 2 * sizeof(long) + keyLen) + keyLen, sizeof(long) ) <= 0 #endif || b4->keyOn >= ( b4numKeys( b4 ) - 1 ) ) /* best match, so done */ break ; else if( b4->keyOn < b4numKeys( b4 ) ) b4skip( b4, 1L ) ; if ( u4memcmp( (void *)b4keyKey(b4,b4->keyOn), searchValue, (unsigned int)len ) ) /* the key has changed, so stop here */ break ; } return rc ; } /* S4FOX */ int b4seek( B4BLOCK *b4, const char *searchValue, const int len ) { int rc, keyLower, keyUpper, saveRc, keyCur, groupVal ; #ifdef E4PARM_LOW if ( b4 == 0 || searchValue == 0 || len < 0 ) return error4( 0, e4parm, E90438 ) ; #endif if ( b4numKeys( b4 ) == 0 ) { b4->keyOn = 0 ; return r4after ; } if ( b4leaf( b4 ) ) return b4leafSeek( b4, searchValue, len ) ; /* keyCur must be between keyLower and keyUpper */ keyLower = -1 ; keyUpper = b4numKeys( b4 ) - 1 ; saveRc = 1 ; groupVal = 2 * sizeof( long ) + b4->tag->header.keyLen ; for(;;) /* Repeat until the key is found */ { keyCur = (keyUpper + keyLower) / 2 ; rc = u4memcmp( (((char *)&b4->nodeHdr) + keyCur * groupVal ), searchValue, (unsigned int)len ) ; if ( rc >= 0 ) { keyUpper = keyCur ; saveRc = rc ; } else keyLower = keyCur ; if ( keyLower >= (keyUpper-1) ) /* then there is no exact match */ { b4->keyOn = keyUpper ; /* branch block, just change keyOn */ if ( saveRc ) return r4after ; return 0 ; } } } #ifdef S4VFP_KEY int u4tailCmp( S4CMP_PARM dataPtr, S4CMP_PARM searchPtr, size_t sLen ) { unsigned char *data = (unsigned char *)dataPtr ; unsigned char *search = (unsigned char *)searchPtr ; unsigned int on ; for ( on = 0 ; on < sLen ; on++ ) if ( search[on] !=17 || ( data[on] >= 10 && data[on] != 17 ) ) break ; return on ; } #endif /* S4FOX */ int b4leafSeek( B4BLOCK *b4, const char *searchValue, const int l ) { int done, len, trailCnt, duplicates, bytesSame, compareLen, keyLen, originalLen, significantBytes, cLen ; #ifdef S4VFP_KEY int skippedSpaces ; #endif char allBlank ; #ifdef E4PARM_LOW if ( b4 == 0 || searchValue == 0 || l < 0 ) return error4( 0, e4parm, E90438 ) ; #endif originalLen = len = l ; keyLen = b4->tag->header.keyLen ; #ifdef S4VFP_KEY if ( tfile4vfpKey( b4->tag ) && b4->tag->expr->type == r4str ) for ( ; len > 0 && searchValue[len-1] == 17 ; len-- ) ; skippedSpaces = ( len == originalLen ) ? 0 : 1 ; #endif len -= b4calcBlanks( (unsigned char *)searchValue, len, b4->tag->pChar ) ; /* don't compare blank bytes */ if ( len == 0 ) /* if all blanks, watch for records < blank */ { len = originalLen ; allBlank = 1 ; } else allBlank = 0 ; duplicates = 0 ; b4top( b4 ) ; for(;;) { if ( b4->curDupCnt == duplicates ) { significantBytes = keyLen - x4trailCnt( b4, b4->keyOn ) ; if ( allBlank && significantBytes == 0 ) /* found a blank record */ len = 0 ; compareLen = ( len < significantBytes ? len : significantBytes ) - b4->curDupCnt ; bytesSame = (*b4->tag->cmp)( b4->curPos, searchValue + b4->curDupCnt, (unsigned int)compareLen ) ; if ( bytesSame == -1 ) return r4after ; if ( bytesSame == compareLen ) { if ( (b4->curDupCnt + bytesSame == len)) /* unless binary character, for sure done */ { if ( len == originalLen ) done = 1 ; else /* in case of binary, we may not be done if values < blank */ { trailCnt = x4trailCnt( b4, b4->keyOn ) ; if ( significantBytes > trailCnt + len ) /* significant bytes beyond the trail, so check binary */ { /* for a VFP_KEY this should never happen as key functions should guarantee l <= keyLen */ cLen = keyLen - trailCnt ; if ( originalLen - len < cLen ) cLen = originalLen - len ; if ( c4memcmp( b4->curPos + compareLen, searchValue + len, (unsigned int)cLen ) < 0 ) /* binaries */ done = 0 ; else done = 1 ; } else done = 1 ; } if ( done == 1 ) { if ( len != originalLen && significantBytes > len ) { #ifdef S4VFP_KEY if ( skippedSpaces ) { cLen = originalLen - ( len < significantBytes ? len : significantBytes ) ; if ( u4tailCmp( b4->curPos + compareLen, searchValue + len, cLen ) != cLen ) return r4after ; } else #endif { if ( significantBytes < originalLen ) return r4after ; #ifdef E4ANALYZE if ( len > originalLen ) return error4( b4->tag->codeBase, e4info, E90438 ) ; #endif if ( (*b4->tag->cmp)( b4->curPos + compareLen, searchValue + len, (unsigned int)(originalLen - len) ) != (originalLen - len) ) return r4after ; } } if ( allBlank != 1 ) /* not all blanks, so significants matter */ b4->curDupCnt += bytesSame ; else b4->curDupCnt = 0 ; return 0 ; } } } b4->curDupCnt += bytesSame ; } b4->keyOn++ ; if ( b4->keyOn >= b4numKeys( b4 ) ) return r4after ; duplicates = x4dupCnt( b4, b4->keyOn ) ; b4->curPos -= keyLen - duplicates - x4trailCnt( b4, b4->keyOn ) ; if ( b4->curDupCnt > duplicates ) { if ( allBlank ) /* must reset the duplicates in this case only */ { b4->curDupCnt = duplicates ; if ( x4trailCnt( b4, b4->keyOn ) == len ) /* blank key found */ return 0 ; } return r4after ; } } } /* S4FOX */ #ifndef S4OFF_WRITE int b4removeLeaf( B4BLOCK *b4 ) { int oldDup, leftDup, leftTrail, keyLen, removeLen, newDup, oldBytes, newBytes, movLen, leftBytes ; unsigned char buffer[6], iLen ; char *oldPos, *infoPos ; #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif b4->builtOn = -1 ; if ( b4numKeys( b4 ) == 1 ) /* removing last key */ { b4->nodeHdr.freeSpace = B4BLOCK_SIZE - sizeof( B4NODE_HEADER ) - sizeof( B4STD_HEADER ) ; memset( b4->data, 0, (unsigned int)b4->nodeHdr.freeSpace ) ; b4->header.nKeys = 0 ; b4->keyOn = 0 ; b4->curPos = ((char *)&b4->header) + B4BLOCK_SIZE ; b4->changed = 1 ; return 0 ; } keyLen = b4->tag->header.keyLen ; iLen = b4->nodeHdr.infoLen ; oldDup = x4dupCnt( b4, b4->keyOn) ; if ( b4->keyOn == b4numKeys( b4 ) - 1 ) /* at end */ { removeLen = keyLen - oldDup - x4trailCnt( b4, b4->keyOn ) ; #ifdef E4ANALYZE if ( removeLen < 0 ) return error4( b4->tag->codeBase, e4info, E80401 ) ; #endif memset( b4->curPos, 0, (unsigned int)removeLen ) ; memset( b4->data + b4->keyOn * iLen, 0, iLen ) ; b4->keyOn-- ; } else { oldBytes = keyLen - oldDup - x4trailCnt( b4, b4->keyOn ) ; oldPos = b4->curPos ; b4skip( b4, 1L ) ; leftDup = x4dupCnt( b4, b4->keyOn) ; leftTrail = x4trailCnt( b4, b4->keyOn ) ; newDup = oldDup < leftDup ? oldDup : leftDup ; leftBytes = keyLen - leftTrail - leftDup ; newBytes = keyLen - leftTrail - newDup ; memcpy( b4->builtKey->value, oldPos, (unsigned int)(leftDup - newDup) ) ; /* copy prev dup bytes between the 2 keys only */ memcpy( b4->builtKey->value + ( leftDup - newDup ), b4->curPos, (unsigned int)leftBytes ) ; memcpy( oldPos + oldBytes - newBytes, b4->builtKey->value, (unsigned int)newBytes ) ; removeLen = oldBytes + leftBytes - newBytes ; #ifdef E4ANALYZE if ( removeLen < 0 ) return error4( b4->tag->codeBase, e4info, E80401 ) ; #endif movLen = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - iLen * b4numKeys( b4 ) - sizeof( B4NODE_HEADER ) - b4->nodeHdr.freeSpace - ( ( (char *)&b4->header ) + B4BLOCK_SIZE - b4->curPos ) ; #ifdef E4ANALYZE if ( movLen < 0 ) return error4( b4->tag->codeBase, e4info, E80401 ) ; #endif c4memmove( b4->curPos - movLen + removeLen, b4->curPos - movLen, (unsigned int)movLen ) ; memset( b4->curPos - movLen, 0, (unsigned int)removeLen ) ; b4->keyOn-- ; /* move and put info */ infoPos = b4->data + ( b4->keyOn ) * iLen ; c4memmove( infoPos, infoPos + iLen, (unsigned int)(iLen * ( b4numKeys( b4 ) - b4->keyOn ) ) ) ; x4putInfo( &b4->nodeHdr, buffer, x4recNo( b4, b4->keyOn ), leftTrail, (unsigned int)newDup ) ; memcpy( infoPos, (void *)buffer, iLen ) ; memset( b4->data + (b4numKeys( b4 ) - 1 ) * iLen, 0, iLen ) ; } b4->changed = 1 ; b4->curPos += removeLen ; b4->header.nKeys-- ; b4->nodeHdr.freeSpace += (short)( (int)iLen + removeLen ) ; return 0 ; } /* S4FOX */ int b4remove( B4BLOCK *b4 ) { char *keyCur ; int len, iLen ; #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif if( b4->header.nodeAttribute >= 2 ) /* leaf */ b4removeLeaf( b4 ) ; else { iLen = b4->tag->header.keyLen + 2 * sizeof( long ) ; keyCur = ((char *)&b4->nodeHdr) + iLen * b4->keyOn ; len = (b4numKeys( b4 ) - b4->keyOn - 1) * iLen ; #ifdef E4ANALYZE if ( b4->keyOn < 0 || b4->keyOn > b4lastpos( b4 ) || len < 0 || (unsigned)len > (B4BLOCK_SIZE - sizeof(B4STD_HEADER) - (unsigned)iLen )) return error4( b4->tag->codeBase, e4info, E90438 ) ; #endif if ( len > 0 ) c4memmove( keyCur, keyCur + iLen, (unsigned int)len ) ; b4->header.nKeys-- ; memset( ((char *)&b4->nodeHdr) + b4numKeys( b4 ) * iLen, 0, (unsigned int)iLen ) ; b4->changed = 1 ; } return 0 ; } #endif /* S4OFF_WRITE */ /* S4FOX */ int b4skip( B4BLOCK *b4, const long num ) { int numSkipped, kLen, nKeys ; long n ; n = num ; #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif nKeys = b4numKeys( b4 ) ; if ( b4->header.nodeAttribute < 2 ) /* branch */ { if ( n > 0 ) numSkipped = nKeys - b4->keyOn ; else numSkipped = -b4->keyOn ; if ( ( n <= 0L ) ? (numSkipped <= (int)n) : (numSkipped >= (int)n) ) { b4->keyOn += (int)n ; return (int)n ; } else { b4->keyOn += numSkipped ; return numSkipped ; } } else /* leaf */ { if ( nKeys == 0 ) return 0 ; kLen = b4->tag->header.keyLen ; if (n > 0 ) { if ( b4->keyOn + n >= nKeys ) { b4->curPos = ((char *)&b4->header ) + sizeof( B4STD_HEADER ) + sizeof( B4NODE_HEADER ) + b4->nodeHdr.infoLen * nKeys + b4->nodeHdr.freeSpace ; n = (long)nKeys - (long)b4->keyOn - ( b4->keyOn != nKeys ) ; b4->keyOn = nKeys ; return (int)n ; } for( numSkipped = (int)n ; numSkipped != 0 ; numSkipped-- ) { b4->keyOn++ ; b4->curPos -= ( kLen - x4dupCnt( b4, b4->keyOn ) - x4trailCnt( b4, b4->keyOn ) ) ; } } else { if ( b4->keyOn + n < 0 ) { n = -b4->keyOn ; b4->keyOn = 0 ; b4->curPos = ((char *)&b4->header ) + B4BLOCK_SIZE - kLen + x4trailCnt( b4, b4->keyOn ) ; return (int) n ; } for( numSkipped = (int)n ; numSkipped != 0 ; numSkipped++ ) { b4->curPos += ( kLen - x4dupCnt( b4, b4->keyOn ) - x4trailCnt( b4, b4->keyOn ) ) ; b4->keyOn-- ; } } return (int) n ; } } #endif /* S4FOX */ #ifdef S4CLIPPER #ifndef S4OFF_WRITE int b4flush( B4BLOCK *b4 ) { int rc ; #ifdef S4BYTE_SWAP char *swap, *swapPtr ; int i ; S4LONG longVal ; short shortVal ; #endif #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif if ( b4->changed ) { #ifdef E4INDEX_VERIFY if ( b4verify( b4 ) == -1 ) error4describe( b4->tag->codeBase, e4index, E90438, b4->tag->alias, 0, 0 ) ; #endif #ifdef S4BYTE_SWAP swap = (char *)u4allocEr( b4->tag->codeBase, B4BLOCK_SIZE ) ; if ( swap == 0 ) return -1 ; memcpy( (void *)swap, (void *)&b4->nKeys, B4BLOCK_SIZE ) ; /* position swapPtr at beginning of pointers */ shortVal = x4reverseShort( (void *)swap ) ; memcpy( swap, (void *) &shortVal, sizeof(short) ) ; swapPtr = swap + 2 ; /* swap the short pointers to B4KEY_DATA */ for ( i = 0 ; i < b4->tag->header.keysMax ; i++ ) { shortVal = x4reverseShort( (void *)swapPtr ) ; memcpy( swapPtr, (void *) &shortVal, sizeof(short) ) ; swapPtr += sizeof(short) ; } /* swap the B4KEY_DATA's */ for ( i = 0 ; i < b4->tag->header.keysMax ; i++ ) { longVal = x4reverseLong( (void *)swapPtr ) ; memcpy( swapPtr, (void *) &longVal, sizeof(S4LONG) ) ; longVal = x4reverseLong( (void *)swapPtr+sizeof(S4LONG) ) ; memcpy( swapPtr+sizeof(S4LONG), (void *) &longVal, sizeof(S4LONG) ) ; swapPtr += b4->tag->header.groupLen ; } #ifndef S4OFF_OPTIMIZE b4->tag->indexFile->readBlockTag = b4->tag ; #endif rc = file4write( &b4->tag->file, (long)b4->fileBlock*I4MULTIPLY, swap, B4BLOCK_SIZE ) ; #ifndef S4OFF_OPTIMIZE b4->tag->indexFile->->readBlockTag = 0 ; #endif u4free( swap ) ; #else #ifndef S4OFF_OPTIMIZE b4->tag->readBlockTag = b4->tag ; #endif rc = file4write( &b4->tag->file, (long)b4->fileBlock*I4MULTIPLY, &b4->nKeys, B4BLOCK_SIZE ) ; #ifndef S4OFF_OPTIMIZE b4->tag->readBlockTag = 0 ; #endif #endif if ( rc < 0 ) return rc ; b4->changed = 0 ; } return 0 ; } int b4append( B4BLOCK *b4, const long pointer ) { long adjPointer = pointer * 512 ; B4KEY_DATA *dataPtr ; #ifdef E4ANALYZE int leftLen ; #endif #ifdef E4PARM_LOW if ( b4 == 0 || pointer < 1L ) return error4( 0, e4parm, E90438 ) ; #endif #ifdef E4ANALYZE if ( b4leaf( b4 ) ) return error4( b4->tag->codeBase, e4info, E90438 ) ; #endif b4goEof( b4 ) ; dataPtr = b4key( b4, b4->keyOn ) ; #ifdef E4ANALYZE leftLen = B4BLOCK_SIZE - b4->keyOn * b4->tag->header.groupLen - sizeof(short) - sizeof(char[2]) - sizeof(pointer) ; if ( b4->keyOn < 0 || b4->keyOn != b4numKeys( b4 ) || leftLen < 0 ) return error4( b4->tag->codeBase, e4info, E90438 ) ; #endif memcpy( &dataPtr->pointer, &adjPointer, sizeof(pointer) ) ; b4->changed = 1 ; #ifdef E4INDEX_VERIFY if ( b4verify( b4 ) == -1 ) return error4describe( b4->tag->codeBase, e4index, E90438, b4->tag->alias, 0, 0 ) ; #endif return 0 ; } #endif /* S4OFF_WRITE */ #ifndef S4OFF_WRITE int b4append2( B4BLOCK *b4, const void *k, const long r, const long pointer ) { unsigned short temp ; B4KEY_DATA *dataPtr ; long adjPointer ; #ifdef E4PARM_LOW if ( b4 == 0 || k == 0 || r < 0L || pointer < 0L ) return error4( 0, e4parm, E90438 ) ; #endif b4goEof( b4 ) ; if ( b4numKeys( b4 ) > 0 ) { if ( !b4leaf( b4 ) ) /* insert after branch */ b4->keyOn++ ; else if ( b4->keyOn + !b4leaf( b4 ) < b4->tag->header.keysMax ) { temp = b4->pointers[b4numKeys( b4 )+1] ; b4->pointers[b4numKeys( b4 )+1] = b4->pointers[b4numKeys( b4 )] ; b4->pointers[b4numKeys( b4 )] = temp ; } } dataPtr = b4key( b4, b4->keyOn ) ; adjPointer = pointer * 512 ; b4->nKeys++ ; memcpy( dataPtr->value, k, b4->tag->header.groupLen-2*sizeof(long) ) ; memcpy( &dataPtr->num, &r, sizeof(r) ) ; memcpy( &dataPtr->pointer, &adjPointer, sizeof(pointer) ) ; b4->changed = 1 ; return 0 ; } /* clipper just puts at end and inserts into the index part */ int b4insert( B4BLOCK *b4, const void *k, const long r, const long pointer ) { short temp, insertPos ; #ifdef E4PARM_LOW if ( b4 == 0 || k == 0 || r < 0L || pointer < 0L ) return error4( 0, e4parm, E90438 ) ; #endif insertPos = b4->keyOn ; /* put at block end: */ b4append2( b4, k, r, pointer ) ; temp = b4->pointers[b4->keyOn] ; /* save the placed position */ c4memmove( &b4->pointers[insertPos+1], &b4->pointers[insertPos], sizeof(short) * ( b4lastpos( b4 ) - insertPos - (!b4leaf( b4 ) && b4numKeys( b4 ) < 2 ) ) ) ; b4->pointers[insertPos] = temp ; if ( b4leaf( b4 ) ) if ( b4key( b4, b4numKeys( b4 ) )->pointer != 0 ) b4key( b4, b4numKeys( b4 ) )->pointer = 0L ; return 0 ; } #endif /* S4OFF_WRITE */ #ifndef S4INLINE /* goes to one past the end of the block */ void b4goEof( B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) { error4( 0, e4parm_null, E90438 ) ; return ; } #endif b4->keyOn = b4numKeys( b4 ) ; return 0 ; } B4KEY_DATA *b4key( const B4BLOCK *b4, const int iKey ) { #ifdef E4PARM_LOW if ( b4 == 0 || iKey < 0 ) { error4( 0, e4parm, E90438 ) ; return 0 ; } #endif #ifdef E4ANALYZE if ( iKey > 2 + b4->tag->header.keysMax ) { error4( b4->tag->codeBase, e4parm, E90438 ) ; return 0 ; } if ( ( b4->pointers[iKey] < (short)((sizeof(short)) * ( b4->tag->header.keysMax + 1 ) ) ) || ( b4->pointers[iKey] > B4BLOCK_SIZE - b4->tag->header.keyLen ) ) { error4( b4->tag->codeBase, e4info, E90438 ) ; return 0 ; } #endif return (B4KEY_DATA *)((char *)&b4->nKeys + b4->pointers[iKey] ) ; } unsigned char *b4keyKey( B4BLOCK *b4, const int iKey ) { #ifdef E4PARM_LOW if ( b4 == 0 || iKey < 0 ) { error4( 0, e4parm, E90438 ) ; return 0 ; } #endif return (unsigned char *) b4key( b4, iKey )->value ; } int b4lastpos( const B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif return ( ( b4leaf( b4 ) ) ? ( b4numKeys( b4 ) - 1 ) : ( b4numKeys( b4 ) ) ) ; } int b4leaf( const B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif return( b4key( b4, 0 )->pointer == 0L ) ; } long b4recNo( const B4BLOCK *b4, const int i ) { #ifdef E4PARM_LOW if ( b4 == 0 || i < 0 ) return error4( 0, e4parm, E90438 ) ; #endif return b4key( b4, i )->num ; } #endif /* S4INLINE */ /* S4CLIPPER */ /* based on the actual stored-data (from file) only, determine whether or not a leaf. Used by file optimization routines */ int b4dataLeaf( void *data, TAG4FILE *tag ) { B4KEY_DATA *keyData ; #ifdef E4PARM_LOW if ( data == 0 || tag == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif keyData = (B4KEY_DATA *)( (char *)data + *((short *)((char *)data + sizeof(short))) ) ; return( keyData->pointer == 0L ) ; } /* S4CLIPPER */ int b4remove( B4BLOCK *b4 ) { short temp ; #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif /* just delete this entry */ temp = b4->pointers[b4->keyOn] ; if ( b4leaf( b4 ) && ( b4->keyOn + !b4leaf( b4 ) < b4->tag->header.keysMax ) ) { c4memmove( &b4->pointers[b4->keyOn], &b4->pointers[b4->keyOn+1], sizeof(short) * (b4lastpos( b4 ) - b4->keyOn + 1) ) ; b4->pointers[b4lastpos( b4 )+1] = temp ; } else { c4memmove( &b4->pointers[b4->keyOn], &b4->pointers[b4->keyOn+1], sizeof(short) * (b4lastpos( b4 ) - b4->keyOn) ) ; b4->pointers[b4lastpos( b4 )] = temp ; } b4->nKeys-- ; b4->changed = 1 ; if ( b4leaf( b4 ) ) memset( b4key( b4, b4lastpos( b4 ) + 1 ), 0, b4->tag->header.keyLen + 2 * sizeof( long ) ) ; return 0 ; } int b4room( const B4BLOCK *b4 ) { #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif if ( b4leaf( b4 ) ) return ( b4numKeys( b4 ) < b4->tag->header.keysMax ) ; return( ( b4numKeys( b4 ) < b4->tag->header.keysMax ) && ( ( B4BLOCK_SIZE - b4numKeys( b4 ) * b4->tag->header.groupLen - sizeof(short) - 2*sizeof(char)) >= sizeof(long) ) ) ; } int b4seek( B4BLOCK *b4, const char *searchValue, const int len ) { int rc, saveRc, keyCur, keyLower, keyUpper ; S4CMP_FUNCTION *cmp = b4->tag->cmp ; #ifdef E4PARM_LOW if ( b4 == 0 || searchValue == 0 || len < 0 ) return error4( 0, e4parm, E90438 ) ; #endif /* keyOn must be between keyLower and keyUpper */ keyLower = -1 ; keyUpper = b4numKeys( b4 ) ; if ( keyUpper == 0 ) { b4->keyOn = 0 ; return r4after ; } saveRc = 1 ; for(;;) /* Repeat until the key is found */ { keyCur = (keyUpper + keyLower) / 2 ; rc = (*cmp)( b4keyKey(b4,keyCur), searchValue, len ) ; if ( rc >= 0 ) { keyUpper = keyCur ; saveRc = rc ; } else keyLower = keyCur ; if ( keyLower >= (keyUpper-1) ) /* then there is no exact match */ { b4->keyOn = keyUpper ; if ( saveRc ) return r4after ; return 0 ; } } } int b4skip( B4BLOCK *b4, const long n ) { int numLeft ; #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif if ( n > 0 ) { numLeft = b4numKeys( b4 ) - b4->keyOn ; if ( b4leaf( b4 ) ) if ( numLeft != 0 ) numLeft -- ; } else numLeft = -b4->keyOn ; if ( ( n <= 0L ) ? ( (long)numLeft <= n ) : ( (long)numLeft >= n ) ) { b4->keyOn = b4->keyOn + (int) n ; return (int) n ; } else { b4->keyOn = b4->keyOn + numLeft ; return numLeft ; } } #endif /* S4CLIPPER */ #ifdef E4INDEX_VERIFY int b4verify( B4BLOCK *b4 ) { int i ; #ifdef S4CLIPPER int j ; long val ; #endif #ifdef S4FOX int holdDup, holdTrail ; #else int iType ; #endif #ifdef E4PARM_LOW if ( b4 == 0 ) return error4( 0, e4parm_null, E90438 ) ; #endif #ifdef S4FOX holdDup = b4->curDupCnt ; holdTrail = b4->curTrailCnt ; #endif if ( b4->tag->codeBase->doIndexVerify == 0 ) return 0 ; #ifdef S4CLIPPER /* block internal verification... */ for ( i = 0 ; i < b4->tag->header.keysMax ; i++ ) for ( j = i + 1 ; j <= b4->tag->header.keysMax ; j++ ) if ( b4->pointers[i] == b4->pointers[j] ) #ifdef E4ANALYZE_ALL return error4describe( b4->tag->codeBase, e4index, E80403, b4->tag->alias, 0, 0 ) ; #else return error4( b4->tag->codeBase, e4index, E80403 ) ; #endif /* validate key count */ if ( b4numKeys( b4 ) < b4->tag->header.keysHalf && b4->tag->header.root / 512 != b4->fileBlock && b4->tag->header.keysHalf > 1 ) /* allowed if only max 2 keys per index block */ return error4describe( b4->tag->codeBase, e4index, E85709, b4->tag->alias, 0, 0 ) ; #endif /* all keys in a given block should be of the same type... - branch = 1 */ #ifndef S4FOX iType = b4leaf( b4 ) ? 0 : 1 ; #endif /* key order verification */ #ifdef S4CLIPPER for ( i = 0 ; i <= b4numKeys( b4 ) ; i++ ) { val = b4key( b4, i )->pointer ; if ( ( b4key( b4, i )->pointer ? 1 : 0 ) != iType ) #ifdef E4ANALYZE_ALL return error4describe( b4->tag->codeBase, E80405, e4index, b4->tag->alias, 0, 0 ) ; #else return error4( b4->tag->codeBase, e4index, E80405 ) ; #endif } #endif for ( i = 0 ; i < b4numKeys( b4 ) - 1 ; i++ ) { #ifdef S4FOX if ( u4keycmp( b4keyKey( b4, i), b4keyKey( b4, i + 1 ), (unsigned)b4->tag->header.keyLen, (unsigned)b4->tag->header.keyLen, 0, &b4->tag->vfpInfo ) > 0 ) #else if ( (*b4->tag->cmp)( b4keyKey( b4, i ), b4keyKey( b4, i + 1 ), b4->tag->header.keyLen ) > 0 ) #endif #ifdef E4ANALYZE_ALL return error4describe( b4->tag->codeBase, e4index, E80406, b4->tag->alias, 0, 0 ) ; #else return error4( b4->tag->codeBase, e4index, E80406 ) ; #endif } #ifdef S4FOX b4->curDupCnt = holdDup ; b4->curTrailCnt = holdTrail ; #endif return 0 ; } #endif /* E4INDEX_VERIFY */ #endif /* S4CLIENT */ #endif /* S4INDEX_OFF */