home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / CODE4-1.ZIP / SOURCE.ZIP / I4REMOVE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-17  |  7.4 KB  |  306 lines

  1.  
  2. /*   i4remove.c    (c)Copyright Sequiter Software Inc., 1987, 1988, 1989.  All rights reserved.
  3.  
  4.      Removes a key from an index file.
  5.      Gives same returns as i4seek except 0 means the key was successfully
  6.      removed.
  7. */
  8.  
  9. #include   "d4base.h"
  10. #include   <string.h>
  11. #include   "u4error.h"
  12.  
  13. extern   INDEX  *v4index ;
  14. extern   BLOCK  *v4block ;
  15.  
  16.  
  17. #ifdef CLIPPER
  18.  
  19. /*   Remove Reference 
  20.  
  21.      A. Save Key for Later Add, Save Next
  22.      B. Remove Key
  23.      C. If Block Empty
  24.     1. If Block is Root
  25.        i.   Make the Reference the new Root
  26.        ii.  Remove the Block
  27.     2. If Block is not the Root
  28.        i.   Save the Ending Block Reference
  29.        ii.  Remove the Block
  30.        iii. Move to the Preceeding Block
  31.        iv.  Change the Block Reference to the Saved Value
  32.      D.  Call i4add to add the Key back.
  33. */
  34.  
  35. extern  int  b4remove_blk( int ) ;
  36.  
  37. static  remove_reference( index_ref )
  38. int index_ref ;
  39. {
  40.    BLOCK *block_ptr ;
  41.    KEY    save_key, *key_ptr ;
  42.  
  43.    block_ptr =  v4block +  v4index[index_ref].block_ref ;
  44.    block_ptr->wrt =  1 ;
  45.    if ( block_ptr->num_keys <= 0 )
  46.    {
  47.       u4error( E_INTERNAL, "remove_reference", (char *) 0 ) ;
  48.       return -1 ;
  49.    }
  50.  
  51.    /* Save the Key to Add it as a new Leaf Later */
  52.    if ( block_ptr->key_on >= block_ptr->num_keys )
  53.    {
  54.       block_ptr->key_on-- ;
  55.       key_ptr   =  b4key(index_ref ) ;
  56.       if ( key_ptr == (KEY *) 0 )
  57.       {
  58.      u4error( E_INTERNAL, "remove_reference 2", (char *) 0 ) ;
  59.      return -1 ;
  60.       }
  61.       memcpy( &save_key, key_ptr, v4index[index_ref].group_len ) ;
  62.       block_ptr->num_keys-- ;
  63.    }
  64.    else
  65.    {
  66.       key_ptr   =  b4key(index_ref ) ;
  67.       if ( key_ptr == (KEY *) 0 )
  68.       {
  69.      u4error( E_INTERNAL, "remove_reference 3", (char *) 0 ) ;
  70.      return -1 ;
  71.       }
  72.       memcpy( &save_key, key_ptr, v4index[index_ref].group_len ) ;
  73.       b4remove( index_ref ) ;
  74.  
  75.       key_ptr   =  b4key(index_ref ) ;
  76.       if ( key_ptr == (KEY *) 0 )
  77.       {
  78.      u4error( E_INTERNAL, "remove_reference 4", (char *) 0 ) ;
  79.      return -1 ;
  80.       }
  81.       save_key.file_block =  key_ptr->file_block ;
  82.    }
  83.  
  84.    if ( block_ptr->num_keys > 0 )
  85.    {
  86.       if ( i4add( index_ref, save_key.value, save_key.rec_num) != 0) return -1;
  87.       return 0 ;
  88.    }
  89.  
  90.    block_ptr->key_on =  0 ;
  91.  
  92.    key_ptr =  b4key(index_ref ) ;
  93.    if ( key_ptr == (KEY *) 0 )
  94.    {
  95.       u4error( E_INTERNAL, "remove_reference 3", (char *) 0 ) ;
  96.       return -1 ;
  97.    }
  98.  
  99.    /* Check for Root Block */
  100.    if ( block_ptr->file_block == v4index[index_ref].root  )
  101.    {
  102.       v4index[index_ref].root =  save_key.file_block ;
  103.       if ( b4remove_blk(index_ref) < 0 )  return -1 ;
  104.       if ( i4add(index_ref, save_key.value, save_key.rec_num) != 0) return -1;
  105.       return 0 ;
  106.    }
  107.  
  108.    if (b4remove_blk(index_ref) < 0)  return -1 ;
  109.  
  110.    key_ptr =  b4key(index_ref ) ;
  111.    if ( key_ptr == (KEY *) 0 ) 
  112.    {
  113.       u4error( E_INTERNAL, "remove_reference 4", (char *) 0 ) ;
  114.       return -1 ;
  115.    }
  116.  
  117.    key_ptr->file_block =  save_key.file_block ;
  118.    v4block[ v4index[index_ref].block_ref].wrt = 1 ;
  119.  
  120.    /* Add the Saved Key */
  121.    if ( i4add( index_ref, save_key.value, save_key.rec_num ) != 0 )  return -1 ;
  122.  
  123.    return 0 ;
  124. }
  125.  
  126.  
  127. /* Algorithm:  (Always call with leaf initially.)
  128.  
  129.    A. Leaf key.
  130.       1.  Remove Key
  131.       2.  Write & Return if block not empty.
  132.       3.  Write & Return if block is the Root.
  133.       4.  Remove Key Block Reference in the Next Level
  134. */
  135.  
  136. static  remove_key( index_ref ) 
  137. int  index_ref ;
  138. {
  139.    BLOCK *block_ptr ;
  140.  
  141.    block_ptr =  v4block +  v4index[index_ref].block_ref ;
  142.    if ( block_ptr->num_keys <= 0 )  
  143.    {
  144.       u4error( E_INTERNAL, "remove_key", (char *) 0 ) ;
  145.       return -1 ;
  146.    }
  147.  
  148.    b4remove( index_ref ) ;
  149.    if ( block_ptr->num_keys > 0 )   return 0 ;
  150.  
  151.    /* Check for Root Block */
  152.    if ( block_ptr->file_block == v4index[index_ref].root )  return 0 ;
  153.  
  154.    /* Remove Block */
  155.    if ( b4remove_blk(index_ref) < 0 )  return -1 ;
  156.  
  157.    return( remove_reference(index_ref) )  ;
  158. }
  159.  
  160.  
  161. i4remove( index_ref, value_ptr, rec_num )
  162. int    index_ref ;
  163. char  *value_ptr ;
  164. long   rec_num   ;
  165. {
  166.    KEY    *key_ptr, *next_key_ptr ;
  167.    int     rc ;
  168.    BLOCK  *block_ptr ;
  169.    INDEX  *index_ptr ;
  170.  
  171.    index_ptr =  v4index +  index_ref ;
  172.    if ( i4lock( index_ref, 1 ) < 0 )  return -1 ;
  173.  
  174.    rc = i4go( index_ref, value_ptr, rec_num ) ;
  175.    if ( rc <  0 )  return( -1 ) ;
  176.    if ( rc >= 1 )  return(  1 ) ;
  177.  
  178.    index_ptr->version =  index_ptr->old_version + 1 ;
  179.  
  180.    if ( ! b4leaf(index_ref) )
  181.    {
  182.       /* Flip the Keys */
  183.       key_ptr =  b4key( index_ref ) ;
  184.       if ( key_ptr == (KEY *) 0 )
  185.       {
  186.      u4error( E_INTERNAL, "Routine i4remove", (char *) 0 ) ;
  187.      return -1 ;
  188.       }
  189.       block_ptr =  v4block+  index_ptr->block_ref ;
  190.  
  191.       rc =  (int)  i4skip( index_ref, -1L ) ;
  192.       if ( rc != -1 ) 
  193.       {
  194.      u4error( E_INTERNAL, "Routine i4remove 2", (char *) 0 ) ;
  195.      return -1 ;
  196.       }
  197.  
  198.       next_key_ptr =  b4key( index_ref ) ;
  199.       if ( next_key_ptr == (KEY *) 0 ) 
  200.       {
  201.      u4error( E_INTERNAL, "Routine i4remove", (char *) 0 ) ;
  202.      return -1 ;
  203.       }
  204.  
  205.       memmove( key_ptr->value, next_key_ptr->value, index_ptr->key_len ) ;
  206.       key_ptr->rec_num =  next_key_ptr->rec_num ;
  207.  
  208.       block_ptr->wrt =  1 ;
  209.    }
  210.  
  211.    if ( remove_key( index_ref ) < 0 )   return -1 ;
  212.  
  213.    return 0 ;
  214. }
  215.  
  216. #else
  217.  
  218. i4remove( i_ref, value_ptr, rec_num )  /* dBASE Version */
  219. int    i_ref ;
  220. char  *value_ptr ;
  221. long   rec_num   ;
  222. {
  223.    INDEX  *i_ptr ;
  224.    BLOCK  *block_ptr ;
  225.    char   *from_ptr, *to_ptr ;
  226.    int     rc, key_last ;
  227.  
  228.    i_ptr=  v4index +  i_ref ;
  229.  
  230.    rc = i4seek( i_ref, value_ptr ) ;
  231.  
  232.    if ( rc <  0 )  return( -1 ) ;
  233.    if ( rc >= 2 )  return(  1 ) ;
  234.  
  235.    while ( rec_num != b4key(i_ref)->rec_num )
  236.    {
  237.       rc = (int) i4skip( i_ref, 1L ) ;
  238.       if ( rc == -1 )  return( -1 ) ;
  239.       if ( rc ==  0 )  return(  1 ) ;
  240.  
  241.       if ( i4keycmp( i_ref, b4key(i_ref)->value, value_ptr) != 0 )
  242.        return( 1 ) ;
  243.    }
  244.  
  245.    i_ptr->version =  i_ptr->old_version + 1 ;
  246.  
  247.    /* Remove the current key */
  248.    for (;;)
  249.    {
  250.       block_ptr =  v4block + i_ptr->block_ref ;
  251.       key_last =  block_ptr->num_keys ;
  252.       if ( b4leaf(i_ref))   key_last-- ;
  253.  
  254.       if ( block_ptr->key_on == key_last  &&  key_last > 0 )
  255.       {
  256.      /* The current blocks last key is going to disapear
  257.         and there are additional keys left.
  258.         Conseqently, a higher entry's key pointer needs to be adjusted.
  259.      */
  260.  
  261.      from_ptr =  block_ptr->key.value + i_ptr->group_len*(block_ptr->key_on-1) ;
  262.  
  263.      while ( block_ptr->prev >= 0 )
  264.      {
  265.         block_ptr =  v4block + block_ptr->prev ;
  266.   
  267.         if ( block_ptr->key_on < block_ptr->num_keys )
  268.         {
  269.            to_ptr =  block_ptr->key.value + i_ptr->group_len*block_ptr->key_on ;
  270.            memcpy( to_ptr, from_ptr, i_ptr->key_len ) ;
  271.            block_ptr->wrt =  1 ;
  272.            break ;
  273.         }
  274.      }
  275.      /* Went up to root; nothing to adjust */
  276.       }
  277.  
  278.       rc =  b4remove( i_ref) ;      
  279.       if ( rc <= 0 )
  280.       {
  281.      if ( rc < 0 )  return -1 ;
  282.  
  283.      rc = b4up( i_ref ) ;
  284.      if ( rc == -2 )
  285.      {
  286.         u4error( E_INTERNAL, "I3REMOVE", (char *) 0 ) ;
  287.         return -1 ;
  288.      }
  289.  
  290.      if ( rc == -1 )
  291.      {
  292.         /* No More Keys */
  293.         block_ptr =  v4block+ i_ptr->block_ref ;
  294.         block_ptr->wrt        = 1 ;
  295.         block_ptr->num_keys       = 0 ;
  296.         block_ptr->key.file_block = 0 ;
  297.         block_ptr->key.rec_num    = 0 ;
  298.         return 0 ;
  299.      }
  300.       }
  301.       else
  302.      return 0 ;
  303.    }
  304.  }
  305. #endif
  306.