home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c160 / 1.ddi / SOURCE / I4REMOVE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-22  |  7.9 KB  |  322 lines

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