home *** CD-ROM | disk | FTP | other *** search
- /* unlzw.c -- decompress files in LZW format.
- * The code in this file is directly derived from the public domain 'compress'
- * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
- * Ken Turkowski, Dave Mack and Peter Jannesen.
- *
- * This is a temporary version which will be rewritten in some future version
- * to accommodate in-memory decompression.
- */
-
- /*
- * Ported to Epoc by Sander van der Wal.
- * This file was originally part of gzip-1.2.4
- *
- * $Id: unlzw.cpp 1.1 2000-09-17 13:39:33+02 svdwal Exp svdwal $
- *
- * $Log: unlzw.cpp $
- * Revision 1.1 2000-09-17 13:39:33+02 svdwal
- * Initial checkin
- *
- *
- */
-
- #ifndef __E32BASE_H__
- #include <e32base.h>
- #endif
-
- #include "file_unlzw.h"
-
- #include "tailor.h"
- #include <stdlib.h>
- #include <unistd.h>
-
- #include "gzip.h"
- #include "lzw.h"
- #include "Pdf.rsg"
-
- extern "C" void C_error(int);
-
- /* originally from in util.c: */
- static int fill_inbuf(RFile& ifd, int eof_ok, uch* inbuf, unsigned* insize, unsigned* inptr);
- static void write_buf (RFile& fd, const char* buf, unsigned cnt);
- static void error (const char *m);
- static void read_error(void);
-
-
- typedef unsigned char char_type;
- typedef long code_int;
- typedef unsigned long count_int;
- typedef unsigned short count_short;
- typedef unsigned long cmp_code_int;
-
- #define MAXCODE(n) (1L << (n))
-
- #ifndef REGISTERS
- # define REGISTERS 3
- #endif
- #define REG1
- #define REG2
- #define REG3
- #define REG4
- #define REG5
- #define REG6
- #define REG7
- #define REG8
- #define REG9
- #define REG10
- #define REG11
- #define REG12
- #define REG13
- #define REG14
- #define REG15
- #define REG16
- #if REGISTERS >= 1
- # undef REG1
- # define REG1 register
- #endif
- #if REGISTERS >= 2
- # undef REG2
- # define REG2 register
- #endif
- #if REGISTERS >= 3
- # undef REG3
- # define REG3 register
- #endif
- #if REGISTERS >= 4
- # undef REG4
- # define REG4 register
- #endif
- #if REGISTERS >= 5
- # undef REG5
- # define REG5 register
- #endif
- #if REGISTERS >= 6
- # undef REG6
- # define REG6 register
- #endif
- #if REGISTERS >= 7
- # undef REG7
- # define REG7 register
- #endif
- #if REGISTERS >= 8
- # undef REG8
- # define REG8 register
- #endif
- #if REGISTERS >= 9
- # undef REG9
- # define REG9 register
- #endif
- #if REGISTERS >= 10
- # undef REG10
- # define REG10 register
- #endif
- #if REGISTERS >= 11
- # undef REG11
- # define REG11 register
- #endif
- #if REGISTERS >= 12
- # undef REG12
- # define REG12 register
- #endif
- #if REGISTERS >= 13
- # undef REG13
- # define REG13 register
- #endif
- #if REGISTERS >= 14
- # undef REG14
- # define REG14 register
- #endif
- #if REGISTERS >= 15
- # undef REG15
- # define REG15 register
- #endif
- #if REGISTERS >= 16
- # undef REG16
- # define REG16 register
- #endif
-
- #ifndef BYTEORDER
- # define BYTEORDER 0000
- #endif
-
- #ifndef NOALLIGN
- # define NOALLIGN 0
- #endif
-
-
- union _bytes {
- long word;
- struct {
- #if BYTEORDER == 4321
- char_type b1;
- char_type b2;
- char_type b3;
- char_type b4;
- #else
- #if BYTEORDER == 1234
- char_type b4;
- char_type b3;
- char_type b2;
- char_type b1;
- #else
- # undef BYTEORDER
- int dummy;
- #endif
- #endif
- } bytes;
- };
-
- #if BYTEORDER == 4321 && NOALLIGN == 1
- # define input(b,o,c,n,m){ \
- (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
- (o) += (n); \
- }
- #else
- # define input(b,o,c,n,m){ \
- REG1 char_type *p = &(b)[(o)>>3]; \
- (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
- ((long)(p[2])<<16))>>((o)&0x7))&(m); \
- (o) += (n); \
- }
- #endif
-
- // for information only
- #define ALLOC(type, array, size) { \
- array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
- if (array == NULL) C_error(R_LZW__INSUFFICIENT_MEMORY); \
- }
- #define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
-
-
- /* DECLARE(ush, tab_prefix, (1<<BITS)); -- prefix code */
- #define tab_prefixof(i) tab_prefix[i]
- #define clear_tab_prefixof() Mem::FillZ(tab_prefix, 256);
-
- #define de_stack ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
- #define tab_suffixof(i) tab_suffix[i]
-
-
- /* ============================================================================
- * Decompress in to out. This routine adapts to the codes in the
- * file building the "string" table on-the-fly; requiring no table to
- * be stored in the compressed file.
- * IN assertions: the buffer inbuf contains already the beginning of
- * the compressed data, from offsets iptr to insize-1 included.
- * The magic header has already been checked and skipped.
- * bytes_in and bytes_out have been initialized.
- */
- int unlzwL(RFile& in, RFile& out) /* input and output file descriptors */
- {
- REG2 char_type *stackp;
- REG3 code_int code;
- REG4 int finchar;
- REG5 code_int oldcode;
- REG6 code_int incode;
- REG7 long inbits;
- REG8 long posbits;
- REG9 int outpos;
- /* REG10 int insize; (global) */
- REG11 unsigned bitmask;
- REG12 code_int free_ent;
- REG13 code_int maxcode;
- REG14 code_int maxmaxcode;
- REG15 int n_bits;
- REG16 int rsize;
-
- int res = 0;
-
- unsigned insize = 0; /* valid bytes in inbuf */
- unsigned inptr = 0; /* index of next byte to be processed in inbuf */
-
- int maxbits = BITS; /* max bits per code for LZW */
- int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */
-
- char magic[2]; /* magic header */
-
-
- /* Allocate all global buffers (for DYN_ALLOC option) */
-
- //ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
- uch* inbuf = (uch*) User::AllocLC((INBUFSIZ +INBUF_EXTRA+1L)*sizeof(uch));
- //ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
- uch* outbuf = (uch*) User::AllocLC((OUTBUFSIZ+OUTBUF_EXTRA+1L)*sizeof(uch));
- //ALLOC(ush, d_buf, DIST_BUFSIZE);
- ush* d_buf = (ush*) User::AllocLC((DIST_BUFSIZE+1L)*2*sizeof(ush));
- //ALLOC(uch, window, 2L*WSIZE);
- uch* window = (uch*) User::AllocLC((2L*WSIZE+1)*2*sizeof(uch));
- //ALLOC(ush, tab_prefix, 1L<<BITS);
- ush* tab_prefix = (ush*) User::AllocLC(((1L<<BITS)+1)*2*sizeof(ush));
-
- #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(in, 0, inbuf, &insize, &inptr))
-
- magic[0] = (char)get_byte();
- magic[1] = (char)get_byte();
-
- if (memcmp(magic, LZW_MAGIC, 2) != 0)
- res = 1;
-
- maxbits = get_byte();
- block_mode = maxbits & BLOCK_MODE;
-
- maxbits &= BIT_MASK;
- maxmaxcode = MAXCODE(maxbits);
-
- if (maxbits > BITS)
- res = 1;
-
- if (res == 0) {
-
- rsize = insize;
- maxcode = MAXCODE(n_bits = INIT_BITS)-1;
- bitmask = (1<<n_bits)-1;
- oldcode = -1;
- finchar = 0;
- outpos = 0;
- posbits = inptr<<3;
-
- free_ent = ((block_mode) ? FIRST : 256);
-
- clear_tab_prefixof(); /* Initialize the first 256 entries in the table. */
-
- for (code = 255 ; code >= 0 ; --code) {
- tab_suffixof(code) = (char_type)code;
- }
-
- do {
- REG1 int i;
- int e;
- int o;
-
- resetbuf:
- e = insize-(o = (posbits>>3));
-
- for (i = 0 ; i < e ; ++i) {
- inbuf[i] = inbuf[i+o];
- }
- insize = e;
- posbits = 0;
-
- if (insize < INBUF_EXTRA) {
- TPtr ptr = TPtr((TUint8*)inbuf+insize, INBUFSIZ);
- User::LeaveIfError(in.Read(ptr, INBUFSIZ));
- rsize = ptr.Length();
- insize += rsize;
- /* bytes_in += (ulg)rsize; */
- }
- inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 :
- ((long)insize<<3)-(n_bits-1));
-
- while (inbits > posbits) {
- if (free_ent > maxcode) {
- posbits = ((posbits-1) +
- ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
- ++n_bits;
- if (n_bits == maxbits) {
- maxcode = maxmaxcode;
- }
- else {
- maxcode = MAXCODE(n_bits)-1;
- }
- bitmask = (1<<n_bits)-1;
- goto resetbuf;
- }
- input(inbuf,posbits,code,n_bits,bitmask);
- Tracev((stderr, "%d ", code));
-
- if (oldcode == -1) {
- if (code >= 256) C_error(R_LZW__CORRUPT_INPUT);
- outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
- continue;
- }
- if (code == CLEAR && block_mode) {
- clear_tab_prefixof();
- free_ent = FIRST - 1;
- posbits = ((posbits-1) +
- ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
- maxcode = MAXCODE(n_bits = INIT_BITS)-1;
- bitmask = (1<<n_bits)-1;
- goto resetbuf;
- }
- incode = code;
- stackp = de_stack;
-
- if (code >= free_ent) { /* Special case for KwKwK string. */
- if (code > free_ent) {
- #ifdef DEBUG
- char_type *p;
-
- posbits -= n_bits;
- p = &inbuf[posbits>>3];
- fprintf(stderr,
- "code:%ld free_ent:%ld n_bits:%d insize:%u\n",
- code, free_ent, n_bits, insize);
- fprintf(stderr,
- "posbits:%ld inbuf:%02X %02X %02X %02X %02X\n",
- posbits, p[-1],p[0],p[1],p[2],p[3]);
- #endif
- if (outpos > 0) {
- write_buf(out, (char*)outbuf, outpos);
- /* bytes_out += (ulg)outpos; */
- }
- C_error(R_LZW__CORRUPT_INPUT);
- }
- *--stackp = (char_type)finchar;
- code = oldcode;
- }
-
- while ((cmp_code_int)code >= (cmp_code_int)256) {
- /* Generate output characters in reverse order */
- *--stackp = tab_suffixof(code);
- code = tab_prefixof(code);
- }
- *--stackp = (char_type)(finchar = tab_suffixof(code));
-
- /* And put them out in forward order */
- {
- REG1 int i;
-
- if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
- do {
- if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;
-
- if (i > 0) {
- Mem::Copy(outbuf+outpos, stackp, i);
- outpos += i;
- }
- if (outpos >= OUTBUFSIZ) {
- write_buf(out, (char*)outbuf, outpos);
- /* bytes_out += (ulg)outpos; */
- outpos = 0;
- }
- stackp+= i;
- } while ((i = (de_stack-stackp)) > 0);
- }
- else {
- Mem::Copy(outbuf+outpos, stackp, i);
- outpos += i;
- }
- }
-
- if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */
-
- tab_prefixof(code) = (unsigned short)oldcode;
- tab_suffixof(code) = (char_type)finchar;
- free_ent = code+1;
- }
- oldcode = incode; /* Remember previous code. */
- }
- } while (rsize != 0);
-
- if (outpos > 0) {
- write_buf(out, (char*)outbuf, outpos);
- /* bytes_out += (ulg)outpos; */
- }
-
- } /* if (res == 0) */
-
- //FREE(inbuf);
- //FREE(outbuf);
- //FREE(d_buf);
- //FREE(window);
- //FREE(tab_prefix);
- CleanupStack::PopAndDestroy(5);
-
- return OK;
- }
-
- /* util.c -- utility functions for gzip support
- * Copyright (C) 1992-1993 Jean-loup Gailly
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- */
-
-
- /* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty.
- */
- int fill_inbuf(RFile& ifd, int eof_ok, uch* inbuf, unsigned* insize, unsigned * inptr) /* set if EOF acceptable as a result */
- {
- int len;
-
- /* Read as much as possible */
- *insize = 0;
- do {
- TPtr ptr = TPtr((TUint8*)inbuf+*insize, INBUFSIZ-*insize);
- User::LeaveIfError(ifd.Read(ptr, INBUFSIZ-*insize));
- len = ptr.Length();
- if (len == 0 || len == EOF) break;
- *insize += len;
- } while (*insize < INBUFSIZ);
-
- if (*insize == 0) {
- if (eof_ok) return EOF;
- read_error();
- }
- /* bytes_in += (ulg)insize; */
- *inptr = 1;
- return inbuf[0];
- }
-
-
- /* ===========================================================================
- * Does the same as write(), but also handles partial pipe writes and checks
- * for error return.
- */
- void write_buf(
- RFile& fd,
- const char* buf,
- unsigned cnt)
- {
-
- TPtrC ptr((TUint8*) buf, cnt);
- User::LeaveIfError(fd.Write(ptr, cnt));
- unsigned n = ptr.Length();
- while (n != cnt) {
-
- cnt -= n;
- ptr.Set((const TUint8*)((TUint8*)buf+n), cnt);
- User::LeaveIfError(fd.Write(ptr, cnt));
- }
- }
-
-
- /* ========================================================================
- * Error handlers.
- */
-
-
- void read_error()
- {
- C_error(R_LZW__UNEXPECTED_END_OF_FILE);
- }
-