1 /* $XConsortium: decompress.c,v 1.6 94/04/17 20:17:00 gildea Exp $ */
3 * Copyright (c) 1985, 1986 The Regents of the University of California.
6 * This code is derived from software contributed to Berkeley by
7 * James A. Woods, derived from original work by Spencer Thomas
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by the University of California, Berkeley. The name of the
16 * University may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25 Copyright (c) 1993 X Consortium
27 Permission is hereby granted, free of charge, to any person obtaining a copy
28 of this software and associated documentation files (the "Software"), to deal
29 in the Software without restriction, including without limitation the rights
30 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31 copies of the Software, and to permit persons to whom the Software is
32 furnished to do so, subject to the following conditions:
34 The above copyright notice and this permission notice shall be included in
35 all copies or substantial portions of the Software.
37 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
40 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
41 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44 Except as contained in this notice, the name of the X Consortium shall not be
45 used in advertising or otherwise to promote the sale, use or other dealings
46 in this Software without prior written authorization from the X Consortium.
50 * decompress - cat a compressed file
59 * a code_int must be able to hold 2**BITS values of type int, and also -1
62 typedef long int code_int;
67 typedef long int count_int;
70 typedef char char_type;
72 typedef unsigned char char_type;
75 static char_type magic_header[] = { "\037\235" }; /* 1F 9D */
77 /* Defines for third byte of header */
79 #define BLOCK_MASK 0x80
80 /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
81 a fourth header byte (for expansion).
84 #define INIT_BITS 9 /* initial number of bits/code */
86 #ifdef COMPATIBLE /* But wrong! */
87 # define MAXCODE(n_bits) (1 << (n_bits) - 1)
89 # define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
90 #endif /* COMPATIBLE */
92 static code_int getcode();
95 * the next two codes should not be changed lightly, as they must not
96 * lie within the contiguous general code space.
98 #define FIRST 257 /* first free entry */
99 #define CLEAR 256 /* table clear output code */
101 #define STACK_SIZE 8192
103 typedef struct _compressedFILE {
112 code_int maxcode, maxmaxcode;
122 char_type de_stack[STACK_SIZE];
123 char_type *tab_suffix;
124 unsigned short *tab_prefix;
128 static int hsize_table[] = {
129 5003, /* 12 bits - 80% occupancy */
130 9001, /* 13 bits - 91% occupancy */
131 18013, /* 14 bits - 91% occupancy */
132 35023, /* 15 bits - 94% occupancy */
133 69001 /* 16 bits - 95% occupancy */
136 static int BufCompressedFill(), BufCompressedSkip(), BufCompressedClose();
139 BufFilePushCompressed (f)
145 CompressedFile *file;
148 if ((BufFileGet(f) != (magic_header[0] & 0xFF)) ||
149 (BufFileGet(f) != (magic_header[1] & 0xFF)))
153 code = BufFileGet (f);
154 maxbits = code & BIT_MASK;
155 if (maxbits > BITS || maxbits < 12)
157 hsize = hsize_table[maxbits - 12];
158 extra = (1 << maxbits) * sizeof (char_type) +
159 hsize * sizeof (unsigned short);
160 file = (CompressedFile *) xalloc (sizeof (CompressedFile) + extra);
164 file->maxbits = maxbits;
165 file->block_compress = code & BLOCK_MASK;
166 file->maxmaxcode = 1 << file->maxbits;
167 file->tab_suffix = (char_type *) &file[1];
168 file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode);
170 * As above, initialize the first 256 entries in the table.
172 file->maxcode = MAXCODE(file->n_bits = INIT_BITS);
173 for ( code = 255; code >= 0; code-- ) {
174 file->tab_prefix[code] = 0;
175 file->tab_suffix[code] = (char_type) code;
177 file->free_ent = ((file->block_compress) ? FIRST : 256 );
181 file->stackp = file->de_stack;
182 file->finchar = file->oldcode = getcode (file);
183 if (file->oldcode != -1)
184 *file->stackp++ = file->finchar;
185 return BufFileCreate ((char *) file,
192 BufCompressedClose (f, doClose)
195 CompressedFile *file;
198 file = (CompressedFile *) f->private;
201 BufFileClose (raw, doClose);
206 BufCompressedFill (f)
209 CompressedFile *file;
210 register char_type *stackp, *de_stack;
211 register char_type finchar;
212 register code_int code, oldcode, incode;
213 BufChar *buf, *bufend;
215 file = (CompressedFile *) f->private;
218 bufend = buf + BUFFILESIZE;
219 stackp = file->stackp;
220 de_stack = file->de_stack;
221 finchar = file->finchar;
222 oldcode = file->oldcode;
223 while (buf < bufend) {
224 while (stackp > de_stack && buf < bufend)
233 code = getcode (file);
237 if ( (code == CLEAR) && file->block_compress ) {
238 for ( code = 255; code >= 0; code-- )
239 file->tab_prefix[code] = 0;
241 file->free_ent = FIRST - 1;
242 if ( (code = getcode (file)) == -1 ) /* O, untimely death! */
247 * Special case for KwKwK string.
249 if ( code >= file->free_ent ) {
255 * Generate output characters in reverse order
257 while ( code >= 256 )
259 *stackp++ = file->tab_suffix[code];
260 code = file->tab_prefix[code];
262 finchar = file->tab_suffix[code];
266 * Generate the new entry.
268 if ( (code=file->free_ent) < file->maxmaxcode ) {
269 file->tab_prefix[code] = (unsigned short)oldcode;
270 file->tab_suffix[code] = finchar;
271 file->free_ent = code+1;
274 * Remember previous code.
278 file->oldcode = oldcode;
279 file->stackp = stackp;
280 file->finchar = finchar;
281 if (buf == f->buffer) {
285 f->bufp = f->buffer + 1;
286 f->left = (buf - f->buffer) - 1;
290 /*****************************************************************
293 * Read one code from the standard input. If BUFFILEEOF, return -1.
297 * code or -1 is returned.
300 static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
304 CompressedFile *file;
306 register code_int code;
307 register int r_off, bits;
308 register char_type *bp = file->buf;
309 register BufFilePtr raw;
311 if ( file->clear_flg > 0 || file->offset >= file->size ||
312 file->free_ent > file->maxcode )
315 * If the next entry will be too big for the current code
316 * size, then we must increase the size. This implies reading
317 * a new buffer full, too.
319 if ( file->free_ent > file->maxcode ) {
321 if ( file->n_bits == file->maxbits )
322 file->maxcode = file->maxmaxcode; /* won't get any bigger now */
324 file->maxcode = MAXCODE(file->n_bits);
326 if ( file->clear_flg > 0) {
327 file->maxcode = MAXCODE (file->n_bits = INIT_BITS);
332 while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF)
338 if (bits == file->n_bits)
339 return -1; /* end of file */
340 file->size = file->n_bits - bits;
342 /* Round size down to integral number of codes */
343 file->size = (file->size << 3) - (file->n_bits - 1);
345 r_off = file->offset;
348 * Get to the first byte.
352 /* Get first part (low order bits) */
354 code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
356 code = (*bp++ >> r_off);
357 #endif /* NO_UCHAR */
359 r_off = 8 - r_off; /* now, offset into code word */
360 /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
363 code |= (*bp++ & 0xff) << r_off;
365 code |= *bp++ << r_off;
366 #endif /* NO_UCHAR */
370 /* high order bits. */
371 code |= (*bp & rmask[bits]) << r_off;
372 file->offset += file->n_bits;
378 BufCompressedSkip (f, bytes)
397 BufFilePtr inputraw, input, output;
400 inputraw = BufFileOpenRead (0);
401 input = BufFilePushCompressed (inputraw);
402 output = BufFileOpenWrite (1);
403 while ((c = BufFileGet (input)) != -1)
404 BufFilePut (c, output);
405 BufFileClose (input, FALSE);
406 BufFileClose (output, FALSE);