home *** CD-ROM | disk | FTP | other *** search
-
- /* i4remove.c (c)Copyright Sequiter Software Inc., 1987-1990. All rights reserved.
-
- Removes a key from an index file.
- Gives same returns as i4seek except 0 means the key was successfully
- removed.
- */
-
- #include "d4all.h"
- #include "u4error.h"
- #include "p4misc.h"
-
- #include <string.h>
-
- extern INDEX *v4index ;
- extern BLOCK *v4block ;
-
-
- #ifdef CLIPPER
- static int b4remove_blk( int ) ;
-
- static int b4remove_blk( int index_ref )
- {
- INDEX *index_ptr ;
- BLOCK *block_ptr ;
- long *long_ptr ;
-
- index_ptr = v4index+ index_ref ;
- block_ptr = v4block+ index_ptr->block_ref ;
-
- long_ptr = (long *) &block_ptr->num_keys ;
- *long_ptr = v4index[index_ref].eof ;
- v4index[index_ref].eof = block_ptr->file_block ;
-
- if ( b4write( index_ref, index_ptr->block_ref) < 0 ) return -1 ;
- index_ptr->block_ref = h4free((char **) &v4block, index_ptr->block_ref);
-
- return 0 ;
- }
-
- /* Remove Reference
-
- A. Save Key for Later Add, Save Next
- B. Remove Key
- C. If Block Empty
- 1. If Block is Root
- i. Make the Reference the new Root
- ii. Remove the Block
- 2. If Block is not the Root
- i. Save the Ending Block Reference
- ii. Remove the Block
- iii. Move to the Preceeding Block
- iv. Change the Block Reference to the Saved Value
- D. Call i4add to add the Key back.
- */
-
- static int remove_reference( int ) ;
-
- static int remove_reference( int index_ref )
- {
- BLOCK *block_ptr ;
- KEY save_key, *key_ptr ;
-
- block_ptr = v4block + v4index[index_ref].block_ref ;
- block_ptr->wrt = 1 ;
- if ( block_ptr->num_keys <= 0 )
- {
- u4error( E_INTERNAL, "remove_reference", (char *) 0 ) ;
- return -1 ;
- }
-
- /* Save the Key to Add it as a new Leaf Later */
- if ( block_ptr->key_on >= block_ptr->num_keys )
- {
- block_ptr->key_on-- ;
- key_ptr = i4key(index_ref ) ;
- if ( key_ptr == (KEY *) 0 )
- {
- u4error( E_INTERNAL, "remove_reference 2", (char *) 0 ) ;
- return -1 ;
- }
- memcpy( &save_key, key_ptr, (size_t) v4index[index_ref].group_len ) ;
- block_ptr->num_keys-- ;
- }
- else
- {
- key_ptr = i4key(index_ref ) ;
- if ( key_ptr == (KEY *) 0 )
- {
- u4error( E_INTERNAL, "remove_reference 3", (char *) 0 ) ;
- return -1 ;
- }
- memcpy( &save_key, key_ptr, (size_t) v4index[index_ref].group_len ) ;
- b4remove( index_ref ) ;
-
- key_ptr = i4key(index_ref ) ;
- if ( key_ptr == (KEY *) 0 )
- {
- u4error( E_INTERNAL, "remove_reference 4", (char *) 0 ) ;
- return -1 ;
- }
- save_key.file_block = key_ptr->file_block ;
- }
-
- if ( block_ptr->num_keys > 0 )
- {
- if ( i4add( index_ref, save_key.value, save_key.rec_num) != 0) return -1;
- return 0 ;
- }
-
- block_ptr->key_on = 0 ;
-
- key_ptr = i4key(index_ref ) ;
- if ( key_ptr == (KEY *) 0 )
- {
- u4error( E_INTERNAL, "remove_reference 3", (char *) 0 ) ;
- return -1 ;
- }
-
- /* Check for Root Block */
- if ( block_ptr->file_block == v4index[index_ref].root )
- {
- v4index[index_ref].root = save_key.file_block ;
- if ( b4remove_blk(index_ref) < 0 ) return -1 ;
- if ( i4add(index_ref, save_key.value, save_key.rec_num) != 0) return -1;
- return 0 ;
- }
-
- if (b4remove_blk(index_ref) < 0) return -1 ;
-
- key_ptr = i4key(index_ref ) ;
- if ( key_ptr == (KEY *) 0 )
- {
- u4error( E_INTERNAL, "remove_reference 4", (char *) 0 ) ;
- return -1 ;
- }
-
- key_ptr->file_block = save_key.file_block ;
- v4block[ v4index[index_ref].block_ref].wrt = 1 ;
-
- /* Add the Saved Key */
- if ( i4add( index_ref, save_key.value, save_key.rec_num ) != 0 ) return -1 ;
-
- return 0 ;
- }
-
-
- /* Algorithm: (Always call with leaf initially.)
-
- A. Leaf key.
- 1. Remove Key
- 2. Write & Return if block not empty.
- 3. Write & Return if block is the Root.
- 4. Remove Key Block Reference in the Next Level
- */
-
- static int remove_key( int ) ;
-
- static int remove_key( int index_ref )
- {
- BLOCK *block_ptr ;
-
- block_ptr = v4block + v4index[index_ref].block_ref ;
- if ( block_ptr->num_keys <= 0 )
- {
- u4error( E_INTERNAL, "remove_key", (char *) 0 ) ;
- return -1 ;
- }
-
- b4remove( index_ref ) ;
- if ( block_ptr->num_keys > 0 ) return 0 ;
-
- /* Check for Root Block */
- if ( block_ptr->file_block == v4index[index_ref].root ) return 0 ;
-
- /* Remove Block */
- if ( b4remove_blk(index_ref) < 0 ) return -1 ;
-
- return( remove_reference(index_ref) ) ;
- }
-
-
- i4remove( int index_ref, char *value_ptr, long rec_num )
- {
- KEY *key_ptr, *next_key_ptr ;
- int rc ;
- BLOCK *block_ptr ;
- INDEX *index_ptr ;
-
- index_ptr = v4index + index_ref ;
-
- rc = i4go( index_ref, value_ptr, rec_num ) ;
- if ( rc < 0 ) return( rc ) ;
- if ( rc >= 1 ) return( 1 ) ;
-
- index_ptr->version = index_ptr->old_version + 1 ;
-
- if ( ! b4leaf(index_ref) )
- {
- /* Flip the Keys */
- key_ptr = i4key( index_ref ) ;
- if ( key_ptr == (KEY *) 0 )
- {
- u4error( E_INTERNAL, "Routine i4remove", (char *) 0 ) ;
- return -1 ;
- }
- block_ptr = v4block+ index_ptr->block_ref ;
-
- rc = (int) i4skip( index_ref, -1L ) ;
- if ( rc != -1 )
- {
- u4error( E_INTERNAL, "Routine i4remove 2", (char *) 0 ) ;
- return -1 ;
- }
-
- next_key_ptr = i4key( index_ref ) ;
- if ( next_key_ptr == (KEY *) 0 )
- {
- u4error( E_INTERNAL, "Routine i4remove", (char *) 0 ) ;
- return -1 ;
- }
-
- memmove( key_ptr->value, next_key_ptr->value, (size_t) index_ptr->key_len ) ;
- key_ptr->rec_num = next_key_ptr->rec_num ;
-
- block_ptr->wrt = 1 ;
- }
-
- if ( remove_key( index_ref ) < 0 ) return -1 ;
-
- return 0 ;
- }
-
- #else
-
- /* dBASE Version */
- i4remove( int i_ref, char *value_ptr, long rec_num )
- {
- INDEX *i_ptr ;
- BLOCK *block_ptr ;
- char *from_ptr, *to_ptr ;
- int rc, key_last ;
-
- i_ptr= v4index + i_ref ;
-
- rc = i4seek( i_ref, value_ptr ) ;
-
- if ( rc < 0 ) return( rc) ;
- if ( rc >= 2 ) return( 1 ) ;
-
- while ( rec_num != i4key(i_ref)->rec_num )
- {
- rc = (int) i4skip( i_ref, 1L ) ;
- if ( rc == -1 ) return( -1 ) ;
- if ( rc == 0 ) return( 1 ) ;
-
- if ( i4keycmp( i_ref, i4key(i_ref)->value, value_ptr) != 0 )
- return( 1 ) ;
- }
-
- i_ptr->version = i_ptr->old_version + 1 ;
-
- /* Remove the current key */
- for (;;)
- {
- block_ptr = v4block + i_ptr->block_ref ;
- key_last = block_ptr->num_keys ;
- if ( b4leaf(i_ref)) key_last-- ;
-
- if ( block_ptr->key_on == key_last && key_last > 0 )
- {
- /* The current blocks last key is going to disapear
- and there are additional keys left.
- Conseqently, a higher entry's key pointer needs to be adjusted.
- */
-
- from_ptr = block_ptr->key.value + i_ptr->group_len*(block_ptr->key_on-1) ;
-
- while ( block_ptr->prev >= 0 )
- {
- block_ptr = v4block + block_ptr->prev ;
-
- if ( block_ptr->key_on < block_ptr->num_keys )
- {
- to_ptr = block_ptr->key.value + i_ptr->group_len*block_ptr->key_on ;
- memcpy( to_ptr, from_ptr, (size_t) i_ptr->key_len ) ;
- block_ptr->wrt = 1 ;
- break ;
- }
- }
- /* Went up to root; nothing to adjust */
- }
-
- rc = b4remove( i_ref) ;
- if ( rc <= 0 )
- {
- if ( rc < 0 ) return -1 ;
-
- rc = b4up( i_ref ) ;
- if ( rc == -2 )
- {
- u4error( E_INTERNAL, "I3REMOVE", (char *) 0 ) ;
- return -1 ;
- }
-
- if ( rc == -1 )
- {
- /* No More Keys */
- block_ptr = v4block+ i_ptr->block_ref ;
- block_ptr->wrt = 1 ;
- block_ptr->num_keys = 0 ;
- block_ptr->key.file_block = 0 ;
- block_ptr->key.rec_num = 0 ;
- return 0 ;
- }
- }
- else
- return 0 ;
- }
- }
- #endif
-