home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2068 / sqread.c next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  4.8 KB  |  239 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <signal.h>
  4. #include <ctype.h>
  5. #include <limits.h>
  6. #include <mem.h>
  7. #define INTERNAL
  8. #include "sqread.h"
  9.  
  10. #define ERROR (-1)
  11. #define PATHLEN    312    /* Number of characters allowed in pathname */
  12. #define OK 0
  13.  
  14. #define RECOGNIZE 0xFF76    /* unlikely pattern */
  15. #define DLE 0x90        /* repeat byte flag */
  16. #define SPEOF 256        /* special endfile token */
  17. #define NUMVALS 257        /* 256 data values plus SPEOF*/
  18.  
  19. static int getuhuff(SQFILE *sqp);
  20. static int portgetw(FILE *f);
  21.  
  22. /* BUG: you cannot select an arbitrary position in the output stream
  23.  * to start your output (unless you make provisions for that).  This is
  24.  * because of the repeat compression.  You can make provision for seeking
  25.  * to the middle of a repeat sequence by terminating the repeat when
  26.  * compressing the file.
  27.  */
  28.  
  29. SQFILE *
  30. sqopen    (const char *path)
  31. {
  32.     FILE *fp;
  33.     SQFILE *sqp;
  34.     int numnodes;
  35.     int i;
  36.  
  37.     fp = fopen(path, "rb");
  38.     if (!fp)
  39.         return NULL;
  40.     sqp = malloc(sizeof(SQFILE));
  41.     if (!sqp)
  42.         return NULL;
  43.     sqp->file = fp;
  44.     if(portgetw(fp) != (int) RECOGNIZE) {/* Process header */
  45.         rewind(sqp->file);
  46.         sqp->issq = 0;
  47.         return sqp;
  48.     }
  49.     sqp->issq = 1;
  50.     (void) portgetw(fp);        /* checksum */
  51.     while (getc(fp))        /* Read and discard the name */
  52.         ;
  53.  
  54.     numnodes = portgetw(fp);
  55.     if(numnodes < 0 || numnodes >= NUMVALS) {
  56.         /* invalid decode tree */
  57.         fclose(fp);
  58.         return NULL;
  59.     }
  60.     /* Initialize for possible empty tree (SPEOF only) */
  61.     sqp->sqleaf[0].children[0] = -(SPEOF + 1);
  62.     sqp->sqleaf[0].children[1] = -(SPEOF + 1);
  63.  
  64.     for(i = 0; i < numnodes; ++i) {    /* Get decoding tree from file */
  65.         sqp->sqleaf[i].children[0] = portgetw(fp);
  66.         sqp->sqleaf[i].children[1] = portgetw(fp);
  67.     }
  68.     sqp->rewpos = ftell(sqp->file);
  69.     sqp->bpos = 7;            /* force initial read */
  70.     sqp->repct = 0;            /* start with no repeats */
  71.     return sqp;
  72. }
  73.  
  74. void
  75. sqrewind(SQFILE *sqp)
  76. {
  77.     sqp->bpos = 7;            /* force initial read */
  78.     sqp->repct = 0;            /* start with no repeats */
  79.     fseek(sqp->file, sqp->rewpos, SEEK_SET);
  80. }
  81.  
  82.  
  83. /* The "offset" is actually a bit offset within the file.  Offset 0 is
  84.  * bit 0, byte 0.  Offset 8 is bit 0, byte 1.  Etc...
  85.  */
  86. long
  87. sqseek(SQFILE *sqp, long offset)
  88. {
  89.     int bpos;
  90.     long value;
  91.  
  92.     if (!sqp->issq)
  93.         return fseek(sqp->file, offset, SEEK_SET);
  94.  
  95.     bpos = offset & 7;
  96.     value = fseek(sqp->file, offset >> 3, SEEK_SET);
  97.     if (bpos == 0) {
  98.         sqp->bpos = 7;
  99.     } else {
  100.         sqp->bpos = bpos - 1;
  101.         sqp->curin = getc(sqp->file) >> (bpos - 1);
  102.     }
  103.     sqp->repct = 0;            /* start with no repeats */
  104.     return value;
  105. }
  106.  
  107.  
  108. /* Get bytes with decoding - this decodes repetition,
  109.  * calls getuhuff to decode file stream into byte
  110.  * level code with only repetition encoding.
  111.  *
  112.  * The code is simple passing through of bytes except
  113.  * that DLE is encoded as DLE-zero and other values
  114.  * repeated more than twice are encoded as value-DLE-count.
  115.  */
  116.  
  117. int
  118. sqgetc(SQFILE *sqp)
  119. {
  120.     int c;
  121.  
  122.     if (!sqp->issq)
  123.         return getc(sqp->file);
  124.  
  125.     if(sqp->repct > 0) {
  126.         /* Expanding a repeated char */
  127.         --sqp->repct;
  128.         return(sqp->value);
  129.     } else {
  130.         /* Nothing unusual */
  131.         if((c = getuhuff(sqp)) != DLE) {
  132.             /* It's not the special delimiter */
  133.             sqp->value = c;
  134.             if(sqp->value == EOF)
  135.                 sqp->repct = INT_MAX;
  136.             return(sqp->value);
  137.         } else {
  138.             /* Special token */
  139.             if((sqp->repct = getuhuff(sqp)) == 0)
  140.                 /* DLE, zero represents DLE */
  141.                 return(DLE);
  142.             else {
  143.                 /* Begin expanding repetition */
  144.                 sqp->repct -= 2;    /* 2nd time */
  145.                 return(sqp->value);
  146.             }
  147.         }
  148.     }
  149. }
  150.  
  151.  
  152. /* Decode file stream into a byte level code with only
  153.  * repetition encoding remaining.
  154.  */
  155. static int
  156. getuhuff(SQFILE *sqp)
  157. {
  158.     int i;
  159.  
  160.     /* Follow bit stream in tree to a leaf*/
  161.     i = 0;    /* Start at root of tree */
  162.     do {
  163.         if(++sqp->bpos > 7) {
  164.             if((sqp->curin = getc(sqp->file)) == EOF)
  165.                 return(ERROR);
  166.             sqp->bpos = 0;
  167.             /* move a level deeper in tree */
  168.             i = sqp->sqleaf[i].children[1 & sqp->curin];
  169.         } else
  170.             i = sqp->sqleaf[i].children[1 & (sqp->curin >>= 1)];
  171.     } while(i >= 0);
  172.  
  173.     /* Decode fake node index to original data value */
  174.     i = -(i + 1);
  175.     /* Decode special endfile token to normal EOF */
  176.     return(i == SPEOF) ? EOF : i;
  177. }
  178.  
  179.  
  180. char
  181. *sqgets    (char *s, int n, SQFILE *sqp)
  182. {
  183.     int c = '\0';
  184.  
  185.     while (c != '\n' && n > 1) {
  186.         if ((c = sqgetc(sqp)) == EOF)
  187.             return NULL;
  188.         if (c == '\r')
  189.             continue;
  190.         *s++ = c;
  191.         --n;
  192.     }
  193.     *s = '\0';
  194.     return s;
  195. }
  196.  
  197.  
  198. long
  199. sqtell    (SQFILE *sqp)
  200. {
  201.     if (!sqp->issq)
  202.         return ftell(sqp->file);
  203.     return (ftell(sqp->file) << 3) + sqp->bpos;
  204. }
  205.  
  206.  
  207. long
  208. sqsize    (SQFILE *sqp)
  209. {
  210.     fseek(sqp->file, 0, SEEK_END);
  211.     if (!sqp->issq)
  212.         return ftell(sqp->file);
  213.     return (ftell(sqp->file) << 3) + 7;
  214. }
  215.  
  216.  
  217. int
  218. sqclose   (SQFILE *sqp)
  219. {
  220.     int value = fclose(sqp->file);
  221.     free(sqp);
  222.     return value;
  223. }
  224.  
  225.  
  226. /*
  227.  * Machine independent getw which always gets bytes in the same order
  228.  *  as the CP/M version of SQ wrote them
  229.  */
  230. static int
  231. portgetw(f)
  232. FILE *f;
  233. {
  234.     int c;
  235.  
  236.     c = getc(f) & 0377;
  237.     return(c | (getc(f) << 8));
  238. }
  239.