2 * Copyright 1985, 1986 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
6 * James A. Woods, derived from original work by Spencer Thomas
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by the University of California, Berkeley. The name of the
15 * University may not be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 Copyright 1993, 1998 The Open Group
26 Permission to use, copy, modify, distribute, and sell this software and its
27 documentation for any purpose is hereby granted without fee, provided that
28 the above copyright notice appear in all copies and that both that
29 copyright notice and this permission notice appear in supporting
32 The above copyright notice and this permission notice shall be included in
33 all copies or substantial portions of the Software.
35 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
39 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 Except as contained in this notice, the name of The Open Group shall not be
43 used in advertising or otherwise to promote the sale, use or other dealings
44 in this Software without prior written authorization from The Open Group.
48 * decompress - cat a compressed file
54 #include <X11/fonts/fontmisc.h>
55 #include <X11/fonts/bufio.h>
60 * a code_int must be able to hold 2**BITS values of type int, and also -1
63 typedef long int code_int;
68 typedef long int count_int;
71 typedef char char_type;
73 typedef unsigned char char_type;
76 static char_type magic_header[] = { "\037\235" }; /* 1F 9D */
78 /* Defines for third byte of header */
80 #define BLOCK_MASK 0x80
81 /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
82 a fourth header byte (for expansion).
85 #define INIT_BITS 9 /* initial number of bits/code */
87 #ifdef COMPATIBLE /* But wrong! */
88 # define MAXCODE(n_bits) (1 << (n_bits) - 1)
90 # define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
91 #endif /* COMPATIBLE */
94 * the next two codes should not be changed lightly, as they must not
95 * lie within the contiguous general code space.
97 #define FIRST 257 /* first free entry */
98 #define CLEAR 256 /* table clear output code */
100 #define STACK_SIZE 8192
102 typedef struct _compressedFILE {
111 code_int maxcode, maxmaxcode;
121 char_type de_stack[STACK_SIZE];
122 char_type *tab_suffix;
123 unsigned short *tab_prefix;
127 static int hsize_table[] = {
128 5003, /* 12 bits - 80% occupancy */
129 9001, /* 13 bits - 91% occupancy */
130 18013, /* 14 bits - 91% occupancy */
131 35023, /* 15 bits - 94% occupancy */
132 69001 /* 16 bits - 95% occupancy */
135 static int BufCompressedClose ( BufFilePtr f, int doClose );
136 static int BufCompressedFill ( BufFilePtr f );
137 static code_int getcode ( CompressedFile *file );
138 static int BufCompressedSkip ( BufFilePtr f, int bytes );
141 BufFilePushCompressed (BufFilePtr f)
146 CompressedFile *file;
149 if ((BufFileGet(f) != (magic_header[0] & 0xFF)) ||
150 (BufFileGet(f) != (magic_header[1] & 0xFF)))
154 code = BufFileGet (f);
155 if (code == BUFFILEEOF) return 0;
157 maxbits = code & BIT_MASK;
158 if (maxbits > BITS || maxbits < 12)
160 hsize = hsize_table[maxbits - 12];
161 extra = (1 << maxbits) * sizeof (char_type) +
162 hsize * sizeof (unsigned short);
163 file = malloc (sizeof (CompressedFile) + extra);
167 file->maxbits = maxbits;
168 file->block_compress = code & BLOCK_MASK;
169 file->maxmaxcode = 1 << file->maxbits;
170 file->tab_suffix = (char_type *) &file[1];
171 file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode);
173 * As above, initialize the first 256 entries in the table.
175 file->maxcode = MAXCODE(file->n_bits = INIT_BITS);
176 for ( code = 255; code >= 0; code-- ) {
177 file->tab_prefix[code] = 0;
178 file->tab_suffix[code] = (char_type) code;
180 file->free_ent = ((file->block_compress) ? FIRST : 256 );
184 file->stackp = file->de_stack;
185 bzero(file->buf, BITS);
186 file->finchar = file->oldcode = getcode (file);
187 if (file->oldcode != -1)
188 *file->stackp++ = file->finchar;
189 return BufFileCreate ((char *) file,
197 BufCompressedClose (BufFilePtr f, int doClose)
199 CompressedFile *file;
202 file = (CompressedFile *) f->private;
205 BufFileClose (raw, doClose);
210 BufCompressedFill (BufFilePtr f)
212 CompressedFile *file;
213 register char_type *stackp, *de_stack;
214 register char_type finchar;
215 register code_int code, oldcode, incode;
216 BufChar *buf, *bufend;
218 file = (CompressedFile *) f->private;
221 bufend = buf + BUFFILESIZE;
222 stackp = file->stackp;
223 de_stack = file->de_stack;
224 finchar = file->finchar;
225 oldcode = file->oldcode;
226 while (buf < bufend) {
227 while (stackp > de_stack && buf < bufend)
236 code = getcode (file);
240 if ( (code == CLEAR) && file->block_compress ) {
241 for ( code = 255; code >= 0; code-- )
242 file->tab_prefix[code] = 0;
244 file->free_ent = FIRST - 1;
245 if ( (code = getcode (file)) == -1 ) /* O, untimely death! */
250 * Special case for KwKwK string.
252 if ( code >= file->free_ent ) {
258 * Generate output characters in reverse order
260 while ( code >= 256 )
262 *stackp++ = file->tab_suffix[code];
263 code = file->tab_prefix[code];
265 finchar = file->tab_suffix[code];
269 * Generate the new entry.
271 if ( (code=file->free_ent) < file->maxmaxcode ) {
272 file->tab_prefix[code] = (unsigned short)oldcode;
273 file->tab_suffix[code] = finchar;
274 file->free_ent = code+1;
277 * Remember previous code.
281 file->oldcode = oldcode;
282 file->stackp = stackp;
283 file->finchar = finchar;
284 if (buf == f->buffer) {
288 f->bufp = f->buffer + 1;
289 f->left = (buf - f->buffer) - 1;
293 /*****************************************************************
296 * Read one code from the standard input. If BUFFILEEOF, return -1.
300 * code or -1 is returned.
303 static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
306 getcode(CompressedFile *file)
308 register code_int code;
309 register int r_off, bits;
310 register char_type *bp = file->buf;
311 register BufFilePtr raw;
313 if ( file->clear_flg > 0 || file->offset >= file->size ||
314 file->free_ent > file->maxcode )
317 * If the next entry will be too big for the current code
318 * size, then we must increase the size. This implies reading
319 * a new buffer full, too.
321 if ( file->free_ent > file->maxcode ) {
323 if ( file->n_bits == file->maxbits )
324 file->maxcode = file->maxmaxcode; /* won't get any bigger now */
326 file->maxcode = MAXCODE(file->n_bits);
328 if ( file->clear_flg > 0) {
329 file->maxcode = MAXCODE (file->n_bits = INIT_BITS);
334 while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF)
340 if (bits == file->n_bits)
341 return -1; /* end of file */
342 file->size = file->n_bits - bits;
344 /* Round size down to integral number of codes */
345 file->size = (file->size << 3) - (file->n_bits - 1);
347 r_off = file->offset;
350 * Get to the first byte.
354 /* Get first part (low order bits) */
356 code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
358 code = (*bp++ >> r_off);
359 #endif /* NO_UCHAR */
361 r_off = 8 - r_off; /* now, offset into code word */
362 /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
365 code |= (*bp++ & 0xff) << r_off;
367 code |= *bp++ << r_off;
368 #endif /* NO_UCHAR */
372 /* high order bits. */
373 code |= (*bp & rmask[bits]) << r_off;
374 file->offset += file->n_bits;
380 BufCompressedSkip (BufFilePtr f, int bytes)
394 main (int argc, char *argv[])
396 BufFilePtr inputraw, input, output;
399 inputraw = BufFileOpenRead (0);
400 input = BufFilePushCompressed (inputraw);
401 output = BufFileOpenWrite (1);
402 while ((c = BufFileGet (input)) != BUFFILEEOF)
403 BufFilePut (c, output);
404 BufFileClose (input, FALSE);
405 BufFileClose (output, FALSE);