1079 lines
30 KiB
C
Executable File
1079 lines
30 KiB
C
Executable File
/* d4seek.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
|
|
|
|
#include "d4all.h"
|
|
#ifndef S4UNIX
|
|
#ifdef __TURBOC__
|
|
#pragma hdrstop
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef S4INDEX_OFF
|
|
#ifndef S4CLIENT
|
|
|
|
#ifdef S4FOX
|
|
/* because of possibilities of null, key may need to have a character
|
|
indicater added */
|
|
static int tfile4stok( TAG4FILE *t4, char *buf, const char *str, int len )
|
|
{
|
|
char *ptr = buf ;
|
|
int hasNull = 0 ;
|
|
|
|
if ( expr4nullLow( t4->expr, 0 ) )
|
|
{
|
|
if ( len == 0 ) /* seek for null */
|
|
{
|
|
*ptr = 0 ;
|
|
return 1 ;
|
|
}
|
|
|
|
*ptr = (char)0x80 ;
|
|
ptr++ ;
|
|
hasNull = 1 ;
|
|
}
|
|
|
|
#ifdef S4VFP_KEY
|
|
if ( tfile4type( t4 ) == r4str && tfile4vfpKey( t4 ) )
|
|
{
|
|
if ( len*2 > t4->header.keyLen )
|
|
{
|
|
#ifdef E4ANALYZE
|
|
if ( (t4->header.keyLen-hasNull)%2 == 1 )
|
|
return error4( 0, e4index, E82107 ) ;
|
|
#endif
|
|
len = (t4->header.keyLen-hasNull) / 2 ;
|
|
}
|
|
len = t4strToVFPKey( ptr, str, len, t4->header.keyLen, &t4->vfpInfo ) ;
|
|
}
|
|
else
|
|
(*t4->stok)( ptr, str, len ) ;
|
|
#else
|
|
(*t4->stok)( ptr, str, len ) ;
|
|
#endif
|
|
|
|
return len + hasNull ;
|
|
}
|
|
|
|
static void tfile4dtok( TAG4FILE *t4, char *buf, const double dkey )
|
|
{
|
|
if ( expr4nullLow( t4->expr, 0 ) )
|
|
{
|
|
buf[0] = (char)0x80 ;
|
|
|
|
(*t4->dtok)( buf+1, dkey ) ;
|
|
return ;
|
|
}
|
|
else
|
|
{
|
|
(*t4->dtok)( buf, dkey ) ;
|
|
return ;
|
|
}
|
|
}
|
|
#else
|
|
#define tfile4stok( t4, buf, str, len ) ((*((t4)->stok))( (buf), (str), (len) ), len)
|
|
#define tfile4dtok( t4, buf, str ) (*((t4)->dtok))( (buf), (str) )
|
|
#endif
|
|
|
|
/* function to ensure the integrity of the seeks return value */
|
|
/* in single user mode, exclusive, or if file is locked, the data is assumed up to date, and not checked */
|
|
#ifdef P4ARGS_USED
|
|
#pragma argsused
|
|
#endif
|
|
static int d4seekCheck( DATA4 *data, TAG4FILE *tag, const int rc, const char *buf, const int l )
|
|
{
|
|
int rc2, len ;
|
|
#ifndef S4SINGLE
|
|
int skipped ;
|
|
unsigned char *dbfKey ;
|
|
#endif
|
|
|
|
#ifndef S4SINGLE
|
|
if ( rc == r4locked )
|
|
return r4locked ;
|
|
skipped = 0 ;
|
|
#endif
|
|
|
|
len = l ;
|
|
|
|
if ( tfile4eof( tag ) )
|
|
return d4goEof( data ) ;
|
|
|
|
if ( len > tag->header.keyLen )
|
|
len = tag->header.keyLen ;
|
|
|
|
if ( d4recCountLessEq( data, tfile4recNo( tag ) ) == 0 ) /* past eof */
|
|
while ( d4recCountLessEq( data, tfile4recNo( tag ) ) == 0 ) /* past eof */
|
|
{
|
|
if ( tfile4skip( tag, 1L ) == 0 ) /* eof */
|
|
return d4goEof( data ) ;
|
|
#ifndef S4SINGLE
|
|
skipped = 1 ;
|
|
#endif
|
|
}
|
|
|
|
#ifndef S4SINGLE
|
|
#ifdef S4SERVER
|
|
if ( dfile4lockTestFile( data->dataFile, data4clientId( data ), data4serverId( data ) ) )
|
|
#else
|
|
if ( d4lockTestFile( data ) )
|
|
#endif
|
|
{
|
|
#endif
|
|
#ifndef S4OFF_OPTIMIZE
|
|
data->dataFile->hiPrio = 1 ;
|
|
#endif
|
|
rc2 = d4go( data, tfile4recNo( tag ) ) ;
|
|
#ifndef S4OFF_OPTIMIZE
|
|
data->dataFile->hiPrio = 0 ;
|
|
#endif
|
|
if ( rc2 )
|
|
return rc2 ;
|
|
return rc ;
|
|
#ifndef S4SINGLE
|
|
}
|
|
for( ;; )
|
|
{
|
|
if ( d4recCountLessEq( data, tfile4recNo( tag ) ) != 0 ) /* valid spot */
|
|
{
|
|
#ifndef S4OFF_OPTIMIZE
|
|
data->dataFile->hiPrio = 1 ;
|
|
#endif
|
|
rc2 = d4go( data, tfile4recNo( tag ) ) ;
|
|
#ifndef S4OFF_OPTIMIZE
|
|
data->dataFile->hiPrio = 0 ;
|
|
#endif
|
|
if ( rc2 )
|
|
return rc2 ;
|
|
|
|
if ( expr4context( tag->expr, data ) < 0 )
|
|
return -1 ;
|
|
if ( tfile4exprKey( tag, &dbfKey ) < 0 )
|
|
return -1 ;
|
|
#ifdef S4FOX
|
|
if ( !u4keycmp( tfile4key( tag ), dbfKey, (unsigned)expr4keyLen( tag->expr ), (unsigned)tag->header.keyLen, 0, &tag->vfpInfo ) ) /* matched */
|
|
#else
|
|
if ( !(*tag->cmp)( tfile4key( tag ), dbfKey, (unsigned)expr4keyLen( tag->expr ) ) ) /* matched */
|
|
#endif
|
|
{
|
|
if ( skipped )
|
|
{
|
|
#ifdef S4FOX
|
|
rc2 = u4keycmp( dbfKey, buf, (unsigned)len, (unsigned)expr4keyLen( tag->expr ), 0, &tag->vfpInfo ) ;
|
|
#else
|
|
rc2 = (*tag->cmp)( dbfKey, buf, (unsigned)expr4keyLen( tag->expr ) ) ;
|
|
#endif
|
|
if ( rc2 == 0 ) /* worked */
|
|
return rc2 ;
|
|
if ( rc2 > 0 )
|
|
return r4after ;
|
|
/* other wise, if < 0, can't return r4after, so go down and skip next */
|
|
}
|
|
else
|
|
return rc ;
|
|
}
|
|
}
|
|
|
|
/* try next record */
|
|
if ( tfile4skip( tag, 1L ) == 0 ) /* eof */
|
|
return d4goEof( data ) ;
|
|
if ( error4code( data->codeBase ) < 0 )
|
|
return -1 ;
|
|
skipped = 1 ;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
static int d4seekServer( DATA4 *data, const void *searchData, const int len, const int fromCurrentPos, const int seekType )
|
|
{
|
|
CONNECTION4 *connection ;
|
|
CONNECTION4GO_INFO_OUT *out ;
|
|
CONNECTION4SEEK_INFO_IN infoIn ;
|
|
int rc, saveRc ;
|
|
TAG4 *tag ;
|
|
CODE4 *c4 ;
|
|
#ifdef E4ANALYZE
|
|
int e4anLen ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 || searchData == 0 || len < 0 || fromCurrentPos < 0 || fromCurrentPos > 1 ||
|
|
( seekType != CON4SEEK && seekType != CON4SEEK_DBL ) )
|
|
return error4( 0, e4parm, E92906 ) ;
|
|
#endif
|
|
|
|
c4 = data->codeBase ;
|
|
|
|
tag = d4tagDefault( data ) ;
|
|
if ( tag == 0 )
|
|
return r4noTag ;
|
|
|
|
#ifndef S4OFF_WRITE
|
|
rc = d4updateRecord( data, 0 ) ; /* was 1 */
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
|
|
connection = data->dataFile->connection ;
|
|
if ( connection == 0 )
|
|
return error4stack( c4, rc, E92906 ) ;
|
|
|
|
connection4assign( connection, seekType, data4clientId( data ), data4serverId( data ) ) ;
|
|
#ifdef E4ANALYZE
|
|
e4anLen = sizeof( infoIn.tagName ) ;
|
|
if ( e4anLen != even4up( LEN4TAG_ALIAS + 1 ) || e4anLen != even4up( sizeof( tag->tagFile->alias ) ) )
|
|
return error4( c4, e4struct, E92906 ) ;
|
|
#endif
|
|
memcpy( infoIn.tagName, tag->tagFile->alias, LEN4TAG_ALIAS ) ;
|
|
infoIn.keyLen = len ;
|
|
infoIn.fromCurrentPos = fromCurrentPos ;
|
|
if ( fromCurrentPos == 1 ) /* verify at valid position, first */
|
|
{
|
|
if ( d4eof( data ) || d4bof( data ) )
|
|
infoIn.startPos = 0 ;
|
|
else
|
|
infoIn.startPos = d4recNo( data ) ; /* for seek next */
|
|
}
|
|
connection4addData( connection, &infoIn, sizeof(CONNECTION4SEEK_INFO_IN), 0 ) ;
|
|
connection4addData( connection, searchData, len, 0 ) ;
|
|
connection4addData( connection, "", 1, 0 ) ; /* null end for character double seeks */
|
|
saveRc = connection4repeat( connection, -2, -1, -1, data ) ;
|
|
if ( saveRc < 0 )
|
|
return connection4errorDescribe( connection, c4, saveRc, E92906, tag->tagFile->alias, 0, 0 ) ;
|
|
if ( saveRc == r4locked )
|
|
return r4locked ;
|
|
if ( saveRc == r4eof )
|
|
{
|
|
rc = d4goEof( data ) ;
|
|
if ( rc == 0 )
|
|
rc = r4eof ;
|
|
return rc ;
|
|
}
|
|
if ( connection4len( connection ) != (long)sizeof( CONNECTION4GO_INFO_OUT ) + (long)d4recWidth( data ) )
|
|
return error4( c4, e4packetLen, E92906 ) ;
|
|
out = (CONNECTION4GO_INFO_OUT *)connection4data( connection ) ;
|
|
|
|
if ( saveRc == r4entry )
|
|
rc = r4entry ;
|
|
else rc = 0 ;
|
|
rc = d4goVirtual( data, out->recNo, rc, out, connection ) ;
|
|
if ( rc != 0 )
|
|
return rc ;
|
|
return saveRc ;
|
|
}
|
|
#endif
|
|
|
|
int S4FUNCTION d4seek( DATA4 *data, const char *str )
|
|
{
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 || str == 0 )
|
|
return error4( 0, e4parm_null, E92907 ) ;
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
return d4seekServer( data, str, strlen( str ), 0, CON4SEEK ) ;
|
|
#else
|
|
return d4seekN( data, str, strlen( str ) ) ;
|
|
#endif
|
|
}
|
|
|
|
#ifndef S4CB51
|
|
int S4FUNCTION d4seekNext( DATA4 *data, const char *str )
|
|
{
|
|
#ifdef S4CLIENT
|
|
int oldErrGo, rc ;
|
|
CODE4 *c4 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 || str == 0 )
|
|
return error4( 0, e4parm_null, E92908 ) ;
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
c4 = data->codeBase ;
|
|
oldErrGo = c4->errGo ; /* avoid for r4entry */
|
|
c4->errGo = 0 ;
|
|
rc = d4seekServer( data, str, strlen( str ), 1, CON4SEEK ) ;
|
|
c4->errGo = oldErrGo ;
|
|
if ( rc < 0 && error4code( c4 ) == 0 )
|
|
return error4( c4, rc, E92908 ) ;
|
|
return rc ;
|
|
#else
|
|
return d4seekNextN( data, str, strlen( str ) ) ;
|
|
#endif
|
|
}
|
|
|
|
int S4FUNCTION d4seekNextN( DATA4 *data, const char *str, const int l )
|
|
{
|
|
CODE4 *c4 ;
|
|
int rc ;
|
|
#ifndef S4SERVER
|
|
#ifndef S4OFF_MULTI
|
|
int oldErrGo ;
|
|
#endif
|
|
#endif
|
|
#ifndef S4CLIENT
|
|
int len, rc2, saveGo ;
|
|
TAG4 *tag ;
|
|
TAG4FILE *tfile ;
|
|
char buf[I4MAX_KEY_SIZE] ;
|
|
unsigned char *dbfKey ;
|
|
#endif
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( data, 2, E92905 ) )
|
|
return 0 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 || str == 0 )
|
|
return error4( 0, e4parm_null, E92905 ) ;
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
c4 = data->codeBase ;
|
|
oldErrGo = c4->errGo ; /* avoid for r4entry */
|
|
c4->errGo = 0 ;
|
|
rc = d4seekServer( data, str, l, 1, CON4SEEK ) ;
|
|
c4->errGo = oldErrGo ;
|
|
if ( rc < 0 && error4code( c4 ) == 0 )
|
|
return error4( c4, rc, E92908 ) ;
|
|
return rc ;
|
|
#else
|
|
len = l ;
|
|
c4 = data->codeBase ;
|
|
if ( c4 == 0 )
|
|
return e4info ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return -1 ;
|
|
|
|
tag = d4tagDefault( data ) ;
|
|
if ( tag == 0 )
|
|
return r4noTag ;
|
|
|
|
#ifndef S4OFF_WRITE
|
|
rc = d4updateRecord( data, 0 ) ; /* was 1 */
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
|
|
tfile = tag->tagFile ;
|
|
|
|
#ifdef S4UNIX
|
|
#ifdef S4MDX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
c4bcdFromA( buf, str, len ) ;
|
|
break ;
|
|
case r4date:
|
|
t4strToDateMdx( buf, str, len ) ;
|
|
break ;
|
|
case r4str:
|
|
t4noChangeStr( buf, str, len ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4FOX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
t4strToFox( buf, str, len ) ;
|
|
break ;
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4dtstrToFox( buf, str, len ) ;
|
|
break ;
|
|
case r4str:
|
|
t4noChangeStr( buf, str, len ) ;
|
|
break ;
|
|
case r4log:
|
|
t4strToLog( buf, str, len ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4CLIPPER
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
t4strToClip( buf, str, len ) ;
|
|
break ;
|
|
case r4date:
|
|
case r4dateDoub:
|
|
case r4str:
|
|
t4noChangeStr( buf, str, len ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4NDX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
t4strToDoub( buf, str, len ) ;
|
|
break ;
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4strToDateMdx( buf, str, len ) ;
|
|
break ;
|
|
case r4str:
|
|
t4noChangeStr( buf, str, len ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#else
|
|
len = tfile4stok( tag->tagFile, buf, str, len ) ;
|
|
#endif
|
|
|
|
if ( tfile4type( tfile ) != r4str )
|
|
len = tfile->header.keyLen ;
|
|
else
|
|
if ( len <= 0 )
|
|
len = strlen( str ) ;
|
|
|
|
t4versionCheck( tag, 0, 0 ) ;
|
|
|
|
if ( tfile4recNo( tfile ) != data->recNum )
|
|
{
|
|
#ifndef S4OFF_MULTI
|
|
if ( d4lockTest( data, data->recNum ) == 0 ) /* ensure latest from disk */
|
|
{
|
|
#ifndef S4SERVER
|
|
oldErrGo = data->codeBase->errGo ;
|
|
data->codeBase->errGo = 0 ;
|
|
#endif
|
|
#ifndef S4OFF_OPTIMIZE
|
|
data->dataFile->hiPrio = 1 ;
|
|
#endif
|
|
saveGo = d4go( data, data->recNum ) ;
|
|
#ifndef S4OFF_OPTIMIZE
|
|
data->dataFile->hiPrio = 0 ;
|
|
#endif
|
|
#ifndef S4SERVER
|
|
data->codeBase->errGo = oldErrGo ;
|
|
#endif
|
|
if ( saveGo < 0 )
|
|
return saveGo ;
|
|
}
|
|
else
|
|
#endif
|
|
saveGo = 0 ;
|
|
|
|
if ( saveGo != r4entry )
|
|
{
|
|
if ( expr4context( tfile->expr, data ) < 0 )
|
|
return -1 ;
|
|
|
|
tfile4exprKey( tfile, &dbfKey ) ;
|
|
|
|
rc = tfile4go( tfile, dbfKey, data->recNum, 0 ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
saveGo = 0 ;
|
|
if ( expr4context( tfile->expr, data ) < 0 )
|
|
return -1 ;
|
|
rc = tfile4exprKey( tfile, &dbfKey ) ;
|
|
}
|
|
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
|
|
if ( len > tfile->header.keyLen )
|
|
len = tfile->header.keyLen ;
|
|
|
|
if ( saveGo == r4entry ) /* at eof or bof, so present record not match, so regular seek */
|
|
{
|
|
rc = tfile4seek( tfile, buf, len ) ;
|
|
return d4seekCheck( data, tfile, rc, buf, len ) ; /* return a valid value */
|
|
}
|
|
|
|
/* first check where the datafile currently is in relation to the
|
|
seeked-for item */
|
|
#ifdef S4FOX
|
|
rc = u4keycmp( buf, dbfKey, len, (unsigned)expr4keyLen( tfile->expr ), 0, &tag->tagFile->vfpInfo ) ;
|
|
#else
|
|
rc = (*tfile->cmp)( buf, dbfKey, (unsigned)len ) ;
|
|
#endif
|
|
|
|
if ( rc != 0 ) /* present record not match, so regular seek */
|
|
{
|
|
rc = tfile4seek( tfile, buf, len ) ;
|
|
return d4seekCheck( data, tfile, rc, buf, len ) ; /* return a valid value */
|
|
}
|
|
|
|
rc = (int)tfile4dskip( tfile, 1L ) ;
|
|
if ( rc == 0 ) /* on a valid entry, but it is last entry, so r4entry returned */
|
|
return r4entry ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
else
|
|
rc = 0 ;
|
|
|
|
/* need to check the key against the seek key to see whether or not
|
|
we have gone too far */
|
|
#ifdef S4FOX
|
|
/* fox version returns # matching bytes, so subtract to see if valid value */
|
|
rc = u4keycmp( tfile4key( tfile ), buf, (unsigned)len, (unsigned)tfile->header.keyLen, 0, &tfile->vfpInfo ) ;
|
|
#else
|
|
rc = (*tfile->cmp)( buf, tfile4key( tfile ), (unsigned)len ) ;
|
|
#endif
|
|
rc2 = d4seekCheck( data, tfile, rc, buf, len ) ; /* return a valid value */
|
|
if ( rc != 0 )
|
|
return r4entry ;
|
|
return rc2 ;
|
|
#endif
|
|
}
|
|
#endif /* S4CB51 */
|
|
|
|
int S4FUNCTION d4seekN( DATA4 *data, const char *str, const int l )
|
|
{
|
|
#ifndef S4CLIENT
|
|
TAG4 *tag ;
|
|
TAG4FILE *tfile ;
|
|
int rc, len ;
|
|
CODE4 *c4 ;
|
|
char buf[I4MAX_KEY_SIZE] ;
|
|
#endif
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( data, 2, E92903 ) )
|
|
return 0 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 || str == 0 )
|
|
return error4( 0, e4parm_null, E92903 ) ;
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
return d4seekServer( data, str, l, 0, CON4SEEK ) ;
|
|
#else
|
|
len = l ;
|
|
c4 = data->codeBase ;
|
|
if ( c4 == 0 )
|
|
return e4info ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return -1 ;
|
|
|
|
tag = d4tagDefault( data ) ;
|
|
if ( tag == 0 )
|
|
return r4noTag ;
|
|
|
|
#ifndef S4OFF_WRITE
|
|
rc = d4updateRecord( data, 0 ) ; /* was 1*/
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
|
|
tfile = tag->tagFile ;
|
|
|
|
#ifdef S4FOX
|
|
if ( d4version( data ) == 0x30 && l == 0 ) /* means seek for .NULL. */
|
|
{
|
|
len = tfile->header.keyLen ;
|
|
memset( buf, 0, len ) ;
|
|
}
|
|
else
|
|
#endif
|
|
{ /* for S4FOX */
|
|
#ifdef S4UNIX
|
|
#ifdef S4MDX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
c4bcdFromA( buf, str, len ) ;
|
|
break ;
|
|
case r4date:
|
|
t4strToDateMdx( buf, str, len ) ;
|
|
break ;
|
|
case r4str:
|
|
if ( len > tfile->header.keyLen )
|
|
len = tfile->header.keyLen ;
|
|
t4noChangeStr( buf, str, len ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4FOX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
t4strToFox( buf, str, len ) ;
|
|
break ;
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4dtstrToFox( buf, str, len ) ;
|
|
break ;
|
|
case r4str:
|
|
if ( len > tfile->header.keyLen )
|
|
len = tfile->header.keyLen ;
|
|
t4noChangeStr( buf, str, len ) ;
|
|
break ;
|
|
case r4log:
|
|
t4strToLog( buf, str, len ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4CLIPPER
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
t4strToClip( buf, str, len ) ;
|
|
break ;
|
|
case r4date:
|
|
case r4dateDoub:
|
|
case r4str:
|
|
if ( len > tfile->header.keyLen )
|
|
len = tfile->header.keyLen ;
|
|
t4noChangeStr( buf, str, len ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4NDX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
t4strToDoub( buf, str, len ) ;
|
|
break ;
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4strToDateMdx( buf, str, len ) ;
|
|
break ;
|
|
case r4str:
|
|
if ( len > tfile->header.keyLen )
|
|
len = tfile->header.keyLen ;
|
|
t4noChangeStr( buf, str, len ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#else
|
|
#ifdef S4CLIPPER
|
|
switch ( tfile4type( tfile ) )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
if ( tfile4stok( tfile, buf, str, tfile->header.keyLen ) < 0 )
|
|
return -1 ;
|
|
break ;
|
|
default:
|
|
if ( tfile4stok( tfile, buf, str, len ) < 0 )
|
|
return -1 ;
|
|
break ;
|
|
}
|
|
#else
|
|
len = tfile4stok( tfile, buf, str, len ) ;
|
|
#endif
|
|
#endif
|
|
|
|
if ( tfile4type( tfile ) != r4str )
|
|
len = tfile->header.keyLen ;
|
|
else
|
|
if ( len <= 0 )
|
|
len = strlen( str ) ;
|
|
} /* for S4FOX */
|
|
|
|
t4versionCheck( tag, 0, 0 ) ;
|
|
rc = tfile4seek( tfile, buf, len ) ;
|
|
|
|
return d4seekCheck( data, tfile, rc, buf, len ) ; /* return a valid value */
|
|
#endif
|
|
}
|
|
|
|
int S4FUNCTION d4seekDouble( DATA4 *data, const double dkey )
|
|
{
|
|
#ifndef S4CLIENT
|
|
TAG4 *tag ;
|
|
TAG4FILE *tfile ;
|
|
CODE4 *c4 ;
|
|
int rc ;
|
|
char buf[I4MAX_KEY_SIZE] ;
|
|
#ifdef S4CLIPPER
|
|
int len ;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( data, 2, E92903 ) )
|
|
return 0 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E92904 ) ;
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
return d4seekServer( data, &dkey, sizeof( dkey ), 0, CON4SEEK_DBL ) ;
|
|
#else
|
|
c4 = data->codeBase ;
|
|
if ( c4 == 0 )
|
|
return e4info ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return -1 ;
|
|
|
|
tag = d4tagDefault( data ) ;
|
|
if ( tag == 0 )
|
|
return r4noTag ;
|
|
|
|
#ifndef S4OFF_WRITE
|
|
rc = d4updateRecord( data, 0 ) ; /* was 1 */
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
|
|
tfile = tag->tagFile ;
|
|
|
|
#ifdef S4CLIPPER
|
|
if ( tfile->dtok == 0 )
|
|
{
|
|
len = tfile->header.keyLen ;
|
|
c4dtoa45( dkey, buf, len, tfile->header.keyDec ) ;
|
|
if ( buf[0] == '*' ) /* unknown overflow result */
|
|
return -1 ;
|
|
c4clip( buf, len ) ;
|
|
}
|
|
else
|
|
#else
|
|
if ( tfile->dtok == 0 )
|
|
return error4( data->codeBase, e4seek, E82902 ) ;
|
|
#endif
|
|
|
|
#ifdef S4UNIX
|
|
#ifdef S4MDX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
c4bcdFromD( buf, dkey ) ;
|
|
break ;
|
|
case r4date:
|
|
t4noChangeDouble( buf, dkey ) ;
|
|
break ;
|
|
case r4str:
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4FOX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4dblToFox( buf, dkey ) ;
|
|
break ;
|
|
case r4str:
|
|
case r4log:
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4CLIPPER
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
case r4str:
|
|
break ;
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4dateDoubToStr( buf, dkey ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4NDX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4noChangeDouble( buf, dkey ) ;
|
|
break ;
|
|
case r4str:
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#else
|
|
tfile4dtok( tfile, buf, dkey ) ;
|
|
#endif
|
|
|
|
t4versionCheck( tag, 0, 0 ) ;
|
|
rc = tfile4seek( tfile, buf, tfile->header.keyLen ) ;
|
|
|
|
return d4seekCheck( data, tfile, rc, buf, tfile->header.keyLen ) ; /* return a valid value */
|
|
#endif
|
|
}
|
|
|
|
#ifndef S4CB51
|
|
int S4FUNCTION d4seekNextDouble( DATA4 *data, const double dkey )
|
|
{
|
|
CODE4 *c4 ;
|
|
int rc ;
|
|
#ifndef S4SERVER
|
|
#ifndef S4OFF_MULTI
|
|
int oldErrGo ;
|
|
#endif
|
|
#endif
|
|
#ifndef S4CLIENT
|
|
int rc2, saveGo ;
|
|
TAG4 *tag ;
|
|
TAG4FILE *tfile ;
|
|
char buf[I4MAX_KEY_SIZE] ;
|
|
unsigned char *dbfKey ;
|
|
#ifdef S4CLIPPER
|
|
int len ;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef S4VBASIC
|
|
if ( c4parm_check( data, 2, E92909 ) )
|
|
return 0 ;
|
|
#endif
|
|
|
|
#ifdef E4PARM_HIGH
|
|
if ( data == 0 )
|
|
return error4( 0, e4parm_null, E92909 ) ;
|
|
#endif
|
|
|
|
#ifdef S4CLIENT
|
|
c4 = data->codeBase ;
|
|
oldErrGo = c4->errGo ; /* avoid for r4entry */
|
|
c4->errGo = 0 ;
|
|
rc = d4seekServer( data, &dkey, sizeof( dkey ), 1, CON4SEEK_DBL ) ;
|
|
c4->errGo = oldErrGo ;
|
|
if ( rc < 0 && error4code( c4 ) == 0 )
|
|
return error4( c4, rc, E92908 ) ;
|
|
return rc ;
|
|
#else
|
|
c4 = data->codeBase ;
|
|
if ( c4 == 0 )
|
|
return e4info ;
|
|
if ( error4code( c4 ) < 0 )
|
|
return -1 ;
|
|
|
|
tag = d4tagDefault( data ) ;
|
|
if ( tag == 0 )
|
|
return r4noTag ;
|
|
|
|
#ifndef S4OFF_WRITE
|
|
rc = d4updateRecord( data, 0 ) ; /* was 1 */
|
|
if ( rc )
|
|
return rc ;
|
|
#endif
|
|
|
|
tfile = tag->tagFile ;
|
|
#ifdef S4CLIPPER
|
|
if ( tfile->dtok == 0 )
|
|
{
|
|
len = tfile->header.keyLen ;
|
|
c4dtoa45( dkey, buf, len, tfile->header.keyDec ) ;
|
|
if ( buf[0] == '*' ) /* unknown overflow result */
|
|
return -1 ;
|
|
c4clip( buf, len ) ;
|
|
}
|
|
else
|
|
#else
|
|
if ( tfile->dtok == 0 )
|
|
return error4( data->codeBase, e4seek, E82902 ) ;
|
|
#endif
|
|
|
|
#ifdef S4UNIX
|
|
#ifdef S4MDX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
c4bcdFromD( buf, dkey ) ;
|
|
break ;
|
|
case r4date:
|
|
t4noChangeDouble( buf, dkey ) ;
|
|
break ;
|
|
case r4str:
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4FOX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4dblToFox( buf, dkey ) ;
|
|
break ;
|
|
case r4str:
|
|
case r4log:
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4CLIPPER
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
case r4str:
|
|
break ;
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4dateDoubToStr( buf, dkey ) ;
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#ifdef S4NDX
|
|
switch ( tfile->keyType )
|
|
{
|
|
case r4num:
|
|
case r4numDoub:
|
|
case r4date:
|
|
case r4dateDoub:
|
|
t4noChangeDouble( buf, dkey ) ;
|
|
break ;
|
|
case r4str:
|
|
break ;
|
|
default:
|
|
return error4( data->codeBase, e4index, E82901 ) ;
|
|
}
|
|
#endif
|
|
#else
|
|
tfile4dtok( tfile, buf, dkey ) ;
|
|
#endif
|
|
|
|
t4versionCheck( tag, 0, 0 ) ;
|
|
|
|
if ( tfile4recNo( tfile ) != data->recNum )
|
|
{
|
|
#ifndef S4OFF_MULTI
|
|
if ( d4lockTest( data, data->recNum ) == 0 ) /* ensure latest from disk */
|
|
{
|
|
#ifndef S4SERVER
|
|
oldErrGo = data->codeBase->errGo ;
|
|
data->codeBase->errGo = 0 ;
|
|
#endif
|
|
#ifndef S4OFF_OPTIMIZE
|
|
data->dataFile->hiPrio = 1 ;
|
|
#endif
|
|
saveGo = d4go( data, data->recNum ) ;
|
|
#ifndef S4OFF_OPTIMIZE
|
|
data->dataFile->hiPrio = 0 ;
|
|
#endif
|
|
#ifndef S4SERVER
|
|
data->codeBase->errGo = oldErrGo ;
|
|
#endif
|
|
if ( saveGo < 0 )
|
|
return saveGo ;
|
|
}
|
|
else
|
|
#endif
|
|
saveGo = 0 ;
|
|
|
|
if ( saveGo != r4entry )
|
|
{
|
|
if ( expr4context( tfile->expr, data ) < 0 )
|
|
return -1 ;
|
|
rc = tfile4exprKey( tfile, &dbfKey ) ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
|
|
rc = tfile4go( tfile, dbfKey, data->recNum, 0 ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
saveGo = 0 ;
|
|
if ( expr4context( tfile->expr, data ) < 0 )
|
|
return -1 ;
|
|
rc = tfile4exprKey( tfile, &dbfKey ) ;
|
|
}
|
|
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
|
|
if ( saveGo == r4entry ) /* at eof or bof, so present record not match, so regular seek */
|
|
{
|
|
rc = tfile4seek( tfile, buf, tfile->header.keyLen ) ;
|
|
return d4seekCheck( data, tfile, rc, buf, tfile->header.keyLen ) ; /* return a valid value */
|
|
}
|
|
|
|
/* first check where the datafile currently is in relation to the
|
|
seeked-for item */
|
|
#ifdef S4FOX
|
|
rc = u4keycmp( dbfKey, buf, (unsigned)tfile->header.keyLen, (unsigned)expr4keyLen( tfile->expr ), 0, &tfile->vfpInfo ) ;
|
|
#else
|
|
rc = (*tfile->cmp)( buf, dbfKey, (unsigned)tfile->header.keyLen ) ;
|
|
#endif
|
|
|
|
if ( rc != 0 ) /* present record not match, so regular seek */
|
|
{
|
|
rc = tfile4seek( tfile, buf, tfile->header.keyLen ) ;
|
|
return d4seekCheck( data, tfile, rc, buf, tfile->header.keyLen ) ; /* return a valid value */
|
|
}
|
|
|
|
rc = (int)tfile4dskip( tfile, 1L ) ;
|
|
if ( rc == 0 )
|
|
return r4after ;
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
else
|
|
rc = 0 ;
|
|
|
|
/* need to check the key against the seek key to see whether or not
|
|
we have gone too far */
|
|
#ifdef S4FOX
|
|
rc = u4keycmp( tfile4key( tfile ), buf, tfile->header.keyLen, (unsigned)tfile->header.keyLen, 0, &tfile->vfpInfo ) ;
|
|
#else
|
|
rc = (*tfile->cmp)( buf, tfile4key( tfile ), tfile->header.keyLen ) ;
|
|
#endif
|
|
rc2 = d4seekCheck( data, tfile, rc, buf, tfile->header.keyLen ) ; /* return a valid value */
|
|
if ( rc != 0 )
|
|
return r4entry ;
|
|
return rc2 ;
|
|
#endif
|
|
}
|
|
#endif /* S4CB51 */
|
|
|
|
#endif /* S4INDEX_OFF */
|
|
|
|
#ifdef S4VB_DOS
|
|
|
|
int d4seek_v( DATA4 *data, const char *seek )
|
|
{
|
|
return d4seek( data, c4str(seek) ) ;
|
|
}
|
|
|
|
#endif
|