dad4af5ae7
git-svn-id: svn://10.65.10.50/branches/R_10_00@20682 c028cbd2-c16b-5b4b-a496-9718f37d4682
1988 lines
55 KiB
C
Executable File
1988 lines
55 KiB
C
Executable File
/* b4block.c (c)Copyright Sequiter Software Inc., 1990-1994. All rights reserved. */
|
|
|
|
#include "d4all.h"
|
|
#ifndef S4UNIX
|
|
#ifdef __TURBOC__
|
|
#pragma hdrstop
|
|
#endif /* __TURBOC__ */
|
|
#endif /* S4UNIX */
|
|
|
|
#ifndef S4INDEX_OFF
|
|
|
|
#ifdef S4FOX
|
|
#define S4REVERSE_FUNC
|
|
#endif
|
|
#ifdef S4BYTE_SWAP
|
|
#define S4REVERSE_FUNC
|
|
#endif
|
|
|
|
#ifdef S4REVERSE_FUNC
|
|
short S4FUNCTION x4reverse_short( void * val )
|
|
{
|
|
unsigned char out[2], *at_val ;
|
|
at_val = (unsigned char *)val ;
|
|
|
|
out[0] = at_val[1] ;
|
|
out[1] = at_val[0] ;
|
|
|
|
return (*(short *)out ) ;
|
|
}
|
|
|
|
S4LONG S4FUNCTION x4reverse_long( void * val )
|
|
{
|
|
unsigned char out[4], *at_val ;
|
|
at_val = (unsigned char *)val ;
|
|
|
|
#ifdef S4BYTEORDER_2301
|
|
out[0] = at_val[2] ;
|
|
out[1] = at_val[3] ;
|
|
out[2] = at_val[0] ;
|
|
out[3] = at_val[1] ;
|
|
#else
|
|
out[0] = at_val[3] ;
|
|
out[1] = at_val[2] ;
|
|
out[2] = at_val[1] ;
|
|
out[3] = at_val[0] ;
|
|
#endif
|
|
|
|
return *(S4LONG *)out ;
|
|
}
|
|
#endif
|
|
|
|
B4BLOCK * S4FUNCTION b4alloc( TAG4 *t4, long fb )
|
|
{
|
|
B4BLOCK *b4 ;
|
|
#ifdef S4CLIPPER
|
|
short offset ;
|
|
int i ;
|
|
#endif /* S4CLIPPER */
|
|
|
|
b4 = (B4BLOCK *)mem4alloc2( t4->index->block_memory, t4->code_base ) ;
|
|
if ( b4 == 0 )
|
|
{
|
|
e4( t4->code_base, e4memory, E4_B4ALLOC ) ;
|
|
return 0 ;
|
|
}
|
|
|
|
b4->tag = t4 ;
|
|
b4->file_block = fb ;
|
|
|
|
#ifdef S4CLIPPER
|
|
offset = ( b4->tag->header.keys_max + 2 +
|
|
(( b4->tag->header.keys_max / 2) * 2 != b4->tag->header.keys_max ) )
|
|
* sizeof(short) ;
|
|
for ( i = 0 ; i <= b4->tag->header.keys_max ; i++ )
|
|
b4->pointers[i] = (short)(( b4->tag->header.group_len * i )) + offset ;
|
|
b4->data = (B4KEY_DATA *) ((char *)&b4->n_keys + b4->pointers[0]) ; /* first entry */
|
|
#endif /* S4CLIPPER */
|
|
|
|
#ifdef S4FOX
|
|
b4->built_key = (B4KEY_DATA *)u4alloc_er( t4->code_base, sizeof(long) + t4->header.key_len + 1 ) ;
|
|
b4->built_on = -1 ;
|
|
#endif /* S4FOX */
|
|
|
|
return b4 ;
|
|
}
|
|
|
|
void S4FUNCTION b4free( B4BLOCK *b4 )
|
|
{
|
|
#ifdef S4FOX
|
|
#ifdef S4DEBUG
|
|
if ( b4->changed )
|
|
e4severe( e4info, E4_B4FREE ) ;
|
|
#endif /* S4DEBUG */
|
|
u4free( b4->built_key ) ;
|
|
#endif /* S4FOX */
|
|
|
|
mem4free( b4->tag->index->block_memory, b4 ) ;
|
|
}
|
|
|
|
#ifdef S4NDX
|
|
|
|
#ifndef S4OFF_WRITE
|
|
int S4FUNCTION b4find( TAG4 *tag, long f_block, B4BLOCK *out_block )
|
|
{
|
|
B4BLOCK *cur_block ;
|
|
|
|
cur_block = (B4BLOCK *)l4first( &tag->blocks ) ;
|
|
if ( cur_block != 0 )
|
|
do
|
|
{
|
|
if ( cur_block->file_block == f_block )
|
|
{
|
|
memcpy( &(out_block->changed), &(cur_block->changed), (B4BLOCK_SIZE + 2*sizeof(int)) ) ;
|
|
out_block->changed = 0 ;
|
|
return( 0 ) ;
|
|
}
|
|
cur_block = (B4BLOCK *)l4next( &tag->blocks, cur_block ) ;
|
|
} while ( cur_block != 0 ) ;
|
|
|
|
cur_block = (B4BLOCK *)l4first( &tag->saved ) ;
|
|
|
|
if ( cur_block != 0 )
|
|
do
|
|
{
|
|
if ( cur_block->file_block == f_block )
|
|
{
|
|
memcpy( &(out_block->changed), &(cur_block->changed), (B4BLOCK_SIZE + 2*sizeof(int)) ) ;
|
|
out_block->changed = 0 ;
|
|
return 0 ;
|
|
}
|
|
cur_block = (B4BLOCK *)l4next( &tag->saved, cur_block ) ;
|
|
} while ( cur_block != 0 ) ;
|
|
|
|
return -1 ;
|
|
}
|
|
|
|
int S4FUNCTION b4get_last_key( B4BLOCK *b4, char *key_info )
|
|
{
|
|
int rc ;
|
|
long block_down ;
|
|
B4BLOCK *temp_block ;
|
|
char *key_data ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( b4leaf( b4 ) )
|
|
e4severe( e4info, E4_B4GET_LK ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
block_down = b4key( b4, b4->key_on )->pointer ;
|
|
|
|
temp_block = b4alloc( b4->tag, block_down ) ;
|
|
if ( temp_block == 0 )
|
|
return -1 ;
|
|
|
|
do
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( block_down <= 0L )
|
|
e4severe( e4info, E4_B4GET_LK ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
if ( b4find( b4->tag, block_down, temp_block ) < 0 )
|
|
{
|
|
if ( file4len( &b4->tag->file ) <= I4MULTIPLY * block_down )
|
|
{
|
|
b4free(temp_block) ;
|
|
return -1 ;
|
|
}
|
|
else
|
|
{
|
|
if ( file4read_all( &b4->tag->file, I4MULTIPLY * block_down, &temp_block->n_keys, B4BLOCK_SIZE ) < 0 )
|
|
{
|
|
b4free(temp_block) ;
|
|
return -1 ;
|
|
}
|
|
temp_block->file_block = block_down ;
|
|
}
|
|
}
|
|
|
|
temp_block->key_on = b4lastpos( temp_block ) ;
|
|
block_down = b4key( temp_block, temp_block->key_on )->pointer ;
|
|
} while( !( b4leaf( temp_block ) ) ) ;
|
|
|
|
key_data = (char *)b4key_key( temp_block, temp_block->key_on ) ;
|
|
|
|
if( strcmp( key_info, key_data ) != 0 )
|
|
{
|
|
strcpy( key_info, key_data ) ;
|
|
rc = 1 ;
|
|
}
|
|
else
|
|
rc = 0 ;
|
|
|
|
b4free( temp_block ) ;
|
|
|
|
return rc ;
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
#endif /* S4NDX */
|
|
|
|
#ifdef S4MDX
|
|
|
|
/* S4MDX */
|
|
#ifndef S4OFF_WRITE
|
|
int S4FUNCTION b4flush( B4BLOCK *b4 )
|
|
{
|
|
int rc ;
|
|
INDEX4 *i4 ;
|
|
#ifdef S4BYTE_SWAP
|
|
char *swap, *swap_ptr ;
|
|
int i ;
|
|
S4LONG long_val ;
|
|
short short_val ;
|
|
#endif /* S4BYTE_SWAP */
|
|
|
|
if ( b4->changed )
|
|
{
|
|
#ifdef S4INDEX_VERIFY
|
|
if ( b4verify( b4 ) == -1 )
|
|
e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4flush()", "" ) ;
|
|
#endif
|
|
i4 = b4->tag->index ;
|
|
|
|
#ifdef S4BYTE_SWAP
|
|
swap = (char *) u4alloc_er( b4->tag->code_base, b4->tag->index->header.block_rw ) ;
|
|
if ( swap == 0 )
|
|
return -1 ;
|
|
|
|
memcpy( (void *)swap, (void *)&b4->n_keys, b4->tag->index->header.block_rw ) ;
|
|
/* position swap_ptr at beginning of B4KEY's */
|
|
swap_ptr = swap ;
|
|
swap_ptr += 6 + sizeof(short) ;
|
|
/* move through all B4KEY's to swap 'long' */
|
|
for ( i = 0 ; i < (*(short *)swap) ; i++ )
|
|
{
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ;
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
swap_ptr += b4->tag->header.group_len ;
|
|
}
|
|
/* mark last_pointer */
|
|
if ( !b4leaf( b4 ) )
|
|
{
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ;
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
}
|
|
/* swap the num_keys value */
|
|
short_val = x4reverse_short( (void *)swap ) ;
|
|
memcpy( swap, (void *) &short_val, sizeof(short) ) ;
|
|
|
|
rc = file4write( &i4->file, (long)b4->file_block*I4MULTIPLY, swap, i4->header.block_rw) ;
|
|
u4free( swap ) ;
|
|
#else
|
|
rc = file4write( &i4->file, (long)b4->file_block*I4MULTIPLY, &b4->n_keys, i4->header.block_rw) ;
|
|
#endif /* S4BYTE_SWAP */
|
|
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
b4->changed = 0 ;
|
|
}
|
|
return 0 ;
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
/* S4MDX */
|
|
void S4FUNCTION b4go_eof( B4BLOCK *b4 )
|
|
{
|
|
b4->key_on = b4->n_keys ;
|
|
}
|
|
|
|
/* S4MDX */
|
|
#ifndef S4OFF_WRITE
|
|
void S4FUNCTION b4insert( B4BLOCK *b4, void *k, long r )
|
|
{
|
|
#ifdef S464BIT
|
|
S4LONG temp_r ;
|
|
#endif
|
|
int left_len ;
|
|
B4KEY_DATA *data_ptr, *next_ptr ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( k == 0 || r <= 0L )
|
|
e4severe( e4parm, E4_B4INSERT ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
data_ptr = b4key( b4, b4->key_on ) ;
|
|
next_ptr = b4key( b4, b4->key_on+1 ) ;
|
|
left_len = b4->tag->index->header.block_rw - ( b4->key_on + 1 ) * b4->tag->header.group_len - sizeof(short) - sizeof(char[6]) ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( b4->key_on < 0 || b4->key_on > b4->n_keys || left_len < 0 )
|
|
e4severe( e4info, E4_B4INSERT ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
memmove( next_ptr, data_ptr, left_len ) ;
|
|
b4->n_keys++ ;
|
|
memcpy( data_ptr->value, k, b4->tag->header.key_len ) ;
|
|
#ifdef S464BIT
|
|
temp_r = (S4LONG) r ;
|
|
memcpy( (void *)&data_ptr->num, (void *)&temp_r, sizeof(temp_r) ) ;
|
|
#else
|
|
memcpy( (void *)&data_ptr->num, (void *)&r, sizeof(r) ) ;
|
|
#endif
|
|
b4->changed = 1 ;
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
/* S4MDX */
|
|
B4KEY_DATA *S4FUNCTION b4key( B4BLOCK *b4, int i_key )
|
|
{
|
|
return (B4KEY_DATA *) ((char *) &b4->info.num + b4->tag->header.group_len * i_key) ;
|
|
}
|
|
|
|
/* S4MDX */
|
|
unsigned char *S4FUNCTION b4key_key( B4BLOCK *b4, int i_key )
|
|
{
|
|
return (unsigned char *)( ( (B4KEY_DATA *)( (char *)&b4->info.num + b4->tag->header.group_len * i_key ) )->value ) ;
|
|
}
|
|
|
|
/* S4MDX */
|
|
int S4FUNCTION b4lastpos( B4BLOCK *b4 )
|
|
{
|
|
if ( b4leaf(b4) )
|
|
return b4->n_keys - 1 ;
|
|
else
|
|
return b4->n_keys ;
|
|
}
|
|
|
|
/* S4MDX */
|
|
int S4FUNCTION b4leaf( B4BLOCK *b4 )
|
|
{
|
|
return( b4key( b4, b4->n_keys )->num == 0L ) ;
|
|
}
|
|
|
|
/* S4MDX */
|
|
long S4FUNCTION b4recno( B4BLOCK *b4, int i )
|
|
{
|
|
return b4key( b4, i )->num ;
|
|
}
|
|
|
|
/* S4MDX */
|
|
#ifndef S4OFF_WRITE
|
|
void S4FUNCTION b4remove( B4BLOCK *b4 )
|
|
{
|
|
B4KEY_DATA *key_cur, *key_next ;
|
|
int left_len ;
|
|
|
|
key_cur = b4key( b4, b4->key_on ) ;
|
|
key_next = b4key( b4, b4->key_on + 1 ) ;
|
|
|
|
left_len = b4->tag->index->header.block_rw - sizeof(b4->n_keys) - sizeof(b4->dummy)
|
|
- (b4->key_on+1) * b4->tag->header.group_len ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( b4->key_on < 0 || b4->key_on > b4lastpos(b4) )
|
|
e4severe( e4info, E4_B4REMOVE ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
if ( left_len > 0 )
|
|
memmove( key_cur, key_next, left_len ) ;
|
|
|
|
b4->n_keys-- ;
|
|
b4->changed = 1 ;
|
|
|
|
if ( b4leaf( b4 ) )
|
|
memset( b4key_key( b4, b4->n_keys ), 0, b4->tag->header.key_len ) ;
|
|
#ifdef S4DEBUG
|
|
else
|
|
if ( b4->n_keys < b4->tag->header.keys_max )
|
|
memset( b4key_key( b4, b4->n_keys ), 0, b4->tag->header.key_len ) ;
|
|
#endif
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
/* S4MDX */
|
|
int S4FUNCTION b4seek( B4BLOCK *b4, char *search_value, int len )
|
|
{
|
|
int rc, key_lower, key_upper, save_rc, key_cur ;
|
|
S4CMP_FUNCTION *cmp;
|
|
|
|
/* key_cur must be between key_lower and key_upper */
|
|
key_lower = -1 ;
|
|
key_upper = b4->n_keys ;
|
|
|
|
cmp = b4->tag->cmp ;
|
|
|
|
if ( key_upper == 0 )
|
|
{
|
|
b4->key_on = 0 ;
|
|
return r4after ;
|
|
}
|
|
|
|
save_rc = 1 ;
|
|
|
|
for(;;) /* Repeat until the key is found */
|
|
{
|
|
key_cur = (key_upper + key_lower) / 2 ;
|
|
rc = (*cmp)( b4key_key(b4,key_cur), search_value, len ) ;
|
|
|
|
if ( rc >= 0 )
|
|
{
|
|
key_upper = key_cur ;
|
|
save_rc = rc ;
|
|
}
|
|
else
|
|
key_lower = key_cur ;
|
|
|
|
if ( key_lower >= (key_upper-1) ) /* then there is no exact match */
|
|
{
|
|
b4->key_on = key_upper ;
|
|
if ( save_rc )
|
|
return r4after ;
|
|
return 0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* S4MDX */
|
|
int S4FUNCTION b4skip( B4BLOCK *b4, long n )
|
|
{
|
|
int num_left ;
|
|
|
|
if ( n > 0 )
|
|
{
|
|
num_left = b4->n_keys - b4->key_on ;
|
|
if ( b4leaf(b4) )
|
|
if ( num_left != 0 )
|
|
num_left -- ;
|
|
}
|
|
else
|
|
num_left = -b4->key_on ;
|
|
|
|
if ( ( n <= 0L ) ? ((long) num_left <= n) : ((long) num_left >= n) )
|
|
{
|
|
b4->key_on = b4->key_on+ (int)n ;
|
|
return (int)n ;
|
|
}
|
|
else
|
|
{
|
|
b4->key_on = b4->key_on + num_left ;
|
|
return num_left ;
|
|
}
|
|
}
|
|
#endif /* S4MDX */
|
|
|
|
#ifdef S4FOX
|
|
|
|
/* S4FOX */
|
|
void S4FUNCTION b4leaf_init( B4BLOCK *b4 )
|
|
{
|
|
TAG4 *t4 ;
|
|
int t_len ;
|
|
unsigned c_len, key_len ;
|
|
unsigned long ff, r_len ;
|
|
|
|
t4 = b4->tag ;
|
|
key_len = t4->header.key_len ;
|
|
ff = 0xFFFFFFFF ;
|
|
|
|
for ( c_len = 0 ; key_len ; key_len >>= 1, c_len++ ) ;
|
|
|
|
key_len = t4->header.key_len ;
|
|
b4->node_hdr.trail_cnt_len = b4->node_hdr.dup_cnt_len = (unsigned char)c_len ;
|
|
|
|
b4->node_hdr.trail_byte_cnt = (unsigned char)((unsigned char)0xFF >> (8 - c_len % 8) ) ;
|
|
b4->node_hdr.dup_byte_cnt = b4->node_hdr.trail_byte_cnt ;
|
|
|
|
r_len = d4reccount( b4->tag->index->data ) ;
|
|
|
|
for ( c_len = 0 ; r_len ; r_len>>=1, c_len++ ) ;
|
|
|
|
b4->node_hdr.rec_num_len = (unsigned char) (c_len + (( 8 - ( 2 * (unsigned int)b4->node_hdr.trail_cnt_len % 8 )) % 8)) ;
|
|
if ( b4->node_hdr.rec_num_len < 12 )
|
|
b4->node_hdr.rec_num_len = 12 ;
|
|
|
|
for( t_len = b4->node_hdr.rec_num_len + b4->node_hdr.trail_cnt_len + b4->node_hdr.dup_cnt_len ;
|
|
(t_len / 8)*8 != t_len ; t_len++, b4->node_hdr.rec_num_len++ ) ; /* make at an 8-bit offset */
|
|
|
|
r_len = ff >> ( sizeof(long)*8 - b4->node_hdr.rec_num_len ) ;
|
|
memcpy( (void *)&b4->node_hdr.rec_num_mask[0], (void *)&r_len, sizeof(long) ) ;
|
|
|
|
b4->node_hdr.info_len = (unsigned char)((unsigned int)(b4->node_hdr.rec_num_len + b4->node_hdr.trail_cnt_len + b4->node_hdr.dup_cnt_len) / 8) ;
|
|
b4->node_hdr.free_space = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - sizeof( B4NODE_HEADER ) ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4calc_blanks( char *key_val, int len, char p_char )
|
|
{
|
|
int a ;
|
|
|
|
for ( a = len ; a > 0; a-- )
|
|
if ( key_val[a-1] != p_char )
|
|
return ( len - a ) ;
|
|
return len ; /* all blanks */
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4calc_dups( char *ptr1, char *ptr2, int len )
|
|
{
|
|
int a ;
|
|
for ( a = 0 ; a < len; a++ )
|
|
if ( ptr1[a] != ptr2[a] )
|
|
return a ;
|
|
return len ; /* all duplicates */
|
|
}
|
|
|
|
|
|
/* S4FOX */
|
|
long S4FUNCTION x4recno( B4BLOCK *b4, int num_in_block )
|
|
{
|
|
#ifdef S4UNIX
|
|
unsigned long long_ptr ;
|
|
unsigned long long_val ;
|
|
|
|
memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len , sizeof(long) ) ;
|
|
#ifdef S4DO_BYTEORDER
|
|
long_ptr = x4reverse_long( (void *)&long_ptr ) ;
|
|
#endif
|
|
|
|
memcpy( (void *)&long_val , (void *)&b4->node_hdr.rec_num_mask[0], sizeof(long) ) ;
|
|
return ( long_ptr & long_val ) ;
|
|
#else
|
|
unsigned long * l_ptr ;
|
|
|
|
l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len ) ;
|
|
return ( *l_ptr & *(long *)&b4->node_hdr.rec_num_mask[0] ) ;
|
|
#endif
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION x4dup_cnt( B4BLOCK *b4, int num_in_block )
|
|
{
|
|
int pos ;
|
|
#ifdef S4UNIX
|
|
unsigned long long_ptr ;
|
|
#else
|
|
unsigned long * l_ptr ;
|
|
#endif
|
|
|
|
if ( b4->node_hdr.info_len > 4 ) /* > size of long, so must do careful shifting and copying */
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( b4->node_hdr.rec_num_len <= 16 )
|
|
e4severe( e4info, E4_INFO_CIB ) ;
|
|
#endif /* S4DEBUG */
|
|
#ifdef S4UNIX
|
|
memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len + 2, sizeof(long) ) ;
|
|
#else
|
|
l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len + 2 ) ;
|
|
#endif
|
|
pos = b4->node_hdr.rec_num_len - 16 ;
|
|
}
|
|
else
|
|
{
|
|
#ifdef S4UNIX
|
|
memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len , sizeof(long) ) ;
|
|
#else
|
|
l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len ) ;
|
|
#endif
|
|
pos = b4->node_hdr.rec_num_len ;
|
|
}
|
|
|
|
#ifdef S4UNIX
|
|
#ifdef S4DO_BYTEORDER
|
|
long_ptr = x4reverse_long( (void *)&long_ptr ) ;
|
|
#endif
|
|
return (int)( ( long_ptr >> pos ) & b4->node_hdr.dup_byte_cnt ) ;
|
|
#else
|
|
return (int)( ( *l_ptr >> pos ) & b4->node_hdr.dup_byte_cnt ) ;
|
|
#endif
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION x4trail_cnt( B4BLOCK *b4, int num_in_block )
|
|
{
|
|
int pos ;
|
|
#ifdef S4UNIX
|
|
unsigned long long_ptr ;
|
|
#else
|
|
unsigned long * l_ptr ;
|
|
#endif
|
|
|
|
if ( b4->node_hdr.info_len > 4 ) /* > size of long, so must do careful shifting and copying */
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( b4->node_hdr.rec_num_len <= 16 )
|
|
e4severe( e4info, E4_INFO_CIB ) ;
|
|
#endif /* S4DEBUG */
|
|
#ifdef S4UNIX
|
|
memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len + 2, sizeof(long) ) ;
|
|
#else
|
|
l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len + 2 ) ;
|
|
#endif
|
|
pos = b4->node_hdr.rec_num_len - 16 + b4->node_hdr.dup_cnt_len ;
|
|
}
|
|
else
|
|
{
|
|
#ifdef S4UNIX
|
|
memcpy( (void *)&long_ptr , b4->data + num_in_block * b4->node_hdr.info_len , sizeof(long) ) ;
|
|
#else
|
|
l_ptr = (unsigned long *)( b4->data + num_in_block * b4->node_hdr.info_len ) ;
|
|
#endif
|
|
pos = b4->node_hdr.rec_num_len + b4->node_hdr.dup_cnt_len;
|
|
}
|
|
|
|
#ifdef S4UNIX
|
|
#ifdef S4DO_BYTEORDER
|
|
long_ptr = x4reverse_long( (void *)&long_ptr ) ;
|
|
#endif
|
|
return (int)( ( long_ptr >> pos ) & b4->node_hdr.trail_byte_cnt ) ;
|
|
#else
|
|
return (int)( ( *l_ptr >> pos ) & b4->node_hdr.trail_byte_cnt ) ;
|
|
#endif
|
|
}
|
|
|
|
|
|
/* S4FOX */
|
|
#ifndef S4OFF_WRITE
|
|
|
|
void S4FUNCTION x4put_info( B4NODE_HEADER *b4node_hdr, void *buffer, long rec, int trail, int dup_cnt )
|
|
{
|
|
int pos ;
|
|
unsigned char *buf ;
|
|
unsigned long *l_ptr ;
|
|
#ifdef S4UNIX
|
|
char unix_buf[6] ;
|
|
char unix_buf2[4] ;
|
|
long long_val, long_temp ;
|
|
int do_shift = 0 ;
|
|
#endif
|
|
|
|
#ifdef S4UNIX
|
|
memset( unix_buf, 0, 6 ) ;
|
|
memcpy( (void *)&long_temp , (void *)&b4node_hdr->rec_num_mask[0], sizeof(long) ) ;
|
|
long_val = rec & long_temp ;
|
|
#ifdef S4DO_BYTEORDER
|
|
long_val = x4reverse_long( (void *)&long_val ) ;
|
|
#endif
|
|
memcpy( unix_buf, (void *)&long_val, sizeof(long) ) ;
|
|
#else
|
|
buf = (unsigned char *) buffer ;
|
|
l_ptr = (unsigned long *)buf ;
|
|
memset( buf, 0, 6 ) ;
|
|
*l_ptr = rec & *(long *)&b4node_hdr->rec_num_mask[0] ;
|
|
#endif
|
|
|
|
if ( b4node_hdr->info_len > 4 ) /* > size of long, so must do careful shifting and copying */
|
|
{
|
|
#ifdef S4DEBUG
|
|
if ( b4node_hdr->rec_num_len <= 16 )
|
|
e4severe( e4info, E4_INFO_CIB ) ;
|
|
#endif /* S4DEBUG */
|
|
#ifndef S4UNIX
|
|
l_ptr = (unsigned long *)( buf + 2 ) ; /* start at new pos */
|
|
#endif
|
|
pos = b4node_hdr->rec_num_len - 16 ;
|
|
#ifdef S4UNIX
|
|
do_shift = 1 ;
|
|
#endif
|
|
}
|
|
else
|
|
pos = b4node_hdr->rec_num_len ;
|
|
|
|
#ifdef S4UNIX
|
|
long_val = ((unsigned long)dup_cnt) << pos ;
|
|
pos += b4node_hdr->dup_cnt_len ;
|
|
long_val |= ((unsigned long)trail) << pos ;
|
|
#ifdef S4DO_BYTEORDER
|
|
long_val = x4reverse_long( (void *)&long_val ) ;
|
|
#endif
|
|
memcpy( unix_buf2, (void *)&long_val, sizeof(long) ) ;
|
|
if (do_shift)
|
|
{
|
|
unix_buf[2] |= unix_buf2[0] ; /* must OR bytes 2 and 3 of 'buf' */
|
|
unix_buf[3] |= unix_buf2[1] ;
|
|
unix_buf[4] = unix_buf2[2] ;
|
|
unix_buf[5] = unix_buf2[3] ;
|
|
}
|
|
else
|
|
{
|
|
unix_buf[0] |= unix_buf2[0] ;
|
|
unix_buf[1] |= unix_buf2[1] ;
|
|
unix_buf[2] |= unix_buf2[2] ;
|
|
unix_buf[3] |= unix_buf2[3] ;
|
|
}
|
|
memcpy( (void *)buffer, unix_buf, 6 ) ;
|
|
#else
|
|
*l_ptr |= ((unsigned long)dup_cnt) << pos ;
|
|
pos += b4node_hdr->dup_cnt_len ;
|
|
*l_ptr |= ((unsigned long)trail) << pos ;
|
|
#endif
|
|
}
|
|
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4insert_leaf( B4BLOCK *b4, void *vkey_data, long rec )
|
|
{
|
|
int left_blanks, right_blanks, left_dups, right_dups, left_len, right_len, reqd_len, mov_len, old_rec, rc, old_right_dups, extra_dups, save_dups ;
|
|
unsigned char buffer[6], i_len ;
|
|
char *key_data, *info_pos, a, b ;
|
|
int key_len ;
|
|
unsigned int rec_len ;
|
|
unsigned long mask ;
|
|
#ifdef S4UNIX
|
|
long long_val ;
|
|
#endif
|
|
|
|
i_len = b4->node_hdr.info_len ;
|
|
key_data = (char *)vkey_data ;
|
|
key_len = b4->tag->header.key_len ;
|
|
b4->built_on = -1 ;
|
|
|
|
if ( b4->header.n_keys == 0 )
|
|
{
|
|
if( b4->node_hdr.free_space == 0 ) /* block needs initialization */
|
|
{
|
|
b4leaf_init( b4 ) ;
|
|
i_len = b4->node_hdr.info_len ;
|
|
}
|
|
left_blanks = b4calc_blanks( key_data, key_len, b4->tag->p_char ) ;
|
|
left_dups = 0 ;
|
|
reqd_len = key_len - left_blanks ;
|
|
b4->key_on = 0 ;
|
|
b4->cur_pos = ((char *)&b4->header) + B4BLOCK_SIZE - reqd_len ;
|
|
memcpy( b4->cur_pos, key_data, reqd_len ) ; /* key */
|
|
x4put_info( &b4->node_hdr, buffer, rec, left_blanks, 0 ) ;
|
|
memcpy( b4->data, (void *)buffer, i_len ) ;
|
|
}
|
|
else
|
|
{
|
|
/* 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( rec_len = 0, a = 0 ; a < b ; a++ )
|
|
{
|
|
if ( rec & mask )
|
|
{
|
|
rec_len = b - a ;
|
|
break ;
|
|
}
|
|
mask >>= 1 ;
|
|
}
|
|
|
|
if ( rec_len > b4->node_hdr.rec_num_len )
|
|
{
|
|
old_rec = b4->key_on ;
|
|
save_dups = b4->cur_dup_cnt ;
|
|
rc = b4reindex( b4 ) ;
|
|
if (rc )
|
|
return rc ;
|
|
i_len = b4->node_hdr.info_len ;
|
|
b4top( b4 ) ;
|
|
b4skip( b4, old_rec ) ;
|
|
b4->cur_dup_cnt = save_dups ;
|
|
}
|
|
|
|
left_blanks = b4calc_blanks( key_data, key_len, b4->tag->p_char ) ;
|
|
|
|
if ( b4->key_on == b4->header.n_keys ) /* at end */
|
|
{
|
|
left_dups = b4->cur_dup_cnt ;
|
|
reqd_len = key_len - left_blanks - b4->cur_dup_cnt ;
|
|
if ( (int)b4->node_hdr.free_space < ( reqd_len + (int)i_len ) ) /* no room to add */
|
|
return 1 ;
|
|
b4->cur_pos -= reqd_len ;
|
|
memcpy( b4->cur_pos, key_data + b4->cur_dup_cnt, reqd_len ) ; /* key */
|
|
x4put_info( &b4->node_hdr, buffer, rec, left_blanks, left_dups ) ;
|
|
memcpy( b4->data + b4->key_on * i_len , (void *)buffer, i_len ) ;
|
|
}
|
|
else
|
|
{
|
|
right_blanks = x4trail_cnt( b4, b4->key_on ) ;
|
|
|
|
if ( b4->key_on == 0 ) /* insert at top */
|
|
{
|
|
old_right_dups = 0 ;
|
|
right_dups = b4calc_dups( key_data, b4->cur_pos, key_len - ( right_blanks > left_blanks ? right_blanks : left_blanks ) ) ;
|
|
extra_dups = right_dups ;
|
|
left_dups = 0 ;
|
|
}
|
|
else /* insert in middle of block */
|
|
{
|
|
old_right_dups = x4dup_cnt( b4, b4->key_on) ;
|
|
extra_dups = b4calc_dups( key_data + old_right_dups, b4->cur_pos, key_len - ( right_blanks > left_blanks ? right_blanks : left_blanks ) - old_right_dups ) ;
|
|
right_dups = old_right_dups + extra_dups ;
|
|
left_dups = b4->cur_dup_cnt ;
|
|
}
|
|
|
|
#ifdef S4DEBUG_DEV
|
|
if ( b4->tag->header.type_code & 0x01 )
|
|
if ( left_dups == b4->tag->header.key_len || right_dups == b4->tag->header.key_len )
|
|
e4severe( e4info, "b4insert_leaf() - duplicate key being inserted in unique index" ) ;
|
|
#endif
|
|
|
|
right_len = key_len - right_blanks - right_dups ;
|
|
left_len = key_len - left_dups - left_blanks ;
|
|
reqd_len = left_len - extra_dups ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( reqd_len < 0 )
|
|
e4severe( e4info, E4_INFO_CIB ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
if ( (int)b4->node_hdr.free_space < (reqd_len + (int)i_len) ) /* no room to add */
|
|
return 1 ;
|
|
|
|
|
|
if ( reqd_len != 0 ) /* shift data over */
|
|
{
|
|
mov_len = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - i_len * b4->header.n_keys
|
|
- sizeof( B4NODE_HEADER ) - b4->node_hdr.free_space
|
|
- ( ( (char *)&b4->header ) + B4BLOCK_SIZE - b4->cur_pos ) ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( mov_len < 0 )
|
|
e4severe( e4info, E4_INFO_CIB ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
/* move and put keys */
|
|
memmove( b4->cur_pos - mov_len - reqd_len, b4->cur_pos - mov_len, mov_len ) ;
|
|
}
|
|
b4->cur_pos += ( key_len - right_blanks - old_right_dups ) ;
|
|
memcpy( b4->cur_pos - left_len - right_len, b4->cur_pos - ( key_len - right_dups - right_blanks ), right_len ) ;
|
|
b4->cur_pos -= left_len ;
|
|
memcpy( b4->cur_pos, key_data + left_dups, left_len ) ;
|
|
|
|
/* move and put info */
|
|
info_pos = b4->data + ( b4->key_on ) * i_len ;
|
|
memmove( info_pos + i_len, info_pos ,i_len * ( b4->header.n_keys - b4->key_on ) ) ;
|
|
x4put_info( &b4->node_hdr, buffer, rec, left_blanks, left_dups ) ;
|
|
memcpy( info_pos, (void *)buffer, i_len ) ;
|
|
x4put_info( &b4->node_hdr, buffer, x4recno( b4, b4->key_on + 1 ), right_blanks, right_dups ) ;
|
|
memcpy( info_pos + i_len, (void *)buffer, i_len ) ;
|
|
}
|
|
}
|
|
|
|
b4->changed = 1 ;
|
|
b4->header.n_keys++ ;
|
|
b4->node_hdr.free_space -= (short) (reqd_len + (int)i_len ) ;
|
|
b4->cur_dup_cnt = left_dups ;
|
|
b4->cur_trail_cnt = left_blanks ;
|
|
return 0 ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4insert_branch( B4BLOCK *b4, void *k, long r, long r2, char new_flag )
|
|
{
|
|
int left_len, move_len, g_len ;
|
|
char *data_ptr, *next_ptr ;
|
|
|
|
g_len = b4->tag->header.key_len + 2 * sizeof(long) ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( k == 0 || r <= 0L )
|
|
e4severe( e4parm, E4_B4INSERT_BR ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
data_ptr = ((char *)&b4->node_hdr) + b4->key_on * g_len ;
|
|
next_ptr = data_ptr + g_len ;
|
|
|
|
left_len = B4BLOCK_SIZE - sizeof( b4->header ) - g_len * b4->header.n_keys ;
|
|
if ( left_len < g_len ) /* not enough room */
|
|
return 1 ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( b4->key_on < 0 || b4->key_on > b4->header.n_keys )
|
|
e4severe( e4info, E4_B4INSERT_BR ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
move_len = g_len * (b4->header.n_keys - b4->key_on) ;
|
|
|
|
memmove( next_ptr, data_ptr, move_len ) ;
|
|
b4->header.n_keys++ ;
|
|
memcpy( data_ptr, k, b4->tag->header.key_len ) ;
|
|
memset( data_ptr + g_len - 2*sizeof(long), 0, sizeof(long) ) ;
|
|
|
|
r2 = x4reverse_long( (void *)&r2 ) ;
|
|
memcpy( data_ptr + g_len - 2*sizeof(long), (void *)&r2, sizeof(long) ) ;
|
|
|
|
r = x4reverse_long( (void *)&r ) ;
|
|
|
|
if ( !new_flag && (b4->key_on + 1) != b4->header.n_keys )
|
|
memcpy( next_ptr + g_len - sizeof(long), (void *)&r, sizeof(long) ) ;
|
|
else
|
|
memcpy( data_ptr + g_len - sizeof(long), (void *)&r, sizeof(long) ) ;
|
|
|
|
b4->changed = 1 ;
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4insert( B4BLOCK *b4, void *key_data, long rec, long rec2, char new_flag )
|
|
{
|
|
if( b4->header.node_attribute >= 2 ) /* leaf */
|
|
return b4insert_leaf( b4, key_data, rec ) ;
|
|
else
|
|
return b4insert_branch( b4, key_data, rec, rec2, new_flag ) ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4reindex( B4BLOCK *b4 )
|
|
{
|
|
int i, dup_cnt, trail ;
|
|
int ni_len = b4->node_hdr.info_len + 1 ;
|
|
unsigned char buffer[6] ;
|
|
long rec ;
|
|
int space_reqd = b4->header.n_keys ; /* 1 byte extra for each record */
|
|
if ( space_reqd > b4->node_hdr.free_space ) /* not enough room */
|
|
return 1 ;
|
|
|
|
for ( i = b4->header.n_keys-1 ; i >= 0 ; i-- )
|
|
{
|
|
dup_cnt = x4dup_cnt( b4, i ) ;
|
|
trail = x4trail_cnt( b4, i ) ;
|
|
rec = x4recno( b4, i ) ;
|
|
memset( b4->data + i * ni_len, 0, ni_len ) ;
|
|
|
|
b4->node_hdr.rec_num_len += 8 ; /* for the new info */
|
|
b4->node_hdr.info_len++ ;
|
|
x4put_info( &b4->node_hdr, buffer, rec, trail, dup_cnt ) ;
|
|
b4->node_hdr.rec_num_len -= 8 ; /* to get the old info */
|
|
b4->node_hdr.info_len-- ;
|
|
memcpy( b4->data + i * ni_len, (void *)buffer, ni_len ) ;
|
|
}
|
|
|
|
memcpy( (void *)&rec, (void *)&b4->node_hdr.rec_num_mask[0], sizeof(long) ) ;
|
|
rec |= (0x000000FFL << b4->node_hdr.rec_num_len ) ;
|
|
memcpy( (void *)&b4->node_hdr.rec_num_mask[0], (void *)&rec, sizeof(long) ) ;
|
|
|
|
b4->node_hdr.info_len++ ;
|
|
b4->node_hdr.rec_num_len += 8 ;
|
|
b4->node_hdr.free_space -= b4->header.n_keys ;
|
|
return 0 ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4flush( B4BLOCK *b4 )
|
|
{
|
|
int rc ;
|
|
INDEX4 *i4 ;
|
|
#ifdef S4BYTE_SWAP
|
|
char swap[B4BLOCK_SIZE] ;
|
|
char *swap_ptr ;
|
|
int i ;
|
|
S4LONG long_val ;
|
|
short short_val ;
|
|
#endif
|
|
|
|
if ( b4->changed )
|
|
{
|
|
i4 = b4->tag->index ;
|
|
|
|
#ifdef S4BYTE_SWAP
|
|
memcpy( (void *)swap, (void *)&b4->header.node_attribute, B4BLOCK_SIZE ) ;
|
|
|
|
/* position at either B4NODE_HEADER (leaf) or data (branch) */
|
|
swap_ptr = swap + 2 * sizeof( short) + 2 * sizeof(S4LONG) ;
|
|
|
|
/* if block is a leaf */
|
|
if (b4->header.node_attribute >= 2 )
|
|
{
|
|
/* swap B4NODE_HEADER members */
|
|
short_val = x4reverse_short( (void *)swap_ptr ) ; /* free_space */
|
|
memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
|
|
swap_ptr += sizeof(short) ;
|
|
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ; /* rec_num_mask */
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
}
|
|
else /* if block is a branch */
|
|
{
|
|
short_val = b4->tag->header.key_len + sizeof(S4LONG) ;
|
|
|
|
/* position swap_ptr to end of first key expression */
|
|
swap_ptr += b4->tag->header.key_len ;
|
|
|
|
/* move through all B4KEY's to swap 'long's */
|
|
for ( i = 0 ; i < (int) b4->header.n_keys ; i++ )
|
|
{
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ;
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
swap_ptr += sizeof(S4LONG) ;
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ;
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
swap_ptr += short_val ;
|
|
}
|
|
}
|
|
|
|
/* reposition to B4STD_HEADER and swap members */
|
|
swap_ptr = swap ;
|
|
|
|
short_val = x4reverse_short( (void *)swap_ptr ) ; /* node_attribute */
|
|
memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
|
|
swap_ptr += sizeof(short) ;
|
|
|
|
short_val = x4reverse_short( (void *)swap_ptr ) ; /* n_keys */
|
|
memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
|
|
swap_ptr += sizeof(short) ;
|
|
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ; /* left_node */
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
swap_ptr += sizeof(S4LONG) ;
|
|
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ; /* right_node */
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
swap_ptr += sizeof(S4LONG) ;
|
|
|
|
rc = file4write( &i4->file, (long)b4->file_block * I4MULTIPLY, swap, B4BLOCK_SIZE ) ;
|
|
#else
|
|
rc = file4write( &i4->file, (long)b4->file_block * I4MULTIPLY, &b4->header.node_attribute, B4BLOCK_SIZE ) ;
|
|
#endif
|
|
|
|
if ( rc < 0 )
|
|
return rc ;
|
|
b4->changed = 0 ;
|
|
}
|
|
return 0 ;
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
/* S4FOX */
|
|
void S4FUNCTION b4go( B4BLOCK *b4, int i_key )
|
|
{
|
|
b4skip( b4, i_key - b4->key_on ) ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
void S4FUNCTION b4top( B4BLOCK *b4 )
|
|
{
|
|
b4->key_on = 0 ;
|
|
if ( b4leaf( b4 ) )
|
|
{
|
|
b4->cur_dup_cnt = 0 ;
|
|
b4->cur_pos = ((char *)&b4->header) + B4BLOCK_SIZE - b4->tag->header.key_len + x4trail_cnt( b4, 0 ) ;
|
|
}
|
|
}
|
|
|
|
/* S4FOX */
|
|
void S4FUNCTION b4go_eof( B4BLOCK *b4 )
|
|
{
|
|
b4->key_on = b4->header.n_keys ;
|
|
b4->cur_pos = ((char *)&b4->header) + sizeof( B4STD_HEADER ) + sizeof( B4NODE_HEADER )
|
|
+ b4->header.n_keys * b4->node_hdr.info_len + b4->node_hdr.free_space ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
B4KEY_DATA *S4FUNCTION b4key( B4BLOCK *b4, int i_key )
|
|
{
|
|
int len ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( i_key > b4->header.n_keys || i_key < 0 )
|
|
e4severe( e4info, E4_INFO_CIF ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
if ( i_key == b4->built_on ) /* already there! */
|
|
return b4->built_key ;
|
|
|
|
if ( b4->header.node_attribute >= 2 ) /* leaf */
|
|
{
|
|
if ( b4->built_on > i_key || b4->built_on == -1 )
|
|
{
|
|
b4->built_on = -1 ;
|
|
b4->built_pos = ((char *)&b4->header) + B4BLOCK_SIZE ;
|
|
}
|
|
|
|
for ( ; b4->built_on != i_key ; )
|
|
{
|
|
b4->built_on++ ;
|
|
b4->cur_dup_cnt = x4dup_cnt( b4, b4->built_on ) ;
|
|
b4->cur_trail_cnt = x4trail_cnt( b4, b4->built_on ) ;
|
|
len = b4->tag->header.key_len - b4->cur_dup_cnt - b4->cur_trail_cnt ;
|
|
#ifdef S4DEBUG
|
|
if (len < 0 || len > b4->tag->header.key_len || ( b4->built_pos - len ) < b4->data )
|
|
e4severe( e4info, E4_INFO_CIF ) ;
|
|
#endif /* S4DEBUG */
|
|
b4->built_pos -= len ;
|
|
memcpy( b4->built_key->value + b4->cur_dup_cnt, b4->built_pos, len ) ;
|
|
memset( b4->built_key->value + b4->tag->header.key_len - b4->cur_trail_cnt, b4->tag->p_char, b4->cur_trail_cnt ) ;
|
|
}
|
|
b4->built_key->num = x4recno( b4, b4->key_on ) ;
|
|
}
|
|
else /* branch */
|
|
{
|
|
memcpy( b4->built_key->value, (((char *)&b4->node_hdr) + i_key*(2*sizeof( long ) + b4->tag->header.key_len ) ), b4->tag->header.key_len ) ;
|
|
b4->built_key->num = x4reverse_long( (void *)( ((unsigned char *)&b4->node_hdr)
|
|
+ (i_key+1)*(2*sizeof(long) + b4->tag->header.key_len)
|
|
- sizeof(long) ) ) ;
|
|
}
|
|
return b4->built_key ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
unsigned char *S4FUNCTION b4key_key( B4BLOCK *b4, int i_key )
|
|
{
|
|
return (unsigned char *)b4key( b4, i_key )->value ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4lastpos( B4BLOCK *b4 )
|
|
{
|
|
return b4->header.n_keys - 1 ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4leaf( B4BLOCK *b4 )
|
|
{
|
|
return( b4->header.node_attribute >= 2 ) ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
long S4FUNCTION b4recno( B4BLOCK *b4, int i )
|
|
{
|
|
if ( b4->header.node_attribute >= 2 ) /* leaf */
|
|
return x4recno( b4, i ) ;
|
|
else /* branch */
|
|
return x4reverse_long( (void *)(((unsigned char *)&b4->node_hdr) +
|
|
i * (2*sizeof(long) + b4->tag->header.key_len) + b4->tag->header.key_len ) ) ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
#ifndef S4OFF_WRITE
|
|
void S4FUNCTION b4br_replace( B4BLOCK *b4, char *str, long rec )
|
|
{
|
|
int key_len ;
|
|
char *put_pl ;
|
|
|
|
key_len = b4->tag->header.key_len ;
|
|
put_pl = ( (char *)&b4->node_hdr ) + b4->key_on * ( 2 * sizeof( long ) + key_len ) ;
|
|
memcpy( put_pl, str, key_len ) ;
|
|
memcpy( b4->built_key->value, str, key_len ) ;
|
|
memset( put_pl + key_len, 0, sizeof(long) ) ;
|
|
rec = x4reverse_long( (void *)&rec ) ;
|
|
memcpy( put_pl + key_len, (void *)&rec, sizeof(long) ) ;
|
|
|
|
b4->changed = 1 ;
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4r_brseek( B4BLOCK *b4, char *search_value, int len, long recno )
|
|
{
|
|
int rc, key_len ;
|
|
#ifdef S4DO_BYTEORDER
|
|
long long_val, lrecno ;
|
|
#endif
|
|
|
|
rc = b4seek( b4, search_value, len ) ;
|
|
key_len = b4->tag->header.key_len ;
|
|
|
|
if ( rc == 0 ) /* string matches, so search on recno */
|
|
for(;;)
|
|
{
|
|
#ifdef S4DO_BYTEORDER
|
|
lrecno = x4reverse_long( (void *)&recno ) ;
|
|
long_val = x4reverse_long( (void *)(((char *)&b4->node_hdr) + b4->key_on * ( 2 * sizeof(long) + key_len) + key_len ) ) ;
|
|
if ( u4memcmp( (void *)&lrecno, (void *)&long_val, sizeof(long) ) <= 0
|
|
#else
|
|
if ( u4memcmp( (void *)&recno, ((char *)&b4->node_hdr) + b4->key_on * ( 2 * sizeof(long) + key_len) + key_len, sizeof(long) ) <= 0
|
|
#endif
|
|
|| b4->key_on >= ( b4->header.n_keys - 1 ) ) /* best match, so done */
|
|
break ;
|
|
else
|
|
if( b4->key_on < b4->header.n_keys )
|
|
b4skip( b4, 1L ) ;
|
|
|
|
if ( u4memcmp( (void *)b4key_key(b4,b4->key_on), search_value, len ) ) /* the key has changed, so stop here */
|
|
break ;
|
|
}
|
|
|
|
return rc ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4seek( B4BLOCK *b4, char *search_value, int len )
|
|
{
|
|
int rc, key_lower, key_upper, save_rc, key_cur, group_val ;
|
|
if ( b4->header.n_keys == 0 )
|
|
{
|
|
b4->key_on = 0 ;
|
|
return r4after ;
|
|
}
|
|
|
|
if ( b4leaf( b4 ) )
|
|
return b4leaf_seek( b4, search_value, len ) ;
|
|
|
|
/* key_cur must be between key_lower and key_upper */
|
|
key_lower = -1 ;
|
|
key_upper = b4->header.n_keys - 1 ;
|
|
|
|
save_rc = 1 ;
|
|
group_val = 2 * sizeof( long ) + b4->tag->header.key_len ;
|
|
|
|
for(;;) /* Repeat until the key is found */
|
|
{
|
|
key_cur = (key_upper + key_lower) / 2 ;
|
|
/* only memcmp for branch blocks */
|
|
rc = u4memcmp( (((char *)&b4->node_hdr) + key_cur * group_val ), search_value, len ) ;
|
|
|
|
if ( rc >= 0 )
|
|
{
|
|
key_upper = key_cur ;
|
|
save_rc = rc ;
|
|
}
|
|
else
|
|
key_lower = key_cur ;
|
|
|
|
if ( key_lower >= (key_upper-1) ) /* then there is no exact match */
|
|
{
|
|
b4->key_on = key_upper ; /* branch block, just change key_on */
|
|
if ( save_rc )
|
|
return r4after ;
|
|
return 0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4leaf_seek( B4BLOCK *b4, char *search_value, int len )
|
|
{
|
|
int duplicates, bytes_same, compare_len, key_len, original_len, significant_bytes, trail_cnt, done ;
|
|
char all_blank ;
|
|
|
|
original_len = len ;
|
|
key_len = b4->tag->header.key_len ;
|
|
len -= b4calc_blanks( search_value, len, b4->tag->p_char ) ; /* don't compare blank bytes */
|
|
if ( len == 0 ) /* if all blanks, watch for records < blank */
|
|
{
|
|
len = original_len ;
|
|
all_blank = 1 ;
|
|
}
|
|
else
|
|
all_blank = 0 ;
|
|
duplicates = 0 ;
|
|
b4top( b4 ) ;
|
|
|
|
for(;;)
|
|
{
|
|
if ( b4->cur_dup_cnt == duplicates )
|
|
{
|
|
significant_bytes = key_len - x4trail_cnt( b4, b4->key_on ) ;
|
|
if ( all_blank && significant_bytes == 0 ) /* found a blank record */
|
|
len = 0 ;
|
|
compare_len = ( len < significant_bytes ? len : significant_bytes ) - b4->cur_dup_cnt ;
|
|
bytes_same = (*b4->tag->cmp)( b4->cur_pos, search_value + b4->cur_dup_cnt, compare_len ) ;
|
|
|
|
if ( bytes_same == -1 )
|
|
return r4after ;
|
|
if ( bytes_same == compare_len )
|
|
{
|
|
if ( b4->cur_dup_cnt + bytes_same == len ) /* unless binary, for sure done */
|
|
{
|
|
/* in case of binary, we may not be done if values < blank */
|
|
trail_cnt = x4trail_cnt( b4, b4->key_on ) ;
|
|
if ( significant_bytes > trail_cnt + len ) /* significant bytes beyond the trail, so check binary */
|
|
{
|
|
if ( memcmp( b4->cur_pos + compare_len, search_value + len, key_len - trail_cnt ) < 0 ) /* binaries */
|
|
done = 0 ;
|
|
else
|
|
done = 1 ;
|
|
|
|
}
|
|
else
|
|
done = 1 ;
|
|
|
|
if ( done == 1 )
|
|
{
|
|
if ( len != original_len && significant_bytes > len )
|
|
{
|
|
if ( significant_bytes < original_len )
|
|
return r4after ;
|
|
#ifdef S4DEBUG
|
|
if ( len > original_len )
|
|
e4severe( e4info, E4_B4LEAF_SEEK ) ;
|
|
#endif
|
|
if ( (*b4->tag->cmp)( b4->cur_pos + compare_len, search_value + len, (original_len - len) ) != (original_len - len) )
|
|
return r4after ;
|
|
}
|
|
if ( all_blank != 1 ) /* not all blanks, so significants matter */
|
|
b4->cur_dup_cnt += bytes_same ;
|
|
else
|
|
b4->cur_dup_cnt = 0 ;
|
|
return 0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
b4->cur_dup_cnt += bytes_same ;
|
|
}
|
|
|
|
b4->key_on++ ;
|
|
if ( b4->key_on >= b4->header.n_keys )
|
|
return r4after ;
|
|
duplicates = x4dup_cnt( b4, b4->key_on ) ;
|
|
b4->cur_pos -= key_len - duplicates - x4trail_cnt( b4, b4->key_on ) ;
|
|
if ( b4->cur_dup_cnt > duplicates )
|
|
return r4after ;
|
|
}
|
|
}
|
|
|
|
/* S4FOX */
|
|
#ifndef S4OFF_WRITE
|
|
void S4FUNCTION b4remove_leaf( B4BLOCK *b4 )
|
|
{
|
|
int old_dup, left_dup, left_trail, key_len, remove_len, new_dup, old_bytes, new_bytes, mov_len, left_bytes ;
|
|
unsigned char buffer[6], i_len ;
|
|
char *old_pos, *info_pos ;
|
|
|
|
b4->built_on = -1 ;
|
|
|
|
if ( b4->header.n_keys == 1 ) /* removing last key */
|
|
{
|
|
b4->node_hdr.free_space = B4BLOCK_SIZE - sizeof( B4NODE_HEADER ) - sizeof( B4STD_HEADER ) ;
|
|
memset( b4->data, 0, b4->node_hdr.free_space ) ;
|
|
b4->header.n_keys = 0 ;
|
|
b4->key_on = 0 ;
|
|
b4->cur_pos = ((char *)&b4->header) + B4BLOCK_SIZE ;
|
|
b4->changed = 1 ;
|
|
return ;
|
|
}
|
|
|
|
key_len = b4->tag->header.key_len ;
|
|
i_len = b4->node_hdr.info_len ;
|
|
old_dup = x4dup_cnt( b4, b4->key_on) ;
|
|
|
|
if ( b4->key_on == b4->header.n_keys - 1 ) /* at end */
|
|
{
|
|
remove_len = key_len - old_dup - x4trail_cnt( b4, b4->key_on ) ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( remove_len < 0 )
|
|
e4severe( e4info, E4_INFO_CIF ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
memset( b4->cur_pos, 0, remove_len ) ;
|
|
memset( b4->data + b4->key_on * i_len, 0, i_len ) ;
|
|
b4->key_on-- ;
|
|
}
|
|
else
|
|
{
|
|
old_bytes = key_len - old_dup - x4trail_cnt( b4, b4->key_on ) ;
|
|
old_pos = b4->cur_pos ;
|
|
b4skip( b4, 1 ) ;
|
|
left_dup = x4dup_cnt( b4, b4->key_on) ;
|
|
left_trail = x4trail_cnt( b4, b4->key_on ) ;
|
|
new_dup = old_dup < left_dup ? old_dup : left_dup ;
|
|
left_bytes = key_len - left_trail - left_dup ;
|
|
new_bytes = key_len - left_trail - new_dup ;
|
|
|
|
memcpy( b4->built_key->value, old_pos, left_dup - new_dup ) ; /* copy prev dup bytes between the 2 keys only */
|
|
memcpy( b4->built_key->value + ( left_dup - new_dup ), b4->cur_pos, left_bytes ) ;
|
|
memcpy( old_pos + old_bytes - new_bytes, b4->built_key->value, new_bytes ) ;
|
|
|
|
remove_len = old_bytes + left_bytes - new_bytes ;
|
|
#ifdef S4DEBUG
|
|
if ( remove_len < 0 )
|
|
e4severe( e4info, E4_INFO_CIF ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
mov_len = B4BLOCK_SIZE - sizeof( B4STD_HEADER ) - i_len * b4->header.n_keys
|
|
- sizeof( B4NODE_HEADER ) - b4->node_hdr.free_space
|
|
- ( ( (char *)&b4->header ) + B4BLOCK_SIZE - b4->cur_pos ) ;
|
|
#ifdef S4DEBUG
|
|
if ( mov_len < 0 )
|
|
e4severe( e4info, E4_INFO_CIB ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
memmove( b4->cur_pos - mov_len + remove_len, b4->cur_pos - mov_len, mov_len ) ;
|
|
|
|
memset( b4->cur_pos - mov_len, 0, remove_len ) ;
|
|
b4->key_on-- ;
|
|
|
|
/* move and put info */
|
|
info_pos = b4->data + ( b4->key_on ) * i_len ;
|
|
memmove( info_pos, info_pos + i_len ,i_len * ( b4->header.n_keys - b4->key_on ) ) ;
|
|
x4put_info( &b4->node_hdr, buffer, x4recno( b4, b4->key_on ), left_trail, new_dup ) ;
|
|
memcpy( info_pos, (void *)buffer, i_len ) ;
|
|
memset( b4->data + (b4->header.n_keys - 1 ) * i_len, 0, i_len ) ;
|
|
}
|
|
b4->changed = 1 ;
|
|
b4->cur_pos += remove_len ;
|
|
b4->header.n_keys-- ;
|
|
b4->node_hdr.free_space += (short) ((int)i_len + remove_len) ;
|
|
}
|
|
|
|
/* S4FOX */
|
|
void S4FUNCTION b4remove( B4BLOCK *b4 )
|
|
{
|
|
char *key_cur ;
|
|
int len, i_len ;
|
|
|
|
if( b4->header.node_attribute >= 2 ) /* leaf */
|
|
b4remove_leaf( b4 ) ;
|
|
else
|
|
{
|
|
i_len = b4->tag->header.key_len + 2 * sizeof( long ) ;
|
|
key_cur = ((char *)&b4->node_hdr) + i_len * b4->key_on ;
|
|
len = (b4->header.n_keys - b4->key_on - 1) * i_len ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( b4->key_on < 0 || b4->key_on > b4lastpos( b4 ) ||
|
|
len < 0 || (unsigned)len > (B4BLOCK_SIZE - sizeof(B4STD_HEADER) - (unsigned)i_len ))
|
|
e4severe( e4info, E4_B4REMOVE ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
if ( len > 0 )
|
|
memmove( key_cur, key_cur + i_len, len ) ;
|
|
|
|
b4->header.n_keys-- ;
|
|
memset( ((char *)&b4->node_hdr) + b4->header.n_keys * i_len, 0, i_len ) ;
|
|
b4->changed = 1 ;
|
|
}
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
/* S4FOX */
|
|
int S4FUNCTION b4skip( B4BLOCK *b4, long n )
|
|
{
|
|
int num_skipped ;
|
|
|
|
if ( b4->header.node_attribute < 2 ) /* branch */
|
|
{
|
|
if ( n > 0 )
|
|
num_skipped = b4->header.n_keys - b4->key_on ;
|
|
else
|
|
num_skipped = -b4->key_on ;
|
|
|
|
if ( ( n <= 0L ) ? (num_skipped <= (int)n) : (num_skipped >= (int)n) )
|
|
{
|
|
b4->key_on += (int) n ;
|
|
return (int) n ;
|
|
}
|
|
else
|
|
{
|
|
b4->key_on += num_skipped ;
|
|
return num_skipped ;
|
|
}
|
|
}
|
|
else /* leaf */
|
|
{
|
|
if ( b4->header.n_keys == 0 )
|
|
return 0 ;
|
|
if (n > 0 )
|
|
{
|
|
if ( b4->key_on + n >= b4->header.n_keys )
|
|
{
|
|
b4->cur_pos = ((char *)&b4->header ) + sizeof( B4STD_HEADER )
|
|
+ sizeof( B4NODE_HEADER ) + b4->node_hdr.info_len * b4->header.n_keys
|
|
+ b4->node_hdr.free_space ;
|
|
n = b4->header.n_keys - b4->key_on - ( b4->key_on != b4->header.n_keys ) ;
|
|
b4->key_on = b4->header.n_keys ;
|
|
return (int)n ;
|
|
}
|
|
for( num_skipped = (int)n ; num_skipped != 0 ; num_skipped-- )
|
|
{
|
|
b4->key_on++ ;
|
|
b4->cur_pos -= ( b4->tag->header.key_len - x4dup_cnt( b4, b4->key_on ) - x4trail_cnt( b4, b4->key_on ) ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( b4->key_on + n < 0 )
|
|
{
|
|
n = -b4->key_on ;
|
|
b4->key_on = 0 ;
|
|
b4->cur_pos = ((char *)&b4->header ) + B4BLOCK_SIZE - b4->tag->header.key_len + x4trail_cnt( b4, b4->key_on ) ;
|
|
return (int) n ;
|
|
}
|
|
for( num_skipped = (int)n ; num_skipped != 0 ; num_skipped++ )
|
|
{
|
|
b4->cur_pos += ( b4->tag->header.key_len - x4dup_cnt( b4, b4->key_on ) - x4trail_cnt( b4, b4->key_on ) ) ;
|
|
b4->key_on-- ;
|
|
}
|
|
}
|
|
|
|
return (int) n ;
|
|
}
|
|
}
|
|
#endif /* S4FOX */
|
|
|
|
#ifdef N4OTHER
|
|
#ifndef S4OFF_WRITE
|
|
int S4FUNCTION b4flush( B4BLOCK *b4 )
|
|
{
|
|
int rc ;
|
|
#ifdef S4BYTE_SWAP
|
|
char *swap, *swap_ptr ;
|
|
int i ;
|
|
S4LONG long_val ;
|
|
short short_val ;
|
|
#endif
|
|
|
|
if ( b4->changed )
|
|
{
|
|
#ifdef S4INDEX_VERIFY
|
|
if ( b4verify( b4 ) == -1 )
|
|
e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4flush()", "" ) ;
|
|
#endif
|
|
#ifdef S4NDX
|
|
#ifdef S4BYTE_SWAP
|
|
swap = (char *) u4alloc_er( b4->tag->code_base, B4BLOCK_SIZE ) ;
|
|
if ( swap == 0 )
|
|
return -1 ;
|
|
|
|
memcpy( (void *)swap, (void *)&b4->n_keys, B4BLOCK_SIZE ) ;
|
|
/* position swap_ptr at beginning of pointers */
|
|
|
|
swap_ptr += swap + 2 + sizeof(short) ;
|
|
|
|
for ( i = 0 ; i < (*(short *)swap) ; i++ )
|
|
{
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ;
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
long_val = x4reverse_long( (void *)swap_ptr+sizeof(S4LONG) ) ;
|
|
memcpy( swap_ptr+sizeof(S4LONG), (void *) &long_val, sizeof(S4LONG) ) ;
|
|
swap_ptr += r4->data->indexes->tags.header->group_len ;
|
|
}
|
|
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ;
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
|
|
short_val = x4reverse_short( (void *)swap ) ;
|
|
memcpy( swap, (void *) &short_val, sizeof(short) ) ;
|
|
|
|
rc = file4write( &b4->tag->file, (long)b4->file_block*I4MULTIPLY, swap, B4BLOCK_SIZE ) ;
|
|
u4free( swap ) ;
|
|
#else
|
|
rc = file4write( &b4->tag->file, (long)b4->file_block*I4MULTIPLY, &b4->n_keys, B4BLOCK_SIZE ) ;
|
|
#endif
|
|
#endif /* S4NDX */
|
|
|
|
#ifdef S4CLIPPER
|
|
#ifdef S4BYTE_SWAP
|
|
swap = (char *)u4alloc_er( b4->tag->code_base, B4BLOCK_SIZE ) ;
|
|
if ( swap == 0 )
|
|
return -1 ;
|
|
|
|
memcpy( (void *)swap, (void *)&b4->n_keys, B4BLOCK_SIZE ) ;
|
|
|
|
/* position swap_ptr at beginning of pointers */
|
|
short_val = x4reverse_short( (void *)swap ) ;
|
|
memcpy( swap, (void *) &short_val, sizeof(short) ) ;
|
|
|
|
swap_ptr = swap + 2 ;
|
|
|
|
/* swap the short pointers to B4KEY_DATA */
|
|
for ( i = 0 ; i < b4->tag->header.keys_max ; i++ )
|
|
{
|
|
short_val = x4reverse_short( (void *)swap_ptr ) ;
|
|
memcpy( swap_ptr, (void *) &short_val, sizeof(short) ) ;
|
|
swap_ptr += sizeof(short) ;
|
|
}
|
|
/* swap the B4KEY_DATA's */
|
|
for ( i = 0 ; i < b4->tag->header.keys_max ; i++ )
|
|
{
|
|
long_val = x4reverse_long( (void *)swap_ptr ) ;
|
|
memcpy( swap_ptr, (void *) &long_val, sizeof(S4LONG) ) ;
|
|
long_val = x4reverse_long( (void *)swap_ptr+sizeof(S4LONG) ) ;
|
|
memcpy( swap_ptr+sizeof(S4LONG), (void *) &long_val, sizeof(S4LONG) ) ;
|
|
swap_ptr += b4->tag->header.group_len ;
|
|
}
|
|
|
|
rc = file4write( &b4->tag->file, (long)b4->file_block*I4MULTIPLY, swap, B4BLOCK_SIZE ) ;
|
|
u4free( swap ) ;
|
|
#else
|
|
rc = file4write( &b4->tag->file, (long)b4->file_block*I4MULTIPLY, &b4->n_keys, B4BLOCK_SIZE ) ;
|
|
#endif
|
|
#endif /* S4CLIPPER */
|
|
|
|
if ( rc < 0 ) return rc ;
|
|
b4->changed = 0 ;
|
|
}
|
|
return 0 ;
|
|
}
|
|
|
|
void S4FUNCTION b4append( B4BLOCK *b4, long pointer )
|
|
{
|
|
#ifdef S4CLIPPER
|
|
long adj_pointer = pointer * 512 ;
|
|
#endif /* S4CLIPPER */
|
|
B4KEY_DATA *data_ptr ;
|
|
#ifdef S4DEBUG
|
|
int left_len ;
|
|
if ( b4leaf( b4 ) || pointer <1L )
|
|
e4severe( e4parm, E4_B4APPEND ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
b4go_eof( b4 ) ;
|
|
data_ptr = b4key( b4, b4->key_on ) ;
|
|
|
|
#ifdef S4DEBUG
|
|
left_len = B4BLOCK_SIZE - b4->key_on * b4->tag->header.group_len -
|
|
sizeof(short) - sizeof(char[2]) - sizeof(pointer) ;
|
|
if ( b4->key_on < 0 || b4->key_on != b4->n_keys || left_len < 0 )
|
|
e4severe( e4info, E4_B4APPEND ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
#ifdef S4NDX
|
|
memcpy( &data_ptr->pointer, &pointer, sizeof(pointer) ) ;
|
|
#endif /* S4NDX */
|
|
#ifdef S4CLIPPER
|
|
memcpy( &data_ptr->pointer, &adj_pointer, sizeof(pointer) ) ;
|
|
#endif /* S4CLIPPER */
|
|
b4->changed = 1 ;
|
|
#ifdef S4INDEX_VERIFY
|
|
if ( b4verify( b4 ) == -1 )
|
|
e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4append()-after append", "" ) ;
|
|
#endif
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
#ifndef S4OFF_WRITE
|
|
#ifdef S4CLIPPER
|
|
void S4FUNCTION b4append2( B4BLOCK *b4, void *k, long r, long pointer )
|
|
{
|
|
unsigned short temp ;
|
|
B4KEY_DATA *data_ptr ;
|
|
long adj_pointer ;
|
|
|
|
b4go_eof( b4 ) ;
|
|
|
|
if ( b4->n_keys > 0 )
|
|
{
|
|
if ( !b4leaf( b4 ) ) /* insert after branch */
|
|
b4->key_on++ ;
|
|
else
|
|
if ( b4->key_on + !b4leaf( b4 ) < b4->tag->header.keys_max )
|
|
{
|
|
temp = b4->pointers[b4->n_keys+1] ;
|
|
b4->pointers[b4->n_keys+1] = b4->pointers[b4->n_keys] ;
|
|
b4->pointers[b4->n_keys] = temp ;
|
|
}
|
|
}
|
|
|
|
data_ptr = b4key( b4, b4->key_on ) ;
|
|
adj_pointer = pointer * 512 ;
|
|
b4->n_keys++ ;
|
|
|
|
memcpy( data_ptr->value, k, b4->tag->header.group_len-2*sizeof(long) ) ;
|
|
memcpy( &data_ptr->num, &r, sizeof(r) ) ;
|
|
memcpy( &data_ptr->pointer, &adj_pointer, sizeof(pointer) ) ;
|
|
b4->changed = 1 ;
|
|
}
|
|
#endif /* S4CLIPPER */
|
|
|
|
#ifdef S4NDX
|
|
|
|
/* S4NDX */
|
|
void S4FUNCTION b4insert( B4BLOCK *b4, void *k, long r, long pointer )
|
|
{
|
|
B4KEY_DATA *data_ptr, *next_ptr ;
|
|
int left_len ;
|
|
#ifdef S4DEBUG
|
|
if ( k == 0 || r < 0L || pointer <0L )
|
|
e4severe( e4parm, E4_B4INSERT ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
data_ptr = b4key( b4, b4->key_on ) ;
|
|
next_ptr= b4key( b4, b4->key_on + 1 ) ;
|
|
|
|
left_len = B4BLOCK_SIZE - (b4->key_on + 1) * b4->tag->header.group_len -
|
|
sizeof(short) - sizeof(char[2]) ; /* 2 for S4NDX version, not 6 */
|
|
|
|
#ifdef S4DEBUG
|
|
if ( b4->key_on < 0 || ( b4->key_on > b4->n_keys && b4leaf( b4 ) ) ||
|
|
( b4->key_on > (b4->n_keys+1) && !b4leaf( b4 ) ) || left_len < 0 )
|
|
e4severe( e4info, E4_B4INSERT ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
memmove( next_ptr, data_ptr, left_len ) ;
|
|
b4->n_keys++ ;
|
|
memcpy( data_ptr->value, k, b4->tag->header.key_len ) ;
|
|
memcpy( &data_ptr->num, &r, sizeof(r) ) ;
|
|
memcpy( &data_ptr->pointer, &pointer, sizeof(pointer) ) ;
|
|
b4->changed = 1 ;
|
|
}
|
|
#endif /* S4NDX */
|
|
|
|
#ifdef S4CLIPPER
|
|
/* clipper just puts at end and inserts into the index part */
|
|
void S4FUNCTION b4insert( B4BLOCK *b4, void *k, long r, long pointer )
|
|
{
|
|
short temp, insert_pos ;
|
|
#ifdef S4DEBUG
|
|
if ( k == 0 || r < 0L || pointer <0L )
|
|
e4severe( e4parm, E4_B4INSERT ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
insert_pos = b4->key_on ;
|
|
|
|
/* put at block end: */
|
|
b4append2( b4, k, r, pointer ) ;
|
|
|
|
temp = b4->pointers[b4->key_on] ; /* save the placed position */
|
|
memmove( &b4->pointers[insert_pos+1], &b4->pointers[insert_pos], sizeof(short) * ( b4lastpos( b4 ) - insert_pos - (!b4leaf( b4 ) && b4->n_keys < 2) ) ) ;
|
|
b4->pointers[insert_pos] = temp ;
|
|
if ( b4leaf( b4 ) )
|
|
if ( b4key( b4, b4->n_keys )->pointer != 0 )
|
|
b4key( b4, b4->n_keys )->pointer = 0L ;
|
|
}
|
|
#endif /* S4CLIPPER */
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
/* goes to one past the end of the block */
|
|
void S4FUNCTION b4go_eof( B4BLOCK *b4 )
|
|
{
|
|
b4->key_on = b4->n_keys ;
|
|
}
|
|
|
|
B4KEY_DATA *S4FUNCTION b4key( B4BLOCK *b4, int i_key )
|
|
{
|
|
#ifdef S4NDX
|
|
return (B4KEY_DATA *) ((char *) &b4->data + b4->tag->header.group_len * i_key) ;
|
|
#endif /* S4NDX */
|
|
|
|
#ifdef S4CLIPPER
|
|
#ifdef S4DEBUG
|
|
if ( i_key > 2 + b4->tag->header.keys_max )
|
|
e4severe( e4parm, E4_B4KEY ) ;
|
|
if ( ( b4->pointers[i_key] < (sizeof(short)) * ( b4->tag->header.keys_max + 1 ) ) ||
|
|
( b4->pointers[i_key] > B4BLOCK_SIZE - b4->tag->header.key_len ) )
|
|
e4severe( e4info, E4_B4KEY ) ;
|
|
#endif /* S4DEBUG */
|
|
return (B4KEY_DATA *) ((char *) &b4->n_keys + b4->pointers[i_key] ) ;
|
|
#endif /* S4CLIPPER */
|
|
}
|
|
|
|
unsigned char *S4FUNCTION b4key_key( B4BLOCK *b4, int i_key )
|
|
{
|
|
return (unsigned char *) b4key( b4, i_key )->value ;
|
|
}
|
|
|
|
int S4FUNCTION b4lastpos( B4BLOCK *b4 )
|
|
{
|
|
if ( !b4leaf( b4 ) )
|
|
return b4->n_keys ;
|
|
else
|
|
return b4->n_keys - 1 ;
|
|
}
|
|
|
|
int S4FUNCTION b4leaf( B4BLOCK *b4 )
|
|
{
|
|
return( b4key( b4, 0 )->pointer == 0L ) ;
|
|
}
|
|
|
|
long S4FUNCTION b4recno( B4BLOCK *b4, int i )
|
|
{
|
|
return b4key( b4, i )->num ;
|
|
}
|
|
|
|
#ifndef S4OFF_WRITE
|
|
#ifdef S4NDX
|
|
void S4FUNCTION b4remove( B4BLOCK *b4 )
|
|
{
|
|
B4KEY_DATA *key_on ;
|
|
int left_len = -1 ;
|
|
|
|
key_on = b4key( b4, b4->key_on ) ;
|
|
|
|
if( !b4leaf( b4 ) )
|
|
{
|
|
if ( b4->key_on >= b4->n_keys )
|
|
left_len = 0 ;
|
|
else /* on last pos, so copy only the rec_num */
|
|
if ( b4lastpos( b4 ) + 1 == b4->n_keys )
|
|
left_len = sizeof( long ) ;
|
|
}
|
|
|
|
if ( left_len == -1 )
|
|
left_len = B4BLOCK_SIZE - sizeof(b4->n_keys) - sizeof(b4->dummy) - (b4->key_on+1) * b4->tag->header.group_len ;
|
|
|
|
#ifdef S4DEBUG
|
|
if ( b4->key_on < 0 || b4->key_on > b4lastpos( b4 ) || left_len < 0 )
|
|
e4severe( e4info, E4_B4REMOVE ) ;
|
|
#endif /* S4DEBUG */
|
|
|
|
if ( left_len > 0 )
|
|
{
|
|
B4KEY_DATA *key_next= b4key( b4, b4->key_on+1 ) ;
|
|
memmove( key_on, key_next, left_len ) ;
|
|
}
|
|
b4->n_keys-- ;
|
|
b4->changed = 1 ;
|
|
}
|
|
#endif /* S4NDX */
|
|
|
|
#ifdef S4CLIPPER
|
|
void S4FUNCTION b4remove( B4BLOCK *b4 )
|
|
{
|
|
short temp ;
|
|
|
|
/* just delete this entry */
|
|
temp = b4->pointers[b4->key_on] ;
|
|
if ( b4leaf( b4 ) && ( b4->key_on + !b4leaf( b4 ) < b4->tag->header.keys_max ) )
|
|
{
|
|
memmove( &b4->pointers[b4->key_on], &b4->pointers[b4->key_on+1],
|
|
sizeof(short) * (b4lastpos( b4 ) - b4->key_on + 1) ) ;
|
|
b4->pointers[b4lastpos( b4 )+1] = temp ;
|
|
}
|
|
else
|
|
{
|
|
memmove( &b4->pointers[b4->key_on], &b4->pointers[b4->key_on+1],
|
|
sizeof(short) * (b4lastpos( b4 ) - b4->key_on) ) ;
|
|
b4->pointers[b4lastpos( b4 )] = temp ;
|
|
}
|
|
b4->n_keys-- ;
|
|
b4->changed = 1 ;
|
|
|
|
if ( b4leaf( b4 ) )
|
|
memset( b4key( b4, b4lastpos( b4 ) + 1 ), 0, b4->tag->header.key_len + 2 * sizeof( long ) ) ;
|
|
}
|
|
#endif /* S4CLIPPER */
|
|
|
|
int S4FUNCTION b4room( B4BLOCK *b4 )
|
|
{
|
|
if ( b4leaf( b4 ) )
|
|
return ( b4->n_keys < b4->tag->header.keys_max ) ;
|
|
|
|
return( ( b4->n_keys < b4->tag->header.keys_max ) && ( ( B4BLOCK_SIZE -
|
|
b4->n_keys * b4->tag->header.group_len - sizeof(short) - 2*sizeof(char)) >= sizeof(long) ) ) ;
|
|
}
|
|
#endif /* S4OFF_WRITE */
|
|
|
|
int S4FUNCTION b4seek( B4BLOCK *b4, char *search_value, int len )
|
|
{
|
|
int rc, save_rc, key_cur ;
|
|
S4CMP_FUNCTION *cmp = b4->tag->cmp ;
|
|
|
|
/* key_on must be between key_lower and key_upper */
|
|
int key_lower = -1 ;
|
|
int key_upper = b4->n_keys ;
|
|
|
|
if ( key_upper == 0 )
|
|
{
|
|
b4->key_on = 0 ;
|
|
return r4after ;
|
|
}
|
|
|
|
save_rc = 1 ;
|
|
|
|
for(;;) /* Repeat until the key is found */
|
|
{
|
|
key_cur = (key_upper + key_lower) / 2 ;
|
|
rc = (*cmp)( b4key_key(b4,key_cur), search_value, len ) ;
|
|
|
|
if ( rc >= 0 )
|
|
{
|
|
key_upper = key_cur ;
|
|
save_rc = rc ;
|
|
}
|
|
else
|
|
key_lower = key_cur ;
|
|
|
|
if ( key_lower >= (key_upper-1) ) /* then there is no exact match */
|
|
{
|
|
b4->key_on = key_upper ;
|
|
if ( save_rc )
|
|
return r4after ;
|
|
return 0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
int S4FUNCTION b4skip( B4BLOCK *b4, long n )
|
|
{
|
|
int num_left ;
|
|
|
|
if ( n > 0 )
|
|
{
|
|
num_left = b4->n_keys - b4->key_on ;
|
|
if ( b4leaf( b4 ) )
|
|
if ( num_left != 0 )
|
|
num_left -- ;
|
|
}
|
|
else
|
|
num_left = -b4->key_on ;
|
|
|
|
if ( ( n <= 0L ) ? ( (long)num_left <= n ) : ( (long)num_left >= n ) )
|
|
{
|
|
b4->key_on = b4->key_on + (int) n ;
|
|
return (int) n ;
|
|
}
|
|
else
|
|
{
|
|
b4->key_on = b4->key_on + num_left ;
|
|
return num_left ;
|
|
}
|
|
}
|
|
#endif /* N4OTHER */
|
|
#endif /* S4INDEX_OFF */
|
|
|
|
#ifdef S4INDEX_VERIFY
|
|
int S4FUNCTION b4verify( B4BLOCK *b4 )
|
|
{
|
|
int i, j, type ;
|
|
long val ;
|
|
#ifdef S4FOX
|
|
int hold_dup, hold_trail ;
|
|
|
|
hold_dup = b4->cur_dup_cnt ;
|
|
hold_trail = b4->cur_trail_cnt ;
|
|
#endif
|
|
|
|
if ( b4->tag->code_base->do_index_verify == 0 )
|
|
return 0 ;
|
|
|
|
#ifdef S4CLIPPER
|
|
/* block internal verification... */
|
|
for ( i = 0 ; i < b4->tag->header.keys_max ; i++ )
|
|
for ( j = i + 1 ; j <= b4->tag->header.keys_max ; j++ )
|
|
if ( b4->pointers[i] == b4->pointers[j] )
|
|
{
|
|
#ifdef S4DEBUG_DEV
|
|
e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", "b4 pointer duplication error" ) ;
|
|
#endif
|
|
e4( b4->tag->code_base, e4index, E4_INFO_CIF ) ;
|
|
return -1 ;
|
|
}
|
|
|
|
/* validate key count */
|
|
if ( b4->n_keys < b4->tag->header.keys_half && b4->tag->header.root / 512 != b4->file_block )
|
|
return e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", E4_RESULT_CII ) ;
|
|
#endif
|
|
|
|
/* #ifdef S4FOX */
|
|
/* */
|
|
/* if ( b4->node_hdr.free_space != B4BLOCK_SIZE - sizeof( B4STD_HEADER ) */
|
|
/* - sizeof( B4NODE_HEADER ) - ) */
|
|
/* return e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", E4_RESULT_CII ) ; */
|
|
/* #endif */
|
|
|
|
/* all keys in a given block should be of the same type... - branch = 1 */
|
|
#ifndef S4FOX
|
|
type = b4leaf( b4 ) ? 0 : 1 ;
|
|
#endif
|
|
|
|
/* key order verification */
|
|
#ifdef N4OTHER
|
|
for ( i = 0 ; i <= b4->n_keys ; i++ )
|
|
{
|
|
#ifdef S4CLIPPER
|
|
val = b4key( b4, i )->pointer ;
|
|
if ( ( b4key( b4, i )->pointer ? 1 : 0 ) != type )
|
|
#endif
|
|
#ifdef S4NDX
|
|
if ( b4key( b4, i )->pointer >= b4->tag->header.eof )
|
|
return e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", "block pointer value exceeds index eof value" ) ;
|
|
if ( ( b4key( b4, i )->pointer ? 1 : 0 ) != type )
|
|
#endif
|
|
{
|
|
#ifdef S4DEBUG_DEV
|
|
e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", "b4 branch/leaf block type inconsistent" ) ;
|
|
#endif
|
|
e4( b4->tag->code_base, e4index, E4_INFO_CIF ) ;
|
|
return -1 ;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef S4FOX
|
|
for ( i = 0 ; i < b4->header.n_keys - 1 ; i++ )
|
|
{
|
|
if ( (u4memcmp)( b4key_key( b4, i ), b4key_key( b4, i + 1 ), b4->tag->header.key_len ) > 0 )
|
|
#else
|
|
for ( i = 0 ; i < b4->n_keys - 1 ; i++ )
|
|
{
|
|
if ( (*b4->tag->cmp)( b4key_key( b4, i ), b4key_key( b4, i + 1 ), b4->tag->header.key_len ) > 0 )
|
|
#endif
|
|
{
|
|
#ifdef S4DEBUG_DEV
|
|
e4describe( b4->tag->code_base, e4index, b4->tag->alias, "b4verify()", "b4 block ordering invalid" ) ;
|
|
#endif
|
|
e4( b4->tag->code_base, e4index, E4_INFO_CIF ) ;
|
|
return -1 ;
|
|
}
|
|
}
|
|
|
|
#ifdef S4FOX
|
|
b4->cur_dup_cnt = hold_dup ;
|
|
b4->cur_trail_cnt = hold_trail ;
|
|
#endif
|
|
|
|
return 0 ;
|
|
}
|
|
#endif
|