File: de_compress.c

package info (click to toggle)
macutils 2.0b3-17
  • links: PTS
  • area: main
  • in suites: bookworm, sid, trixie
  • size: 1,256 kB
  • sloc: ansic: 12,737; makefile: 661
file content (225 lines) | stat: -rwxr-xr-x 5,169 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include "macunpack.h"
#ifdef SIT
#define DECOMPRESS
#endif /* SIT */
#ifdef LZC
#define DECOMPRESS
#endif /* LZC */
#ifdef DECOMPRESS
#include "globals.h"
#include "../fileio/wrfile.h"

/* Written to allow for bits to be upto 16, MacCompress can use 16 bits */

#define	BITS	16
#define HSIZE	69001		/* 95% occupancy */

#define INIT_BITS 9			/* initial number of bits/code */

static int n_bits;				/* number of bits/code */
static int maxbits;			/* user settable max # bits/code */
static long maxcode;			/* maximum code, given n_bits */
static long maxmaxcode;			/* should NEVER generate this code */
# define MAXCODE(n_bits)	((1 << (n_bits)) - 1)

static long htab [HSIZE];
static unsigned short codetab [HSIZE];

#define tab_prefixof(i) codetab[i]
#define tab_suffixof(i)	((unsigned char *)(htab))[i]
#define de_stack	((unsigned char *)&tab_suffixof(1<<BITS))

static long free_ent = 0;			/* first unused entry */

static long getcode();

static int clear_flg = 0;

/*
 * the next two codes should not be changed lightly, as they must not
 * lie within the contiguous general code space.
 */
#define FIRST	257	/* first free entry */
#define	CLEAR	256	/* table clear output code */

static int toread;

void de_compress(ibytes, mb)
unsigned long ibytes;
int mb;
{
    register unsigned char *stackp;
    register int finchar;
    register long code, oldcode, incode;

    toread = ibytes;
    maxbits = mb;
    maxmaxcode = 1 << maxbits;
    maxcode = MAXCODE(n_bits = INIT_BITS);
    for(code = 255; code >= 0; code--) {
	tab_prefixof(code) = 0;
	tab_suffixof(code) = (unsigned char)code;
    }
    free_ent = FIRST;
    finchar = oldcode = getcode();
    if(oldcode == -1) {	/* EOF already? */
	return;			/* Get out of here */
    }
    /* first code must be 8 bits = char */
    *out_ptr++ = (char)finchar;
    stackp = de_stack;
    while((code = getcode()) > -1) {
	if(code == CLEAR) {
	    for(code = 255; code >= 0; code--) {
		tab_prefixof(code) = 0;
	    }
	    clear_flg = 1;
	    free_ent = FIRST - 1;
	    if((code = getcode()) == -1) {	/* O, untimely death! */
		break;
	    }
	}
	incode = code;
	/*
	 * Special case for KwKwK string.
	 */
	if(code >= free_ent) {
	    *stackp++ = finchar;
	    code = oldcode;
	}
	/*
	 * Generate output characters in reverse order
	 */
	while(code >= 256) {
	    *stackp++ = tab_suffixof(code);
	    code = tab_prefixof(code);
	}
	*stackp++ = finchar = tab_suffixof(code);
	/*
	 * And put them out in forward order
	 */
	do {
	    *out_ptr++ = (char)*--stackp;
	} while(stackp > de_stack);
	/*
	 * Generate the new entry.
	 */
	if((code=free_ent) < maxmaxcode) {
	    tab_prefixof(code) = (unsigned short)oldcode;
	    tab_suffixof(code) = finchar;
	    free_ent = code+1;
	}
	/*
	 * Remember previous code.
	 */
	oldcode = incode;
    }
    return;
}

static unsigned char rmask[9] =
    {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};

static int get_core_bytes;
static char *core_ptr;
static int file_bytes();
static int core_bytes();

static long getcode()
{
    register long code;
    static int offset = 0, size = 0;
    static unsigned char buf[BITS];
    register int r_off, bits;
    register unsigned char *bp = buf;

    if(clear_flg > 0 || offset >= size || free_ent > maxcode) {
	/*
	 * If the next entry will be too big for the current code
	 * size, then we must increase the size.  This implies reading
	 * a new buffer full, too.
	 */
	if(free_ent > maxcode) {
	    n_bits++;
	    if(n_bits == maxbits) {
		maxcode = maxmaxcode;	/* won't get any bigger now */
	    } else {
		maxcode = MAXCODE(n_bits);
	    }
	}
	if(clear_flg > 0) {
	    maxcode = MAXCODE (n_bits = INIT_BITS);
	    clear_flg = 0;
	}
	if(toread == 0) {
	    return -1;
	}
	if(get_core_bytes) {
	    size = core_bytes((char *)buf, (n_bits < toread ? n_bits : toread));
	} else {
	    size = file_bytes((char *)buf, (n_bits < toread ? n_bits : toread));
	}
	toread -= size;
	if(size <= 0) {
	    (void)fprintf(stderr, "Premature EOF\n");
#ifdef SCAN
	    do_error("macunpack: Premature EOF");
#endif /* SCAN */
	    exit(1);
	}
	offset = 0;
	/* Round size down to integral number of codes */
	size = (size << 3) - (n_bits - 1);
    }
    r_off = offset;
    bits = n_bits;
    /*
     * Get to the first byte.
     */
    bp += (r_off >> 3);
    r_off &= 7;
    /* Get first part (low order bits) */
    code = (*bp++ >> r_off);
    bits -= (8 - r_off);
    r_off = 8 - r_off;		/* now, offset into code word */
    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
    if(bits >= 8) {
	code |= *bp++ << r_off;
	r_off += 8;
	bits -= 8;
    }
    /* high order bits. */
    code |= (*bp & rmask[bits]) << r_off;
    offset += n_bits;
    return code;
}

static int file_bytes(buf, length)
char *buf;
int length;
{
    return fread(buf, 1, length, infp);
}

static int core_bytes(buf, length)
char *buf;
int length;
{
    int i;

    for(i = 0; i < length; i++) {
	*buf++ = *core_ptr++;
    }
    return length;
}

void core_compress(ptr)
char *ptr;
{
    core_ptr = ptr;
    get_core_bytes = ptr != NULL;
}
#else /* DECOMPRESS */
int decompress; /* keep lint and some compilers happy */
#endif /* DECOMPRESS */