home *** CD-ROM | disk | FTP | other *** search
/ PSION CD 2 / PsionCDVol2.iso / Programs / 720 / PDF090B4-SorceCode / pdf / unlzw.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-30  |  12.6 KB  |  492 lines

  1. /* unlzw.c -- decompress files in LZW format.
  2.  * The code in this file is directly derived from the public domain 'compress'
  3.  * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
  4.  * Ken Turkowski, Dave Mack and Peter Jannesen.
  5.  *
  6.  * This is a temporary version which will be rewritten in some future version
  7.  * to accommodate in-memory decompression.
  8.  */
  9.  
  10. /*
  11.  * Ported to Epoc by Sander van der Wal.
  12.  * This file was originally part of gzip-1.2.4
  13.  * 
  14.  * $Id: unlzw.cpp 1.1 2000-09-17 13:39:33+02 svdwal Exp svdwal $
  15.  *
  16.  * $Log: unlzw.cpp $
  17.  * Revision 1.1  2000-09-17 13:39:33+02  svdwal
  18.  * Initial checkin
  19.  *
  20.  *
  21.  */
  22.  
  23. #ifndef __E32BASE_H__
  24. #include <e32base.h>
  25. #endif
  26.  
  27. #include "file_unlzw.h"
  28.  
  29. #include "tailor.h"
  30. #include <stdlib.h>
  31. #include <unistd.h>
  32.  
  33. #include "gzip.h"
  34. #include "lzw.h"
  35. #include "Pdf.rsg"
  36.  
  37. extern "C" void C_error(int);
  38.  
  39. /* originally from in util.c: */
  40. static int  fill_inbuf(RFile& ifd, int eof_ok, uch* inbuf, unsigned* insize, unsigned* inptr);
  41. static void write_buf (RFile& fd, const char* buf, unsigned cnt);
  42. static void error     (const char *m);
  43. static void read_error(void);
  44.  
  45.  
  46. typedef    unsigned char    char_type;
  47. typedef          long   code_int;
  48. typedef unsigned long     count_int;
  49. typedef unsigned short    count_short;
  50. typedef unsigned long     cmp_code_int;
  51.  
  52. #define MAXCODE(n)    (1L << (n))
  53.  
  54. #ifndef    REGISTERS
  55. #  define REGISTERS 3
  56. #endif
  57. #define    REG1    
  58. #define    REG2    
  59. #define    REG3    
  60. #define    REG4    
  61. #define    REG5    
  62. #define    REG6    
  63. #define    REG7    
  64. #define    REG8    
  65. #define    REG9    
  66. #define    REG10
  67. #define    REG11    
  68. #define    REG12    
  69. #define    REG13
  70. #define    REG14
  71. #define    REG15
  72. #define    REG16
  73. #if REGISTERS >= 1
  74. #    undef    REG1
  75. #    define    REG1    register
  76. #endif
  77. #if REGISTERS >= 2
  78. #    undef    REG2
  79. #    define    REG2    register
  80. #endif
  81. #if REGISTERS >= 3
  82. #    undef    REG3
  83. #    define    REG3    register
  84. #endif
  85. #if REGISTERS >= 4
  86. #    undef    REG4
  87. #    define    REG4    register
  88. #endif
  89. #if REGISTERS >= 5
  90. #    undef    REG5
  91. #    define    REG5    register
  92. #endif
  93. #if REGISTERS >= 6
  94. #    undef    REG6
  95. #    define    REG6    register
  96. #endif
  97. #if REGISTERS >= 7
  98. #    undef    REG7
  99. #    define    REG7    register
  100. #endif
  101. #if REGISTERS >= 8
  102. #    undef    REG8
  103. #    define    REG8    register
  104. #endif
  105. #if REGISTERS >= 9
  106. #    undef    REG9
  107. #    define    REG9    register
  108. #endif
  109. #if REGISTERS >= 10
  110. #    undef    REG10
  111. #    define    REG10    register
  112. #endif
  113. #if REGISTERS >= 11
  114. #    undef    REG11
  115. #    define    REG11    register
  116. #endif
  117. #if REGISTERS >= 12
  118. #    undef    REG12
  119. #    define    REG12    register
  120. #endif
  121. #if REGISTERS >= 13
  122. #    undef    REG13
  123. #    define    REG13    register
  124. #endif
  125. #if REGISTERS >= 14
  126. #    undef    REG14
  127. #    define    REG14    register
  128. #endif
  129. #if REGISTERS >= 15
  130. #    undef    REG15
  131. #    define    REG15    register
  132. #endif
  133. #if REGISTERS >= 16
  134. #    undef    REG16
  135. #    define    REG16    register
  136. #endif
  137.     
  138. #ifndef    BYTEORDER
  139. #     define    BYTEORDER    0000
  140. #endif
  141.     
  142. #ifndef    NOALLIGN
  143. #     define    NOALLIGN    0
  144. #endif
  145.  
  146.  
  147. union    _bytes {
  148.     long  word;
  149.     struct {
  150. #if BYTEORDER == 4321
  151.     char_type    b1;
  152.     char_type    b2;
  153.     char_type    b3;
  154.     char_type    b4;
  155. #else
  156. #if BYTEORDER == 1234
  157.     char_type    b4;
  158.     char_type    b3;
  159.     char_type    b2;
  160.     char_type    b1;
  161. #else
  162. #    undef    BYTEORDER
  163.     int  dummy;
  164. #endif
  165. #endif
  166.     } bytes;
  167. };
  168.  
  169. #if BYTEORDER == 4321 && NOALLIGN == 1
  170. #  define input(b,o,c,n,m){ \
  171.      (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
  172.      (o) += (n); \
  173.    }
  174. #else
  175. #  define input(b,o,c,n,m){ \
  176.      REG1 char_type *p = &(b)[(o)>>3]; \
  177.      (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
  178.      ((long)(p[2])<<16))>>((o)&0x7))&(m); \
  179.      (o) += (n); \
  180.    }
  181. #endif
  182.  
  183. // for information only
  184. #define ALLOC(type, array, size) { \
  185.       array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
  186.       if (array == NULL) C_error(R_LZW__INSUFFICIENT_MEMORY); \
  187.    }
  188. #define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
  189.  
  190.  
  191.    /* DECLARE(ush, tab_prefix, (1<<BITS)); -- prefix code */
  192. #define tab_prefixof(i) tab_prefix[i]
  193. #define clear_tab_prefixof()    Mem::FillZ(tab_prefix, 256);
  194.  
  195. #define de_stack        ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
  196. #define tab_suffixof(i) tab_suffix[i]
  197.  
  198.  
  199. /* ============================================================================
  200.  * Decompress in to out.  This routine adapts to the codes in the
  201.  * file building the "string" table on-the-fly; requiring no table to
  202.  * be stored in the compressed file.
  203.  * IN assertions: the buffer inbuf contains already the beginning of
  204.  *   the compressed data, from offsets iptr to insize-1 included.
  205.  *   The magic header has already been checked and skipped.
  206.  *   bytes_in and bytes_out have been initialized.
  207.  */
  208. int unlzwL(RFile& in, RFile& out)   /* input and output file descriptors */
  209. {
  210.   REG2   char_type  *stackp;
  211.   REG3   code_int   code;
  212.   REG4   int        finchar;
  213.   REG5   code_int   oldcode;
  214.   REG6   code_int   incode;
  215.   REG7   long       inbits;
  216.   REG8   long       posbits;
  217.   REG9   int        outpos;
  218. /*  REG10  int        insize; (global) */
  219.   REG11  unsigned   bitmask;
  220.   REG12  code_int   free_ent;
  221.   REG13  code_int   maxcode;
  222.   REG14  code_int   maxmaxcode;
  223.   REG15  int        n_bits;
  224.   REG16  int        rsize;
  225.   
  226.   int res = 0;
  227.  
  228.   unsigned insize = 0; /* valid bytes in inbuf */
  229.   unsigned inptr  = 0;  /* index of next byte to be processed in inbuf */
  230.   
  231.   int maxbits = BITS;   /* max bits per code for LZW */
  232.   int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */
  233.   
  234.   char magic[2]; /* magic header */
  235.   
  236.   
  237.   /* Allocate all global buffers (for DYN_ALLOC option) */
  238.  
  239.   //ALLOC(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
  240.   uch* inbuf = (uch*) User::AllocLC((INBUFSIZ +INBUF_EXTRA+1L)*sizeof(uch));
  241.   //ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
  242.   uch* outbuf = (uch*) User::AllocLC((OUTBUFSIZ+OUTBUF_EXTRA+1L)*sizeof(uch));
  243.   //ALLOC(ush, d_buf,  DIST_BUFSIZE);
  244.   ush* d_buf = (ush*) User::AllocLC((DIST_BUFSIZE+1L)*2*sizeof(ush));
  245.   //ALLOC(uch, window, 2L*WSIZE);
  246.   uch* window = (uch*) User::AllocLC((2L*WSIZE+1)*2*sizeof(uch));
  247.   //ALLOC(ush, tab_prefix, 1L<<BITS);
  248.   ush* tab_prefix = (ush*) User::AllocLC(((1L<<BITS)+1)*2*sizeof(ush));
  249.  
  250. #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf(in, 0, inbuf, &insize, &inptr))
  251.  
  252.   magic[0] = (char)get_byte();
  253.   magic[1] = (char)get_byte();
  254.  
  255.   if (memcmp(magic, LZW_MAGIC, 2) != 0)
  256.     res = 1;
  257.   
  258.   maxbits = get_byte();
  259.   block_mode = maxbits & BLOCK_MODE;
  260.   
  261.   maxbits &= BIT_MASK;
  262.   maxmaxcode = MAXCODE(maxbits);
  263.     
  264.   if (maxbits > BITS)
  265.       res = 1;
  266.  
  267.   if (res == 0) {
  268.   
  269.     rsize = insize;
  270.     maxcode = MAXCODE(n_bits = INIT_BITS)-1;
  271.     bitmask = (1<<n_bits)-1;
  272.     oldcode = -1;
  273.     finchar = 0;
  274.     outpos = 0;
  275.     posbits = inptr<<3;
  276.  
  277.     free_ent = ((block_mode) ? FIRST : 256);
  278.     
  279.     clear_tab_prefixof(); /* Initialize the first 256 entries in the table. */
  280.     
  281.     for (code = 255 ; code >= 0 ; --code) {
  282.         tab_suffixof(code) = (char_type)code;
  283.     }
  284.   
  285.     do {
  286.         REG1 int i;
  287.       int  e;
  288.       int  o;
  289.     
  290. resetbuf:
  291.       e = insize-(o = (posbits>>3));
  292.     
  293.       for (i = 0 ; i < e ; ++i) {
  294.         inbuf[i] = inbuf[i+o];
  295.       }
  296.       insize = e;
  297.       posbits = 0;
  298.     
  299.       if (insize < INBUF_EXTRA) {
  300.         TPtr ptr = TPtr((TUint8*)inbuf+insize, INBUFSIZ);
  301.         User::LeaveIfError(in.Read(ptr, INBUFSIZ));
  302.         rsize = ptr.Length();
  303.         insize += rsize;
  304.         /* bytes_in += (ulg)rsize; */
  305.       }
  306.       inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 : 
  307.                                ((long)insize<<3)-(n_bits-1));
  308.     
  309.       while (inbits > posbits) {
  310.         if (free_ent > maxcode) {
  311.             posbits = ((posbits-1) +
  312.                         ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
  313.           ++n_bits;
  314.           if (n_bits == maxbits) {
  315.             maxcode = maxmaxcode;
  316.           } 
  317.           else {
  318.             maxcode = MAXCODE(n_bits)-1;
  319.           }
  320.           bitmask = (1<<n_bits)-1;
  321.           goto resetbuf;
  322.         }
  323.         input(inbuf,posbits,code,n_bits,bitmask);
  324.         Tracev((stderr, "%d ", code));
  325.  
  326.         if (oldcode == -1) {
  327.           if (code >= 256) C_error(R_LZW__CORRUPT_INPUT);
  328.           outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
  329.           continue;
  330.         }
  331.         if (code == CLEAR && block_mode) {
  332.           clear_tab_prefixof();
  333.           free_ent = FIRST - 1;
  334.           posbits = ((posbits-1) +
  335.                     ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
  336.           maxcode = MAXCODE(n_bits = INIT_BITS)-1;
  337.           bitmask = (1<<n_bits)-1;
  338.           goto resetbuf;
  339.         }
  340.         incode = code;
  341.         stackp = de_stack;
  342.         
  343.         if (code >= free_ent) { /* Special case for KwKwK string. */
  344.           if (code > free_ent) {
  345. #ifdef DEBUG            
  346.             char_type *p;
  347.  
  348.             posbits -= n_bits;
  349.             p = &inbuf[posbits>>3];
  350.             fprintf(stderr,
  351.                     "code:%ld free_ent:%ld n_bits:%d insize:%u\n",
  352.                     code, free_ent, n_bits, insize);
  353.             fprintf(stderr,
  354.                     "posbits:%ld inbuf:%02X %02X %02X %02X %02X\n",
  355.                      posbits, p[-1],p[0],p[1],p[2],p[3]);
  356. #endif
  357.             if (outpos > 0) {
  358.               write_buf(out, (char*)outbuf, outpos);
  359.               /* bytes_out += (ulg)outpos; */
  360.             }
  361.             C_error(R_LZW__CORRUPT_INPUT);
  362.           }
  363.           *--stackp = (char_type)finchar;
  364.           code = oldcode;
  365.         }
  366.  
  367.         while ((cmp_code_int)code >= (cmp_code_int)256) {
  368.           /* Generate output characters in reverse order */
  369.           *--stackp = tab_suffixof(code);
  370.           code = tab_prefixof(code);
  371.         }
  372.         *--stackp =    (char_type)(finchar = tab_suffixof(code));
  373.         
  374.         /* And put them out in forward order */
  375.         {
  376.           REG1 int i;
  377.     
  378.           if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
  379.             do {
  380.               if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;
  381.  
  382.               if (i > 0) {
  383.                 Mem::Copy(outbuf+outpos, stackp, i);
  384.                 outpos += i;
  385.               }
  386.               if (outpos >= OUTBUFSIZ) {
  387.                 write_buf(out, (char*)outbuf, outpos);
  388.                 /* bytes_out += (ulg)outpos; */
  389.                 outpos = 0;
  390.               }
  391.               stackp+= i;
  392.             } while ((i = (de_stack-stackp)) > 0);
  393.           } 
  394.           else {
  395.             Mem::Copy(outbuf+outpos, stackp, i);
  396.             outpos += i;
  397.           }
  398.         }
  399.  
  400.         if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */
  401.  
  402.           tab_prefixof(code) = (unsigned short)oldcode;
  403.           tab_suffixof(code) = (char_type)finchar;
  404.           free_ent = code+1;
  405.         } 
  406.         oldcode = incode;    /* Remember previous code.    */
  407.       }
  408.     } while (rsize != 0);
  409.     
  410.     if (outpos > 0) {
  411.       write_buf(out, (char*)outbuf, outpos);
  412.       /* bytes_out += (ulg)outpos; */
  413.     }
  414.   
  415.   } /* if (res == 0) */
  416.  
  417.   //FREE(inbuf);
  418.   //FREE(outbuf);
  419.   //FREE(d_buf);
  420.   //FREE(window);
  421.   //FREE(tab_prefix);
  422.   CleanupStack::PopAndDestroy(5);
  423.  
  424.   return OK;
  425. }
  426.  
  427. /* util.c -- utility functions for gzip support
  428.  * Copyright (C) 1992-1993 Jean-loup Gailly
  429.  * This is free software; you can redistribute it and/or modify it under the
  430.  * terms of the GNU General Public License, see the file COPYING.
  431.  */
  432.  
  433.  
  434. /* ===========================================================================
  435.  * Fill the input buffer. This is called only when the buffer is empty.
  436.  */
  437. int fill_inbuf(RFile& ifd, int eof_ok, uch* inbuf, unsigned* insize, unsigned * inptr)  /* set if EOF acceptable as a result */
  438. {
  439.   int len;
  440.  
  441.   /* Read as much as possible */
  442.   *insize = 0;
  443.   do {
  444.     TPtr ptr = TPtr((TUint8*)inbuf+*insize, INBUFSIZ-*insize);
  445.     User::LeaveIfError(ifd.Read(ptr, INBUFSIZ-*insize));
  446.     len = ptr.Length();
  447.     if (len == 0 || len == EOF) break;
  448.     *insize += len;
  449.   } while (*insize < INBUFSIZ);
  450.  
  451.   if (*insize == 0) {
  452.       if (eof_ok) return EOF;
  453.     read_error();
  454.   }
  455.   /* bytes_in += (ulg)insize; */
  456.   *inptr = 1;
  457.   return inbuf[0];
  458. }
  459.  
  460.  
  461. /* ===========================================================================
  462.  * Does the same as write(), but also handles partial pipe writes and checks
  463.  * for error return.
  464.  */
  465. void write_buf(
  466.     RFile&      fd,
  467.     const char* buf,
  468.     unsigned  cnt)
  469. {
  470.   
  471.   TPtrC ptr((TUint8*) buf, cnt);
  472.   User::LeaveIfError(fd.Write(ptr, cnt));
  473.   unsigned  n = ptr.Length();
  474.   while (n != cnt) {
  475.     
  476.     cnt -= n;
  477.     ptr.Set((const TUint8*)((TUint8*)buf+n), cnt);
  478.     User::LeaveIfError(fd.Write(ptr, cnt));
  479.   }
  480. }
  481.  
  482.  
  483. /* ========================================================================
  484.  * Error handlers.
  485.  */
  486.  
  487.  
  488. void read_error()
  489. {
  490.   C_error(R_LZW__UNEXPECTED_END_OF_FILE);
  491. }
  492.