home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 05 / tichnr / varray.c next >
Text File  |  1988-04-04  |  4KB  |  175 lines

  1. /*  Virtual Array Access Routines  */
  2.  
  3. #include <varray.h>
  4.  
  5. #define header 7
  6.  
  7. /****************
  8.  * init_v_array *
  9.  ****************/
  10.  
  11. int init_v_array(filename,rec_size,filchar)
  12. char *filename, filchar;
  13. int  rec_size;
  14. {
  15.    long size;
  16.    FILE *f;
  17.    f = fopen(filename,"wb");
  18.    if (f != NULL) {    
  19.       size = 0;
  20.       fwrite(&size,4,1,f);         /* write array size of zero */
  21.       fwrite(&rec_size,2,1,f);     /* and array element size   */
  22.       fwrite(&filchar,1,1,f);      /* and fill char            */
  23.       fclose(f);                   /* to file header */
  24.       return(1);
  25.    }
  26.    else
  27.       return(NULL);
  28. }
  29.  
  30. /****************
  31.  * open_v_array *
  32.  ****************/
  33.  
  34. VACB *open_v_array(filename,buffer_size)
  35. char *filename;
  36. int  buffer_size;
  37. {
  38.    VACB *v_array;
  39.    char *buf_ptr;
  40.    int  i;
  41.    char filchar;
  42.  
  43.    /* allocate virtual array control block */
  44.  
  45.    v_array = (VACB *) malloc(sizeof(VACB));
  46.    if (v_array == NULL) return(NULL);
  47.  
  48.    /* open virtual array file */
  49.  
  50.    v_array->file = fopen(filename,"r+b");
  51.    if (v_array->file == NULL) {
  52.       free(v_array);
  53.       return(NULL);
  54.    };
  55.  
  56.    /* get array size and element size for control block */
  57.  
  58.    fread(&v_array->size,4,1,v_array->file);
  59.    fread(&v_array->elsize,2,1,v_array->file);
  60.    fread(&filchar,1,1,v_array->file);
  61.    v_array->buf_elsize = v_array->elsize + 4;
  62.  
  63.    /* allocate buffer */
  64.  
  65.    v_array->buffer = (char *) malloc(v_array->buf_elsize * (buffer_size + 1));
  66.    if (v_array->buffer == NULL) {
  67.       fclose(v_array->file);
  68.       free(v_array);
  69.       return(NULL);
  70.    };
  71.    v_array->buf_size = buffer_size;
  72.  
  73.    /* set up blank_rec using the fill character in array header */
  74.    /* for initializing new array elements */
  75.  
  76.    buf_ptr = v_array->buffer + v_array->buf_elsize * v_array->buf_size;
  77.    v_array->blank_rec = buf_ptr + 4;
  78.    for (i=0; i < v_array->buf_elsize; i++)
  79.       *buf_ptr++ = filchar;    
  80.  
  81.    /* set record index negative for all buffer elements   */
  82.  
  83.    buf_ptr = v_array->buffer;
  84.    for (i = 0; i < v_array->buf_size; i++) {
  85.       *((long *)buf_ptr) = -1L;        
  86.       buf_ptr += v_array->buf_elsize;    
  87.    };
  88.    return(v_array);
  89. }
  90.  
  91. /*****************
  92.  * close_v_array *
  93.  *****************/
  94.  
  95. void close_v_array(v_array)
  96. VACB *v_array;
  97. {
  98.    int  i;
  99.    char *buf_ptr;
  100.    long rec_index, file_offset;
  101.  
  102.    buf_ptr = v_array->buffer;
  103.  
  104.    /*  flush buffer */
  105.  
  106.    for (i=0; i < v_array->buf_size; i++) {
  107.  
  108.       /* check each element index */
  109.       /* if element present, write it to disk */
  110.  
  111.       rec_index = *((long *)buf_ptr);
  112.       if (rec_index >= 0) {
  113.      file_offset = header + rec_index * v_array->elsize;
  114.      fseek(v_array->file,file_offset,0);
  115.      fwrite(buf_ptr + 4, v_array->elsize,1, v_array->file);
  116.       };
  117.       buf_ptr += v_array->buf_elsize;
  118.    };
  119.    free(v_array->buffer);     /* de-allocate buffer */
  120.    fclose(v_array->file);     /* close array file   */
  121.    free(v_array);             /* de-allocate VACB   */
  122. }
  123.  
  124. /****************
  125.  * access_v_rec *
  126.  ****************/
  127.  
  128. void *access_v_rec(v_array,index)
  129. VACB *v_array;
  130. long index;
  131. {
  132.    char *buf_ptr;
  133.    int  buf_index;
  134.    long rec_index, temp_index;
  135.  
  136.    /* calculate buffer address of referenced element */
  137.  
  138.    buf_index = index % v_array->buf_size;
  139.    buf_ptr = v_array->buffer + buf_index * v_array->buf_elsize;
  140.    rec_index = *(long *)buf_ptr;
  141.  
  142.    /* if element present, return its buffer address */
  143.  
  144.    if (rec_index == index) return(buf_ptr + 4);
  145.  
  146.    /* if element doesn't exist, extend the file */
  147.  
  148.    if (index >= v_array->size) {
  149.       fseek(v_array->file,0,2);
  150.       for (temp_index = v_array->size; temp_index++ <= index; )
  151.      fwrite(v_array->blank_rec, v_array->elsize, 1, v_array->file);
  152.       v_array->size = index + 1;
  153.       fseek(v_array->file,0,0);
  154.       fwrite(&v_array->size, 4, 1, v_array->file);
  155.    };
  156.  
  157.    /* if buffer slot is occupied by another element, */
  158.    /* save it to disk */
  159.  
  160.    if (rec_index >= 0) {
  161.       fseek(v_array->file, rec_index * v_array->elsize + header, 0);
  162.       fwrite(buf_ptr + 4, v_array->elsize, 1, v_array->file);
  163.    };
  164.  
  165.    /* read referenced element into buffer slot */
  166.  
  167.    fseek(v_array->file, index * v_array->elsize + header, 0);
  168.    fread(buf_ptr + 4, v_array->elsize, 1, v_array->file);
  169.    *((long *)buf_ptr) = index;
  170.  
  171.    /* return address of element in buffer */
  172.  
  173.    return(buf_ptr + 4);
  174. }
  175.