home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 June / ccd0605.iso / LINUX / gopchop-1.1.7.tar.tar / gopchop-1.1.7.tar / gopchop-1.1.7 / src / file_buffer.c < prev    next >
C/C++ Source or Header  |  2003-08-25  |  6KB  |  235 lines

  1. /*
  2. #
  3. # Utilities for seeking around in a file stream
  4. #
  5. # $Id: file_buffer.c,v 1.2 2003/08/25 08:17:41 nemies Exp $
  6. #
  7. # Copyright (C) 2001-2003 Kees Cook
  8. # kees@outflux.net, http://outflux.net/
  9. # This program is free software; you can redistribute it and/or
  10. # modify it under the terms of the GNU General Public License
  11. # as published by the Free Software Foundation; either version 2
  12. # of the License, or (at your option) any later version.
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. # GNU General Public License for more details.
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20. # http://www.gnu.org/copyleft/gpl.html
  21. #
  22. */
  23.  
  24. /*
  25.  * buffer management inspired by mplayer
  26.  */
  27. #include "file_buffer.h"
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include <unistd.h>
  31.  
  32. struct file_buf_t
  33. {
  34.     char * filename;
  35.     FILE *fp;
  36.     uint8_t * buffer;
  37.     off_t offset;
  38.     size_t buffer_min;
  39.     size_t buffer_max;
  40.     size_t buffer_malloc;
  41. };
  42.  
  43. off_t buffer_tell(struct file_buf_t *fb)
  44. {
  45.     if (!fb) return 0;
  46.     return fb->offset - fb->buffer_max + fb->buffer_min;
  47. }
  48.  
  49. off_t buffer_file_size(struct file_buf_t *fb)
  50. {
  51.     struct stat info;
  52.  
  53.     if (!fb) return 0;
  54.     if (!(fstat(fileno(fb->fp), &info))<0) {
  55.         perror("fstat");
  56.         exit(1);
  57.     }
  58.     return info.st_size;
  59. }
  60.  
  61. // can point to a file offset to refill from
  62. int buffer_refill(struct file_buf_t *fb)
  63. {
  64.     size_t got;
  65.  
  66.     if (!fb)
  67.         return FILE_BUF_ERR_NULL_STRUCT;
  68.  
  69.     //fprintf(stderr,"filling...\n");
  70.  
  71.     if (fb->buffer_min < fb->buffer_max)
  72.     {
  73.         memmove(fb->buffer, fb->buffer + fb->buffer_min,
  74.                             fb->buffer_max - fb->buffer_min);
  75.     }
  76.     fb->buffer_max -= fb->buffer_min;
  77.     fb->buffer_min = 0;
  78.  
  79.     got =
  80.         fread(fb->buffer + fb->buffer_max, sizeof(uint8_t),
  81.               fb->buffer_malloc - fb->buffer_max, fb->fp);
  82.     if (got < 0)
  83.         return FILE_BUF_ERR_READ;
  84.  
  85.     fb->offset += got;
  86.     fb->buffer_max += got;
  87.  
  88.     //fprintf(stderr,"bump %d more\n",got);
  89.     return FILE_BUF_OKAY;
  90. }
  91.  
  92. int buffer_seek(struct file_buf_t *fb, off_t location)
  93. {
  94.     if (!fb)
  95.         return FILE_BUF_ERR_NULL_STRUCT;
  96.  
  97.     // is this location within our current buffer?
  98.     if (location < fb->offset && location >= buffer_tell(fb)) {
  99.         fb->buffer_min += location - buffer_tell(fb);
  100.     }
  101.     else {
  102.         // outside: clear the buffer 
  103.         fb->buffer_min = fb->buffer_max = 0;    // clear buffer
  104.         fb->offset = location;
  105.         if (FSEEK(fb->fp, fb->offset, SEEK_SET) < 0) {
  106.             return FILE_BUF_ERR_SEEK;
  107.         }
  108.     }
  109.     //don't do this... way too slow
  110.     //buffer_refill();
  111.     return FILE_BUF_OKAY;
  112. }
  113.  
  114. // A null return from "buffer_start" indicates that errno has been set,
  115. // and calls to "perror" and the like are valid.
  116. struct file_buf_t * buffer_start(struct file_buf_t *fb, char *filename,
  117.                                  size_t size)
  118. {
  119.     FILE * fp=NULL;
  120.     uint8_t * buffer=NULL;
  121.  
  122.     // check for fopen first, before dealing with memory allocation or
  123.     // making changes to the passed-in structure
  124.     if (!(fp = fopen(filename, "r"))) {
  125.         goto err_out;
  126.     }
  127.     if (!fb || fb->buffer_malloc != size) {
  128.         if (!(buffer=(uint8_t*)calloc(size,sizeof(uint8_t)))) {
  129.             goto err_out;
  130.         }
  131.     }
  132.     // create a buffer if it doesn't already exist
  133.     if (!fb) {
  134.         if (!(fb=(struct file_buf_t*)calloc(1,sizeof(*fb)))) {
  135.             goto err_out;
  136.         }
  137.     }
  138.     // swap out the new file handle
  139.     if (fb->fp)
  140.         fclose(fb->fp);
  141.     fb->fp = fp;
  142.  
  143.     // swap out the new buffer
  144.     if (buffer) {
  145.         // drop the old buffer if we have a new one
  146.         if (fb->buffer)
  147.             free(fb->buffer);
  148.         fb->buffer = buffer;
  149.     }
  150.     // record our buffer size
  151.     fb->buffer_malloc = size;
  152.  
  153.     // clear our counters
  154.     fb->offset = 0;
  155.     fb->buffer_min = 0;
  156.     fb->buffer_max = 0;
  157.  
  158.     return fb;
  159.  
  160. err_out:
  161.     if (buffer)
  162.         free(buffer);
  163.     if (fp)
  164.         fclose(fp);
  165.     buffer_end(fb); // hm: well I guess I *will* muck with the passed in one
  166.     return NULL;
  167. }
  168.  
  169. int buffer_end(struct file_buf_t *fb)
  170. {
  171.     if (!fb)
  172.         return FILE_BUF_ERR_NULL_STRUCT;
  173.  
  174.     if (fb->fp)
  175.         fclose(fb->fp);
  176.     if (fb->buffer)
  177.         free(fb->buffer);
  178.     free(fb);
  179.  
  180.     return FILE_BUF_OKAY;
  181. }
  182.  
  183. int buffer_get_byte(struct file_buf_t *fb, uint8_t * byte)
  184. {
  185.     int ret;
  186.  
  187.     if (!fb)
  188.         return FILE_BUF_ERR_NULL_STRUCT;
  189.     if (!byte)
  190.         return FILE_BUF_ERR_NULL_ARG;
  191.  
  192.     if (fb->buffer_min == fb->buffer_max) {
  193.         if ((ret=buffer_refill(fb))!=FILE_BUF_OKAY)
  194.             return ret;
  195.     }
  196.     if (fb->buffer_min == fb->buffer_max)
  197.         return FILE_BUF_ERR_PAST_END;
  198.  
  199.     //fprintf(stderr,"getting %" OFF_T_FORMAT "\n",buffer_tell(fb));
  200.     *byte = fb->buffer[fb->buffer_min++];
  201.     return FILE_BUF_OKAY;
  202. }
  203.  
  204. int buffer_look_ahead(struct file_buf_t *fb, uint8_t * bytes, size_t count)
  205. {
  206.     if (!fb)
  207.         return FILE_BUF_ERR_NULL_STRUCT;
  208.     if (!bytes)
  209.         return FILE_BUF_ERR_NULL_ARG;
  210.     if (count >= fb->buffer_malloc)
  211.         return FILE_BUF_ERR_COUNT_EXCEEDS_BUFFER_SIZE;
  212.  
  213.     if (fb->buffer_min + count > fb->buffer_max)
  214.         buffer_refill(fb);
  215.     if (fb->buffer_min + count > fb->buffer_max)
  216.         return FILE_BUF_ERR_PAST_END;
  217.  
  218.     memcpy(bytes,fb->buffer+fb->buffer_min,count);
  219.     /*
  220.      * for debugging:
  221.     for (i = 0; i < count; i++)
  222.     {
  223.         *(bytes++) = fb->buffer[fb->buffer_min + i];
  224.         //fprintf(stderr,"\tsaw: 0x%02X\n",buffer[buffer_min+i]);
  225.     }
  226.     */
  227.  
  228.     return FILE_BUF_OKAY;
  229. }
  230.  
  231. /* vi:set ai ts=4 sw=4 expandtab: */
  232.