home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xloadimg.zip / xloadimage.4.1 / zio.c < prev    next >
C/C++ Source or Header  |  1993-10-28  |  7KB  |  302 lines

  1. /* zio.c:
  2.  *
  3.  * this properly opens and reads from an image file, compressed or otherwise.
  4.  *
  5.  * jim frost 10.03.89
  6.  *
  7.  * this was hacked on 09.12.90 to cache reads and to use stdin.
  8.  *
  9.  * Copyright 1989, 1990 Jim Frost.  See included file "copyright.h" for
  10.  * complete copyright information.
  11.  */
  12.  
  13. #include "copyright.h"
  14. #include "image.h"
  15.  
  16. #ifdef VMS
  17. #define NO_PIPES /* VMS doesn't have pipes */
  18. #endif
  19. #ifndef NO_PIPES
  20. extern struct filter *Filters;
  21. #endif
  22.  
  23. #define MAX_ZFILES 32
  24.  
  25. static ZFILE ZFileTable[MAX_ZFILES];
  26.  
  27. /* read some info through the read cache
  28.  */
  29.  
  30. static int doRead(zf, buf, len)
  31.      ZFILE *zf;
  32.      byte *buf;
  33.      int len;
  34. { int bread, readlen;
  35.  
  36.   /* loop through the read
  37.    */
  38.  
  39.   for (bread= 0; bread < len; bread += readlen, zf->bufptr += readlen) {
  40.  
  41.     /* read new or move to next data block if necessary
  42.      */
  43.  
  44.     if (!zf->dataptr || (zf->bufptr == zf->dataptr->len)) {
  45.       if (zf->dataptr && (zf->dataptr->len == 0)) /* EOF */
  46.     return(bread);
  47.       if (zf->dataptr && zf->dataptr->next) {
  48.     zf->dataptr= zf->dataptr->next;
  49.       }
  50.       else {
  51.     if (!zf->dataptr) {
  52.  
  53.       /* if the reader told us to stop caching, just do the read.
  54.        */
  55.       if (zf->nocache)
  56.         return(fread(zf->dataptr->buf, 1, BUFSIZ, zf->stream));
  57.       zf->data= zf->dataptr= (struct cache *)lmalloc(sizeof(struct cache));
  58.     }
  59.     else {
  60.       zf->dataptr->next= (struct cache *)lmalloc(sizeof(struct cache));
  61.       zf->dataptr= zf->dataptr->next;
  62.     }
  63.     zf->dataptr->next= NULL;
  64.     zf->dataptr->len= fread(zf->dataptr->buf, 1, BUFSIZ, zf->stream);
  65.     if (zf->dataptr->len < 0) {
  66.       perror("fread");
  67.       exit(1);
  68.     }
  69.       }
  70.       zf->bufptr= 0;
  71.     }
  72.  
  73.     /* calculate length we can get out of read buffer
  74.      */
  75.  
  76.     readlen= (len - bread > zf->dataptr->len - zf->bufptr ?
  77.           zf->dataptr->len - zf->bufptr : len - bread);
  78.     if (!readlen) /* we're at EOF */
  79.       return(bread);
  80.     bcopy(zf->dataptr->buf + zf->bufptr, buf + bread, readlen);
  81.   }
  82.   return(bread);
  83. }
  84.  
  85. /* reset a read cache
  86.  */
  87.  
  88. void zreset(filename)
  89.      char *filename;
  90. { int a;
  91.   struct cache *old;
  92.  
  93.   /* if NULL filename, reset the entire table
  94.    */
  95.  
  96.   if (!filename) {
  97.     for (a= 0; a < MAX_ZFILES; a++)
  98.       if (ZFileTable[a].filename)
  99.     zreset(ZFileTable[a].filename);
  100.     return;
  101.   }
  102.  
  103.   for (a= 0; a < MAX_ZFILES; a++)
  104.     if (ZFileTable[a].filename && !strcmp(filename, ZFileTable[a].filename))
  105.       break;
  106.  
  107.   if (a == MAX_ZFILES) /* no go joe */
  108.     return;
  109.  
  110.   if (ZFileTable[a].dataptr != ZFileTable[a].data)
  111.     fprintf(stderr, "zreset: warning: ZFILE for %s was not closed properly\n",
  112.        ZFileTable[a].filename);
  113.   while (ZFileTable[a].data) {
  114.     old= ZFileTable[a].data;
  115.     ZFileTable[a].data= ZFileTable[a].data->next;
  116.     free(old);
  117.   }
  118.   lfree((byte *)ZFileTable[a].filename);
  119.   ZFileTable[a].filename= NULL;
  120.   ZFileTable[a].dataptr= NULL;
  121.   ZFileTable[a].bufptr= 0;
  122.   ZFileTable[a].nocache= 0;
  123.  
  124.   switch(ZFileTable[a].type) {
  125.   case ZSTANDARD:
  126.     fclose(ZFileTable[a].stream);
  127.     break;
  128. #ifndef NO_PIPES
  129.   case ZPIPE:
  130.     pclose(ZFileTable[a].stream);
  131.     break;
  132. #endif /* NO_PIPES */
  133.   case ZSTDIN:
  134.     break;
  135.   default:
  136.     fprintf(stderr, "zreset: bad ZFILE structure\n");
  137.     exit(1);
  138.   }
  139. }
  140.  
  141. ZFILE *zopen(name)
  142.      char *name;
  143. { int    a;
  144.   ZFILE *zf;
  145.   char   buf[BUFSIZ];
  146.   struct filter *filter;
  147.  
  148.   debug(("zopen(\"%s\") called\n", name));
  149.  
  150.   /* look for filename in open file table
  151.    */
  152.  
  153.   for (a= 0; a < MAX_ZFILES; a++)
  154.     if (ZFileTable[a].filename && !strcmp(name, ZFileTable[a].filename)) {
  155.  
  156.       /* if we try to reopen a file whose caching was disabled, warn the user
  157.        * and try to recover.  we cannot recover if it was stdin.
  158.        */
  159.  
  160.       if (ZFileTable[a].nocache) {
  161.     if (ZFileTable[a].type == ZSTDIN) {
  162.       fprintf(stderr, "zopen: caching was disabled by previous caller; can't reopen stdin\n");
  163.       return(NULL);
  164.     }
  165.     fprintf(stderr, "zopen: warning: caching was disabled by previous caller\n");
  166.     zreset(ZFileTable[a].filename);
  167.     break;
  168.       }
  169.       if (ZFileTable[a].dataptr != ZFileTable[a].data)
  170.     fprintf(stderr, "zopen: warning: file doubly opened\n");
  171.       ZFileTable[a].dataptr= ZFileTable[a].data;
  172.       ZFileTable[a].bufptr= 0;
  173.       return(ZFileTable + a);
  174.     }
  175.  
  176.   /* find open ZFileTable entry
  177.    */
  178.  
  179.   for (a= 0; (a < MAX_ZFILES) && ZFileTable[a].filename; a++)
  180.     /* EMPTY */
  181.     ;
  182.  
  183.   if (a == MAX_ZFILES) {
  184.     fprintf(stderr, "zopen: no more files available\n");
  185.     exit(1);
  186.   }
  187.   zf= ZFileTable + a;
  188.  
  189.   zf->filename= dupString(name);
  190.   zf->dataptr= NULL;
  191.   zf->bufptr= 0;
  192.   zf->nocache= 0;
  193.  
  194.   /* file filename is `stdin' then use stdin
  195.    */
  196.  
  197.   if (!strcmp(name, "stdin")) {
  198.     zf->type= ZSTDIN;
  199.     zf->stream= stdin;
  200.     return(zf);
  201.   }
  202.  
  203. #ifndef NO_PIPES
  204.   /* check suffix against the table of filters and invoke the filter
  205.    * if necessary.  if your system doesn't support pipes you can
  206.    * define NO_PIPES and this will not happen.
  207.    */
  208.  
  209.   for (filter= Filters; filter; filter= filter->next) {
  210.     if ((strlen(name) > strlen(filter->extension)) &&
  211.     !strcmp(filter->extension,
  212.         name + (strlen(name) - strlen(filter->extension)))) {
  213.       debug(("Filtering image through '%s'\n", filter->filter));
  214.       zf->type= ZPIPE;
  215.       sprintf(buf, "%s %s", filter->filter, name);
  216.       if (! (zf->stream= popen(buf, "r"))) {
  217.     lfree((byte *)zf->filename);
  218.     zf->filename= NULL;
  219.     return(NULL);
  220.       }
  221.       return(zf);
  222.     }
  223.   }
  224. #endif /* !NO_PIPES */
  225.  
  226.   /* default to normal stream
  227.    */
  228.  
  229.   zf->type= ZSTANDARD;
  230.   if (!
  231. #ifdef VMS
  232.       (zf->stream= fopen(name, "r", "ctx=bin", "ctx=stm", "rfm=stmlf"))
  233. #else
  234.       (zf->stream= fopen(name, "r"))
  235. #endif
  236.       ) {
  237.     lfree((byte *)zf->filename);
  238.     zf->filename= NULL;
  239.     return(NULL);
  240.   }
  241.   return(zf);
  242. }
  243.  
  244. int zread(zf, buf, len)
  245.      ZFILE        *zf;
  246.      byte         *buf;
  247.      unsigned int  len;
  248. {
  249.   return(doRead(zf, buf, len));
  250. }
  251.  
  252. int zgetc(zf)
  253.      ZFILE *zf;
  254. { unsigned char c;
  255.  
  256.   if (doRead(zf, &c, 1) > 0)
  257.     return(c);
  258.   else
  259.     return(EOF);
  260. }
  261.  
  262. char *zgets(buf, size, zf)
  263.      byte         *buf;
  264.      unsigned int  size;
  265.      ZFILE        *zf;
  266. { int p= 0;
  267.  
  268.   while (doRead(zf, buf + p, 1) > 0) {
  269.     if (p == size)
  270.       return((char *)buf);
  271.     if (*(buf + p) == '\n') {
  272.       *(buf + p + 1)= '\0';
  273.       return((char *)buf);
  274.     }
  275.     p++;
  276.   }
  277.   return(NULL);
  278. }
  279.  
  280. /* this turns off caching when an image has been identified and we will not
  281.  * need to re-open it
  282.  */
  283.  
  284. void znocache(zf)
  285.      ZFILE *zf;
  286. {
  287.   debug(("znocache(\"%s\") called\n", zf->filename));
  288.   zf->nocache= 1;
  289. }
  290.  
  291. /* reset cache pointers in a ZFILE.  nothing is actually reset until a
  292.  * zreset() is called with the filename.
  293.  */
  294.  
  295. void zclose(zf)
  296.      ZFILE *zf;
  297. {
  298.   debug(("zclose(\"%s\") called\n", zf->filename));
  299.   zf->dataptr= zf->data;
  300.   zf->bufptr= 0;
  301. }
  302.