home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / boozshar / lzd.c < prev    next >
C/C++ Source or Header  |  1989-05-29  |  6KB  |  217 lines

  1. /*
  2. Lempel-Ziv decompression.  Mostly based on Tom Pfau's assembly language
  3. code.  The contents of this file are hereby released to the public domain.
  4.                                  -- Rahul Dhesi 1986/11/14, 1987/02/08
  5. */
  6.  
  7. #include "func.h"
  8. #include "options.h"
  9.  
  10. #define  INBUFSIZ    (IN_BUF_SIZE - SPARE)
  11. #define  OUTBUFSIZ   (OUT_BUF_SIZE - SPARE)
  12. #define  MEMERR      2
  13. #define  IOERR       1
  14. #define  MAXBITS     13
  15. #define  CLEAR       256         /* clear code */
  16. #define  Z_EOF       257         /* end of file marker */
  17. #define  FIRST_FREE  258         /* first free code */
  18. #define  MAXMAX      8192        /* max code + 1 */
  19.  
  20. #define  SPARE       5
  21.  
  22. struct tabentry {
  23.    unsigned next;
  24.    char z_ch;
  25. };
  26.  
  27. struct tabentry *table;
  28. int   gotmem = 0;
  29.  
  30. int init_dtab();
  31. unsigned rd_dcode();
  32. int wr_dchar();
  33. int ad_dcode();
  34.  
  35. unsigned lzd_sp = 0;
  36. unsigned lzd_stack[STACKSIZE + SPARE];
  37.  
  38. int push(ch)
  39. int ch;
  40. {
  41.    lzd_stack[lzd_sp++] = ch;
  42.    if (lzd_sp >= STACKSIZE)
  43.       prterror ('f', "Stack overflow in lzd()\n", (char *) 0, (char *) 0);
  44. }
  45.    
  46. #define  pop()    (lzd_stack[--lzd_sp])
  47.  
  48. char out_buf_adr[IN_BUF_SIZE + SPARE];
  49. char in_buf_adr[OUT_BUF_SIZE + SPARE];
  50.  
  51. char memflag = 0;                /* memory allocated? flag */
  52.  
  53. unsigned cur_code;
  54. unsigned old_code;
  55. unsigned in_code;
  56.  
  57. unsigned free_code;
  58. int nbits;
  59. unsigned max_code;
  60.  
  61. char fin_char;
  62. char k;
  63. unsigned masks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
  64.                         0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff };
  65. unsigned bit_offset;
  66. unsigned output_offset;
  67. int in_han, out_han; 
  68.  
  69. int lzd(input_handle, output_handle)
  70. int input_handle, output_handle;          /* input & output file handles */
  71. {
  72.    in_han = input_handle;                 /* make it avail to other fns */
  73.    out_han = output_handle;               /* ditto */
  74.    nbits = 9;
  75.    max_code = 512;
  76.    free_code = FIRST_FREE;
  77.    lzd_sp = 0;
  78.    bit_offset = 0;
  79.    output_offset = 0;
  80.  
  81.    if (gotmem == 0) {
  82.       table = (struct tabentry *) 
  83.          malloc (MAXMAX * sizeof (struct tabentry) + SPARE);
  84.       gotmem++;
  85.    }
  86.    if (table == (struct tabentry *) 0)
  87.       memerr();
  88.  
  89.    if (read(in_han, in_buf_adr, INBUFSIZ) == -1)
  90.       return(IOERR);
  91.  
  92.    init_dtab();             /* initialize table */
  93.  
  94. loop:
  95.    cur_code = rd_dcode();
  96.    if (cur_code == Z_EOF) {
  97.       if (output_offset != 0) {
  98.          if (out_han != -2) {
  99.             if (write(out_han, out_buf_adr, output_offset) != output_offset)
  100.                prterror ('f', "Output error in lzd()\n", 
  101.                         (char *) 0, (char *) 0);
  102.          }
  103.          addbfcrc(out_buf_adr, output_offset);
  104.       }
  105.       return (0);
  106.    }
  107.  
  108.    if (cur_code == CLEAR) {
  109.       init_dtab();
  110.       fin_char = k = old_code = cur_code = rd_dcode();
  111.       wr_dchar(k);
  112.       goto loop;
  113.    }
  114.  
  115.    in_code = cur_code;
  116.    if (cur_code >= free_code) {        /* if code not in table (k<w>k<w>k) */
  117.       cur_code = old_code;             /* previous code becomes current */
  118.       push(fin_char);
  119.    }
  120.  
  121.    while (cur_code > 255) {               /* if code, not character */
  122.       push(table[cur_code].z_ch);         /* push suffix char */
  123.       cur_code = table[cur_code].next;    /* <w> := <w>.code */
  124.    }
  125.  
  126.    k = fin_char = cur_code;
  127.    push(k);
  128.    while (lzd_sp != 0) {
  129.       wr_dchar(pop());
  130.    }
  131.    ad_dcode();
  132.    old_code = in_code;
  133.  
  134.    goto loop;
  135. } /* lzd() */
  136.  
  137. /* rd_dcode() reads a code from the input (compressed) file and returns
  138. its value. */
  139. unsigned rd_dcode()
  140. {
  141.    register char *ptra, *ptrb;    /* miscellaneous pointers */
  142.    unsigned word;                     /* first 16 bits in buffer */
  143.    unsigned byte_offset;
  144.    char nextch;                           /* next 8 bits in buffer */
  145.    unsigned ofs_inbyte;               /* offset within byte */
  146.  
  147.    ofs_inbyte = bit_offset % 8;
  148.    byte_offset = bit_offset / 8;
  149.    bit_offset = bit_offset + nbits;
  150.  
  151.    if (byte_offset >= INBUFSIZ - 5) {
  152.       int space_left;
  153.  
  154.       bit_offset = ofs_inbyte + nbits;
  155.       space_left = INBUFSIZ - byte_offset;
  156.       ptrb = byte_offset + in_buf_adr;          /* point to char */
  157.       ptra = in_buf_adr;
  158.       /* we now move the remaining characters down buffer beginning */
  159.       while (space_left > 0) {
  160.          *ptra++ = *ptrb++;
  161.          space_left--;
  162.       }
  163.       if (read(in_han, ptra, byte_offset) == -1)
  164.          prterror ('f', "I/O error in lzd:rd_dcode\n", 
  165.                 (char *) 0, (char *) 0);
  166.       byte_offset = 0;
  167.    }
  168.    ptra = byte_offset + in_buf_adr;
  169.    /* NOTE:  "word = *((int *) ptra)" would not be independent of byte order. */
  170.    word = (unsigned char) *ptra; ptra++;
  171.    word = word | ((unsigned char) *ptra) << 8; ptra++;
  172.  
  173.    nextch = *ptra;
  174.    if (ofs_inbyte != 0) {
  175.       /* shift nextch right by ofs_inbyte bits */
  176.       /* and shift those bits right into word; */
  177.       word = (word >> ofs_inbyte) | (((unsigned)nextch) << (16-ofs_inbyte));
  178.    }
  179.    return (word & masks[nbits]); 
  180. } /* rd_dcode() */
  181.  
  182. int init_dtab()
  183. {
  184.    nbits = 9;
  185.    max_code = 512;
  186.    free_code = FIRST_FREE;
  187. }
  188.  
  189. int wr_dchar (ch)
  190. char ch;
  191. {
  192.    if (output_offset >= OUTBUFSIZ) {      /* if buffer full */
  193.       if (out_han != -2) {
  194.          if (write(out_han, out_buf_adr, output_offset) != output_offset)
  195.             prterror ('f', "Write error in lzd:wr_dchar\n", 
  196.                     (char *) 0, (char *) 0);
  197.       }
  198.       addbfcrc(out_buf_adr, output_offset);     /* update CRC */
  199.       output_offset = 0;                  /* restore empty buffer */
  200.    }
  201.    out_buf_adr[output_offset++] = ch;        /* store character */
  202. } /* wr_dchar() */
  203.  
  204. /* adds a code to table */
  205. int ad_dcode()
  206. {
  207.    table[free_code].z_ch = k;                /* save suffix char */
  208.    table[free_code].next = old_code;         /* save prefix code */
  209.    free_code++;
  210.    if (free_code >= max_code) {
  211.       if (nbits < MAXBITS) {
  212.          nbits++;
  213.          max_code = max_code << 1;        /* double max_code */
  214.       }
  215.    }
  216. }
  217.