1*80ee5cbfSDavid du Colombier #include <u.h>
2*80ee5cbfSDavid du Colombier #include <libc.h>
3*80ee5cbfSDavid du Colombier #include <flate.h>
4*80ee5cbfSDavid du Colombier
5*80ee5cbfSDavid du Colombier enum {
6*80ee5cbfSDavid du Colombier HistorySize= 32*1024,
7*80ee5cbfSDavid du Colombier BufSize= 4*1024,
8*80ee5cbfSDavid du Colombier MaxHuffBits= 17, /* maximum bits in a encoded code */
9*80ee5cbfSDavid du Colombier Nlitlen= 288, /* number of litlen codes */
10*80ee5cbfSDavid du Colombier Noff= 32, /* number of offset codes */
11*80ee5cbfSDavid du Colombier Nclen= 19, /* number of codelen codes */
12*80ee5cbfSDavid du Colombier LenShift= 10, /* code = len<<LenShift|code */
13*80ee5cbfSDavid du Colombier LitlenBits= 7, /* number of bits in litlen decode table */
14*80ee5cbfSDavid du Colombier OffBits= 6, /* number of bits in offset decode table */
15*80ee5cbfSDavid du Colombier ClenBits= 6, /* number of bits in code len decode table */
16*80ee5cbfSDavid du Colombier MaxFlatBits= LitlenBits,
17*80ee5cbfSDavid du Colombier MaxLeaf= Nlitlen
18*80ee5cbfSDavid du Colombier };
19*80ee5cbfSDavid du Colombier
20*80ee5cbfSDavid du Colombier typedef struct Input Input;
21*80ee5cbfSDavid du Colombier typedef struct History History;
22*80ee5cbfSDavid du Colombier typedef struct Huff Huff;
23*80ee5cbfSDavid du Colombier
24*80ee5cbfSDavid du Colombier struct Input
25*80ee5cbfSDavid du Colombier {
26*80ee5cbfSDavid du Colombier int error; /* first error encountered, or FlateOk */
27*80ee5cbfSDavid du Colombier void *wr;
28*80ee5cbfSDavid du Colombier int (*w)(void*, void*, int);
29*80ee5cbfSDavid du Colombier void *getr;
30*80ee5cbfSDavid du Colombier int (*get)(void*);
31*80ee5cbfSDavid du Colombier ulong sreg;
32*80ee5cbfSDavid du Colombier int nbits;
33*80ee5cbfSDavid du Colombier };
34*80ee5cbfSDavid du Colombier
35*80ee5cbfSDavid du Colombier struct History
36*80ee5cbfSDavid du Colombier {
37*80ee5cbfSDavid du Colombier uchar his[HistorySize];
38*80ee5cbfSDavid du Colombier uchar *cp; /* current pointer in history */
39*80ee5cbfSDavid du Colombier int full; /* his has been filled up at least once */
40*80ee5cbfSDavid du Colombier };
41*80ee5cbfSDavid du Colombier
42*80ee5cbfSDavid du Colombier struct Huff
43*80ee5cbfSDavid du Colombier {
44*80ee5cbfSDavid du Colombier int maxbits; /* max bits for any code */
45*80ee5cbfSDavid du Colombier int minbits; /* min bits to get before looking in flat */
46*80ee5cbfSDavid du Colombier int flatmask; /* bits used in "flat" fast decoding table */
47*80ee5cbfSDavid du Colombier ulong flat[1<<MaxFlatBits];
48*80ee5cbfSDavid du Colombier ulong maxcode[MaxHuffBits];
49*80ee5cbfSDavid du Colombier ulong last[MaxHuffBits];
50*80ee5cbfSDavid du Colombier ulong decode[MaxLeaf];
51*80ee5cbfSDavid du Colombier };
52*80ee5cbfSDavid du Colombier
53*80ee5cbfSDavid du Colombier /* litlen code words 257-285 extra bits */
54*80ee5cbfSDavid du Colombier static int litlenextra[Nlitlen-257] =
55*80ee5cbfSDavid du Colombier {
56*80ee5cbfSDavid du Colombier /* 257 */ 0, 0, 0,
57*80ee5cbfSDavid du Colombier /* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
58*80ee5cbfSDavid du Colombier /* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
59*80ee5cbfSDavid du Colombier /* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
60*80ee5cbfSDavid du Colombier };
61*80ee5cbfSDavid du Colombier
62*80ee5cbfSDavid du Colombier static int litlenbase[Nlitlen-257];
63*80ee5cbfSDavid du Colombier
64*80ee5cbfSDavid du Colombier /* offset code word extra bits */
65*80ee5cbfSDavid du Colombier static int offextra[Noff] =
66*80ee5cbfSDavid du Colombier {
67*80ee5cbfSDavid du Colombier 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
68*80ee5cbfSDavid du Colombier 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
69*80ee5cbfSDavid du Colombier 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
70*80ee5cbfSDavid du Colombier 0, 0,
71*80ee5cbfSDavid du Colombier };
72*80ee5cbfSDavid du Colombier static int offbase[Noff];
73*80ee5cbfSDavid du Colombier
74*80ee5cbfSDavid du Colombier /* order code lengths */
75*80ee5cbfSDavid du Colombier static int clenorder[Nclen] =
76*80ee5cbfSDavid du Colombier {
77*80ee5cbfSDavid du Colombier 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
78*80ee5cbfSDavid du Colombier };
79*80ee5cbfSDavid du Colombier
80*80ee5cbfSDavid du Colombier /* for static huffman tables */
81*80ee5cbfSDavid du Colombier static Huff litlentab;
82*80ee5cbfSDavid du Colombier static Huff offtab;
83*80ee5cbfSDavid du Colombier static uchar revtab[256];
84*80ee5cbfSDavid du Colombier
85*80ee5cbfSDavid du Colombier static int uncblock(Input *in, History*);
86*80ee5cbfSDavid du Colombier static int fixedblock(Input *in, History*);
87*80ee5cbfSDavid du Colombier static int dynamicblock(Input *in, History*);
88*80ee5cbfSDavid du Colombier static int sregfill(Input *in, int n);
89*80ee5cbfSDavid du Colombier static int sregunget(Input *in);
90*80ee5cbfSDavid du Colombier static int decode(Input*, History*, Huff*, Huff*);
91*80ee5cbfSDavid du Colombier static int hufftab(Huff*, char*, int, int);
92*80ee5cbfSDavid du Colombier static int hdecsym(Input *in, Huff *h, int b);
93*80ee5cbfSDavid du Colombier
94*80ee5cbfSDavid du Colombier int
inflateinit(void)95*80ee5cbfSDavid du Colombier inflateinit(void)
96*80ee5cbfSDavid du Colombier {
97*80ee5cbfSDavid du Colombier char *len;
98*80ee5cbfSDavid du Colombier int i, j, base;
99*80ee5cbfSDavid du Colombier
100*80ee5cbfSDavid du Colombier /* byte reverse table */
101*80ee5cbfSDavid du Colombier for(i=0; i<256; i++)
102*80ee5cbfSDavid du Colombier for(j=0; j<8; j++)
103*80ee5cbfSDavid du Colombier if(i & (1<<j))
104*80ee5cbfSDavid du Colombier revtab[i] |= 0x80 >> j;
105*80ee5cbfSDavid du Colombier
106*80ee5cbfSDavid du Colombier for(i=257,base=3; i<Nlitlen; i++) {
107*80ee5cbfSDavid du Colombier litlenbase[i-257] = base;
108*80ee5cbfSDavid du Colombier base += 1<<litlenextra[i-257];
109*80ee5cbfSDavid du Colombier }
110*80ee5cbfSDavid du Colombier /* strange table entry in spec... */
111*80ee5cbfSDavid du Colombier litlenbase[285-257]--;
112*80ee5cbfSDavid du Colombier
113*80ee5cbfSDavid du Colombier for(i=0,base=1; i<Noff; i++) {
114*80ee5cbfSDavid du Colombier offbase[i] = base;
115*80ee5cbfSDavid du Colombier base += 1<<offextra[i];
116*80ee5cbfSDavid du Colombier }
117*80ee5cbfSDavid du Colombier
118*80ee5cbfSDavid du Colombier len = malloc(MaxLeaf);
119*80ee5cbfSDavid du Colombier if(len == nil)
120*80ee5cbfSDavid du Colombier return FlateNoMem;
121*80ee5cbfSDavid du Colombier
122*80ee5cbfSDavid du Colombier /* static Litlen bit lengths */
123*80ee5cbfSDavid du Colombier for(i=0; i<144; i++)
124*80ee5cbfSDavid du Colombier len[i] = 8;
125*80ee5cbfSDavid du Colombier for(i=144; i<256; i++)
126*80ee5cbfSDavid du Colombier len[i] = 9;
127*80ee5cbfSDavid du Colombier for(i=256; i<280; i++)
128*80ee5cbfSDavid du Colombier len[i] = 7;
129*80ee5cbfSDavid du Colombier for(i=280; i<Nlitlen; i++)
130*80ee5cbfSDavid du Colombier len[i] = 8;
131*80ee5cbfSDavid du Colombier
132*80ee5cbfSDavid du Colombier if(!hufftab(&litlentab, len, Nlitlen, MaxFlatBits))
133*80ee5cbfSDavid du Colombier return FlateInternal;
134*80ee5cbfSDavid du Colombier
135*80ee5cbfSDavid du Colombier /* static Offset bit lengths */
136*80ee5cbfSDavid du Colombier for(i=0; i<Noff; i++)
137*80ee5cbfSDavid du Colombier len[i] = 5;
138*80ee5cbfSDavid du Colombier
139*80ee5cbfSDavid du Colombier if(!hufftab(&offtab, len, Noff, MaxFlatBits))
140*80ee5cbfSDavid du Colombier return FlateInternal;
141*80ee5cbfSDavid du Colombier free(len);
142*80ee5cbfSDavid du Colombier
143*80ee5cbfSDavid du Colombier return FlateOk;
144*80ee5cbfSDavid du Colombier }
145*80ee5cbfSDavid du Colombier
146*80ee5cbfSDavid du Colombier int
inflate(void * wr,int (* w)(void *,void *,int),void * getr,int (* get)(void *))147*80ee5cbfSDavid du Colombier inflate(void *wr, int (*w)(void*, void*, int), void *getr, int (*get)(void*))
148*80ee5cbfSDavid du Colombier {
149*80ee5cbfSDavid du Colombier History *his;
150*80ee5cbfSDavid du Colombier Input in;
151*80ee5cbfSDavid du Colombier int final, type;
152*80ee5cbfSDavid du Colombier
153*80ee5cbfSDavid du Colombier his = malloc(sizeof(History));
154*80ee5cbfSDavid du Colombier if(his == nil)
155*80ee5cbfSDavid du Colombier return FlateNoMem;
156*80ee5cbfSDavid du Colombier his->cp = his->his;
157*80ee5cbfSDavid du Colombier his->full = 0;
158*80ee5cbfSDavid du Colombier in.getr = getr;
159*80ee5cbfSDavid du Colombier in.get = get;
160*80ee5cbfSDavid du Colombier in.wr = wr;
161*80ee5cbfSDavid du Colombier in.w = w;
162*80ee5cbfSDavid du Colombier in.nbits = 0;
163*80ee5cbfSDavid du Colombier in.sreg = 0;
164*80ee5cbfSDavid du Colombier in.error = FlateOk;
165*80ee5cbfSDavid du Colombier
166*80ee5cbfSDavid du Colombier do {
167*80ee5cbfSDavid du Colombier if(!sregfill(&in, 3))
168*80ee5cbfSDavid du Colombier goto bad;
169*80ee5cbfSDavid du Colombier final = in.sreg & 0x1;
170*80ee5cbfSDavid du Colombier type = (in.sreg>>1) & 0x3;
171*80ee5cbfSDavid du Colombier in.sreg >>= 3;
172*80ee5cbfSDavid du Colombier in.nbits -= 3;
173*80ee5cbfSDavid du Colombier switch(type) {
174*80ee5cbfSDavid du Colombier default:
175*80ee5cbfSDavid du Colombier in.error = FlateCorrupted;
176*80ee5cbfSDavid du Colombier goto bad;
177*80ee5cbfSDavid du Colombier case 0:
178*80ee5cbfSDavid du Colombier /* uncompressed */
179*80ee5cbfSDavid du Colombier if(!uncblock(&in, his))
180*80ee5cbfSDavid du Colombier goto bad;
181*80ee5cbfSDavid du Colombier break;
182*80ee5cbfSDavid du Colombier case 1:
183*80ee5cbfSDavid du Colombier /* fixed huffman */
184*80ee5cbfSDavid du Colombier if(!fixedblock(&in, his))
185*80ee5cbfSDavid du Colombier goto bad;
186*80ee5cbfSDavid du Colombier break;
187*80ee5cbfSDavid du Colombier case 2:
188*80ee5cbfSDavid du Colombier /* dynamic huffman */
189*80ee5cbfSDavid du Colombier if(!dynamicblock(&in, his))
190*80ee5cbfSDavid du Colombier goto bad;
191*80ee5cbfSDavid du Colombier break;
192*80ee5cbfSDavid du Colombier }
193*80ee5cbfSDavid du Colombier } while(!final);
194*80ee5cbfSDavid du Colombier
195*80ee5cbfSDavid du Colombier if(his->cp != his->his && (*w)(wr, his->his, his->cp - his->his) != his->cp - his->his) {
196*80ee5cbfSDavid du Colombier in.error = FlateOutputFail;
197*80ee5cbfSDavid du Colombier goto bad;
198*80ee5cbfSDavid du Colombier }
199*80ee5cbfSDavid du Colombier
200*80ee5cbfSDavid du Colombier if(!sregunget(&in))
201*80ee5cbfSDavid du Colombier goto bad;
202*80ee5cbfSDavid du Colombier
203*80ee5cbfSDavid du Colombier free(his);
204*80ee5cbfSDavid du Colombier if(in.error != FlateOk)
205*80ee5cbfSDavid du Colombier return FlateInternal;
206*80ee5cbfSDavid du Colombier return FlateOk;
207*80ee5cbfSDavid du Colombier
208*80ee5cbfSDavid du Colombier bad:
209*80ee5cbfSDavid du Colombier free(his);
210*80ee5cbfSDavid du Colombier if(in.error == FlateOk)
211*80ee5cbfSDavid du Colombier return FlateInternal;
212*80ee5cbfSDavid du Colombier return in.error;
213*80ee5cbfSDavid du Colombier }
214*80ee5cbfSDavid du Colombier
215*80ee5cbfSDavid du Colombier static int
uncblock(Input * in,History * his)216*80ee5cbfSDavid du Colombier uncblock(Input *in, History *his)
217*80ee5cbfSDavid du Colombier {
218*80ee5cbfSDavid du Colombier int len, nlen, c;
219*80ee5cbfSDavid du Colombier uchar *hs, *hp, *he;
220*80ee5cbfSDavid du Colombier
221*80ee5cbfSDavid du Colombier if(!sregunget(in))
222*80ee5cbfSDavid du Colombier return 0;
223*80ee5cbfSDavid du Colombier len = (*in->get)(in->getr);
224*80ee5cbfSDavid du Colombier len |= (*in->get)(in->getr)<<8;
225*80ee5cbfSDavid du Colombier nlen = (*in->get)(in->getr);
226*80ee5cbfSDavid du Colombier nlen |= (*in->get)(in->getr)<<8;
227*80ee5cbfSDavid du Colombier if(len != (~nlen&0xffff)) {
228*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
229*80ee5cbfSDavid du Colombier return 0;
230*80ee5cbfSDavid du Colombier }
231*80ee5cbfSDavid du Colombier
232*80ee5cbfSDavid du Colombier hp = his->cp;
233*80ee5cbfSDavid du Colombier hs = his->his;
234*80ee5cbfSDavid du Colombier he = hs + HistorySize;
235*80ee5cbfSDavid du Colombier
236*80ee5cbfSDavid du Colombier while(len > 0) {
237*80ee5cbfSDavid du Colombier c = (*in->get)(in->getr);
238*80ee5cbfSDavid du Colombier if(c < 0)
239*80ee5cbfSDavid du Colombier return 0;
240*80ee5cbfSDavid du Colombier *hp++ = c;
241*80ee5cbfSDavid du Colombier if(hp == he) {
242*80ee5cbfSDavid du Colombier his->full = 1;
243*80ee5cbfSDavid du Colombier if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
244*80ee5cbfSDavid du Colombier in->error = FlateOutputFail;
245*80ee5cbfSDavid du Colombier return 0;
246*80ee5cbfSDavid du Colombier }
247*80ee5cbfSDavid du Colombier hp = hs;
248*80ee5cbfSDavid du Colombier }
249*80ee5cbfSDavid du Colombier len--;
250*80ee5cbfSDavid du Colombier }
251*80ee5cbfSDavid du Colombier
252*80ee5cbfSDavid du Colombier his->cp = hp;
253*80ee5cbfSDavid du Colombier
254*80ee5cbfSDavid du Colombier return 1;
255*80ee5cbfSDavid du Colombier }
256*80ee5cbfSDavid du Colombier
257*80ee5cbfSDavid du Colombier static int
fixedblock(Input * in,History * his)258*80ee5cbfSDavid du Colombier fixedblock(Input *in, History *his)
259*80ee5cbfSDavid du Colombier {
260*80ee5cbfSDavid du Colombier return decode(in, his, &litlentab, &offtab);
261*80ee5cbfSDavid du Colombier }
262*80ee5cbfSDavid du Colombier
263*80ee5cbfSDavid du Colombier static int
dynamicblock(Input * in,History * his)264*80ee5cbfSDavid du Colombier dynamicblock(Input *in, History *his)
265*80ee5cbfSDavid du Colombier {
266*80ee5cbfSDavid du Colombier Huff *lentab, *offtab;
267*80ee5cbfSDavid du Colombier char *len;
268*80ee5cbfSDavid du Colombier int i, j, n, c, nlit, ndist, nclen, res, nb;
269*80ee5cbfSDavid du Colombier
270*80ee5cbfSDavid du Colombier if(!sregfill(in, 14))
271*80ee5cbfSDavid du Colombier return 0;
272*80ee5cbfSDavid du Colombier nlit = (in->sreg&0x1f) + 257;
273*80ee5cbfSDavid du Colombier ndist = ((in->sreg>>5) & 0x1f) + 1;
274*80ee5cbfSDavid du Colombier nclen = ((in->sreg>>10) & 0xf) + 4;
275*80ee5cbfSDavid du Colombier in->sreg >>= 14;
276*80ee5cbfSDavid du Colombier in->nbits -= 14;
277*80ee5cbfSDavid du Colombier
278*80ee5cbfSDavid du Colombier if(nlit > Nlitlen || ndist > Noff || nlit < 257) {
279*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
280*80ee5cbfSDavid du Colombier return 0;
281*80ee5cbfSDavid du Colombier }
282*80ee5cbfSDavid du Colombier
283*80ee5cbfSDavid du Colombier /* huff table header */
284*80ee5cbfSDavid du Colombier len = malloc(Nlitlen+Noff);
285*80ee5cbfSDavid du Colombier lentab = malloc(sizeof(Huff));
286*80ee5cbfSDavid du Colombier offtab = malloc(sizeof(Huff));
287*80ee5cbfSDavid du Colombier if(len == nil || lentab == nil || offtab == nil){
288*80ee5cbfSDavid du Colombier in->error = FlateNoMem;
289*80ee5cbfSDavid du Colombier goto bad;
290*80ee5cbfSDavid du Colombier }
291*80ee5cbfSDavid du Colombier for(i=0; i < Nclen; i++)
292*80ee5cbfSDavid du Colombier len[i] = 0;
293*80ee5cbfSDavid du Colombier for(i=0; i<nclen; i++) {
294*80ee5cbfSDavid du Colombier if(!sregfill(in, 3))
295*80ee5cbfSDavid du Colombier goto bad;
296*80ee5cbfSDavid du Colombier len[clenorder[i]] = in->sreg & 0x7;
297*80ee5cbfSDavid du Colombier in->sreg >>= 3;
298*80ee5cbfSDavid du Colombier in->nbits -= 3;
299*80ee5cbfSDavid du Colombier }
300*80ee5cbfSDavid du Colombier
301*80ee5cbfSDavid du Colombier if(!hufftab(lentab, len, Nclen, ClenBits)){
302*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
303*80ee5cbfSDavid du Colombier goto bad;
304*80ee5cbfSDavid du Colombier }
305*80ee5cbfSDavid du Colombier
306*80ee5cbfSDavid du Colombier n = nlit+ndist;
307*80ee5cbfSDavid du Colombier for(i=0; i<n;) {
308*80ee5cbfSDavid du Colombier nb = lentab->minbits;
309*80ee5cbfSDavid du Colombier for(;;){
310*80ee5cbfSDavid du Colombier if(in->nbits<nb && !sregfill(in, nb))
311*80ee5cbfSDavid du Colombier goto bad;
312*80ee5cbfSDavid du Colombier c = lentab->flat[in->sreg & lentab->flatmask];
313*80ee5cbfSDavid du Colombier nb = c & 0xff;
314*80ee5cbfSDavid du Colombier if(nb > in->nbits){
315*80ee5cbfSDavid du Colombier if(nb != 0xff)
316*80ee5cbfSDavid du Colombier continue;
317*80ee5cbfSDavid du Colombier c = hdecsym(in, lentab, c);
318*80ee5cbfSDavid du Colombier if(c < 0)
319*80ee5cbfSDavid du Colombier goto bad;
320*80ee5cbfSDavid du Colombier }else{
321*80ee5cbfSDavid du Colombier c >>= 8;
322*80ee5cbfSDavid du Colombier in->sreg >>= nb;
323*80ee5cbfSDavid du Colombier in->nbits -= nb;
324*80ee5cbfSDavid du Colombier }
325*80ee5cbfSDavid du Colombier break;
326*80ee5cbfSDavid du Colombier }
327*80ee5cbfSDavid du Colombier
328*80ee5cbfSDavid du Colombier if(c < 16) {
329*80ee5cbfSDavid du Colombier j = 1;
330*80ee5cbfSDavid du Colombier } else if(c == 16) {
331*80ee5cbfSDavid du Colombier if(in->nbits<2 && !sregfill(in, 2))
332*80ee5cbfSDavid du Colombier goto bad;
333*80ee5cbfSDavid du Colombier j = (in->sreg&0x3)+3;
334*80ee5cbfSDavid du Colombier in->sreg >>= 2;
335*80ee5cbfSDavid du Colombier in->nbits -= 2;
336*80ee5cbfSDavid du Colombier if(i == 0) {
337*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
338*80ee5cbfSDavid du Colombier goto bad;
339*80ee5cbfSDavid du Colombier }
340*80ee5cbfSDavid du Colombier c = len[i-1];
341*80ee5cbfSDavid du Colombier } else if(c == 17) {
342*80ee5cbfSDavid du Colombier if(in->nbits<3 && !sregfill(in, 3))
343*80ee5cbfSDavid du Colombier goto bad;
344*80ee5cbfSDavid du Colombier j = (in->sreg&0x7)+3;
345*80ee5cbfSDavid du Colombier in->sreg >>= 3;
346*80ee5cbfSDavid du Colombier in->nbits -= 3;
347*80ee5cbfSDavid du Colombier c = 0;
348*80ee5cbfSDavid du Colombier } else if(c == 18) {
349*80ee5cbfSDavid du Colombier if(in->nbits<7 && !sregfill(in, 7))
350*80ee5cbfSDavid du Colombier goto bad;
351*80ee5cbfSDavid du Colombier j = (in->sreg&0x7f)+11;
352*80ee5cbfSDavid du Colombier in->sreg >>= 7;
353*80ee5cbfSDavid du Colombier in->nbits -= 7;
354*80ee5cbfSDavid du Colombier c = 0;
355*80ee5cbfSDavid du Colombier } else {
356*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
357*80ee5cbfSDavid du Colombier goto bad;
358*80ee5cbfSDavid du Colombier }
359*80ee5cbfSDavid du Colombier
360*80ee5cbfSDavid du Colombier if(i+j > n) {
361*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
362*80ee5cbfSDavid du Colombier goto bad;
363*80ee5cbfSDavid du Colombier }
364*80ee5cbfSDavid du Colombier
365*80ee5cbfSDavid du Colombier while(j) {
366*80ee5cbfSDavid du Colombier len[i] = c;
367*80ee5cbfSDavid du Colombier i++;
368*80ee5cbfSDavid du Colombier j--;
369*80ee5cbfSDavid du Colombier }
370*80ee5cbfSDavid du Colombier }
371*80ee5cbfSDavid du Colombier
372*80ee5cbfSDavid du Colombier if(!hufftab(lentab, len, nlit, LitlenBits)
373*80ee5cbfSDavid du Colombier || !hufftab(offtab, &len[nlit], ndist, OffBits)){
374*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
375*80ee5cbfSDavid du Colombier goto bad;
376*80ee5cbfSDavid du Colombier }
377*80ee5cbfSDavid du Colombier
378*80ee5cbfSDavid du Colombier res = decode(in, his, lentab, offtab);
379*80ee5cbfSDavid du Colombier
380*80ee5cbfSDavid du Colombier free(len);
381*80ee5cbfSDavid du Colombier free(lentab);
382*80ee5cbfSDavid du Colombier free(offtab);
383*80ee5cbfSDavid du Colombier
384*80ee5cbfSDavid du Colombier return res;
385*80ee5cbfSDavid du Colombier
386*80ee5cbfSDavid du Colombier bad:
387*80ee5cbfSDavid du Colombier free(len);
388*80ee5cbfSDavid du Colombier free(lentab);
389*80ee5cbfSDavid du Colombier free(offtab);
390*80ee5cbfSDavid du Colombier return 0;
391*80ee5cbfSDavid du Colombier }
392*80ee5cbfSDavid du Colombier
393*80ee5cbfSDavid du Colombier static int
decode(Input * in,History * his,Huff * litlentab,Huff * offtab)394*80ee5cbfSDavid du Colombier decode(Input *in, History *his, Huff *litlentab, Huff *offtab)
395*80ee5cbfSDavid du Colombier {
396*80ee5cbfSDavid du Colombier int len, off;
397*80ee5cbfSDavid du Colombier uchar *hs, *hp, *hq, *he;
398*80ee5cbfSDavid du Colombier int c;
399*80ee5cbfSDavid du Colombier int nb;
400*80ee5cbfSDavid du Colombier
401*80ee5cbfSDavid du Colombier hs = his->his;
402*80ee5cbfSDavid du Colombier he = hs + HistorySize;
403*80ee5cbfSDavid du Colombier hp = his->cp;
404*80ee5cbfSDavid du Colombier
405*80ee5cbfSDavid du Colombier for(;;) {
406*80ee5cbfSDavid du Colombier nb = litlentab->minbits;
407*80ee5cbfSDavid du Colombier for(;;){
408*80ee5cbfSDavid du Colombier if(in->nbits<nb && !sregfill(in, nb))
409*80ee5cbfSDavid du Colombier return 0;
410*80ee5cbfSDavid du Colombier c = litlentab->flat[in->sreg & litlentab->flatmask];
411*80ee5cbfSDavid du Colombier nb = c & 0xff;
412*80ee5cbfSDavid du Colombier if(nb > in->nbits){
413*80ee5cbfSDavid du Colombier if(nb != 0xff)
414*80ee5cbfSDavid du Colombier continue;
415*80ee5cbfSDavid du Colombier c = hdecsym(in, litlentab, c);
416*80ee5cbfSDavid du Colombier if(c < 0)
417*80ee5cbfSDavid du Colombier return 0;
418*80ee5cbfSDavid du Colombier }else{
419*80ee5cbfSDavid du Colombier c >>= 8;
420*80ee5cbfSDavid du Colombier in->sreg >>= nb;
421*80ee5cbfSDavid du Colombier in->nbits -= nb;
422*80ee5cbfSDavid du Colombier }
423*80ee5cbfSDavid du Colombier break;
424*80ee5cbfSDavid du Colombier }
425*80ee5cbfSDavid du Colombier
426*80ee5cbfSDavid du Colombier if(c < 256) {
427*80ee5cbfSDavid du Colombier /* literal */
428*80ee5cbfSDavid du Colombier *hp++ = c;
429*80ee5cbfSDavid du Colombier if(hp == he) {
430*80ee5cbfSDavid du Colombier his->full = 1;
431*80ee5cbfSDavid du Colombier if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
432*80ee5cbfSDavid du Colombier in->error = FlateOutputFail;
433*80ee5cbfSDavid du Colombier return 0;
434*80ee5cbfSDavid du Colombier }
435*80ee5cbfSDavid du Colombier hp = hs;
436*80ee5cbfSDavid du Colombier }
437*80ee5cbfSDavid du Colombier continue;
438*80ee5cbfSDavid du Colombier }
439*80ee5cbfSDavid du Colombier
440*80ee5cbfSDavid du Colombier if(c == 256)
441*80ee5cbfSDavid du Colombier break;
442*80ee5cbfSDavid du Colombier
443*80ee5cbfSDavid du Colombier if(c > 285) {
444*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
445*80ee5cbfSDavid du Colombier return 0;
446*80ee5cbfSDavid du Colombier }
447*80ee5cbfSDavid du Colombier
448*80ee5cbfSDavid du Colombier c -= 257;
449*80ee5cbfSDavid du Colombier nb = litlenextra[c];
450*80ee5cbfSDavid du Colombier if(in->nbits < nb && !sregfill(in, nb))
451*80ee5cbfSDavid du Colombier return 0;
452*80ee5cbfSDavid du Colombier len = litlenbase[c] + (in->sreg & ((1<<nb)-1));
453*80ee5cbfSDavid du Colombier in->sreg >>= nb;
454*80ee5cbfSDavid du Colombier in->nbits -= nb;
455*80ee5cbfSDavid du Colombier
456*80ee5cbfSDavid du Colombier /* get offset */
457*80ee5cbfSDavid du Colombier nb = offtab->minbits;
458*80ee5cbfSDavid du Colombier for(;;){
459*80ee5cbfSDavid du Colombier if(in->nbits<nb && !sregfill(in, nb))
460*80ee5cbfSDavid du Colombier return 0;
461*80ee5cbfSDavid du Colombier c = offtab->flat[in->sreg & offtab->flatmask];
462*80ee5cbfSDavid du Colombier nb = c & 0xff;
463*80ee5cbfSDavid du Colombier if(nb > in->nbits){
464*80ee5cbfSDavid du Colombier if(nb != 0xff)
465*80ee5cbfSDavid du Colombier continue;
466*80ee5cbfSDavid du Colombier c = hdecsym(in, offtab, c);
467*80ee5cbfSDavid du Colombier if(c < 0)
468*80ee5cbfSDavid du Colombier return 0;
469*80ee5cbfSDavid du Colombier }else{
470*80ee5cbfSDavid du Colombier c >>= 8;
471*80ee5cbfSDavid du Colombier in->sreg >>= nb;
472*80ee5cbfSDavid du Colombier in->nbits -= nb;
473*80ee5cbfSDavid du Colombier }
474*80ee5cbfSDavid du Colombier break;
475*80ee5cbfSDavid du Colombier }
476*80ee5cbfSDavid du Colombier
477*80ee5cbfSDavid du Colombier if(c > 29) {
478*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
479*80ee5cbfSDavid du Colombier return 0;
480*80ee5cbfSDavid du Colombier }
481*80ee5cbfSDavid du Colombier
482*80ee5cbfSDavid du Colombier nb = offextra[c];
483*80ee5cbfSDavid du Colombier if(in->nbits < nb && !sregfill(in, nb))
484*80ee5cbfSDavid du Colombier return 0;
485*80ee5cbfSDavid du Colombier
486*80ee5cbfSDavid du Colombier off = offbase[c] + (in->sreg & ((1<<nb)-1));
487*80ee5cbfSDavid du Colombier in->sreg >>= nb;
488*80ee5cbfSDavid du Colombier in->nbits -= nb;
489*80ee5cbfSDavid du Colombier
490*80ee5cbfSDavid du Colombier hq = hp - off;
491*80ee5cbfSDavid du Colombier if(hq < hs) {
492*80ee5cbfSDavid du Colombier if(!his->full) {
493*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
494*80ee5cbfSDavid du Colombier return 0;
495*80ee5cbfSDavid du Colombier }
496*80ee5cbfSDavid du Colombier hq += HistorySize;
497*80ee5cbfSDavid du Colombier }
498*80ee5cbfSDavid du Colombier
499*80ee5cbfSDavid du Colombier /* slow but correct */
500*80ee5cbfSDavid du Colombier while(len) {
501*80ee5cbfSDavid du Colombier *hp = *hq;
502*80ee5cbfSDavid du Colombier hq++;
503*80ee5cbfSDavid du Colombier hp++;
504*80ee5cbfSDavid du Colombier if(hq >= he)
505*80ee5cbfSDavid du Colombier hq = hs;
506*80ee5cbfSDavid du Colombier if(hp == he) {
507*80ee5cbfSDavid du Colombier his->full = 1;
508*80ee5cbfSDavid du Colombier if((*in->w)(in->wr, hs, HistorySize) != HistorySize) {
509*80ee5cbfSDavid du Colombier in->error = FlateOutputFail;
510*80ee5cbfSDavid du Colombier return 0;
511*80ee5cbfSDavid du Colombier }
512*80ee5cbfSDavid du Colombier hp = hs;
513*80ee5cbfSDavid du Colombier }
514*80ee5cbfSDavid du Colombier len--;
515*80ee5cbfSDavid du Colombier }
516*80ee5cbfSDavid du Colombier
517*80ee5cbfSDavid du Colombier }
518*80ee5cbfSDavid du Colombier
519*80ee5cbfSDavid du Colombier his->cp = hp;
520*80ee5cbfSDavid du Colombier
521*80ee5cbfSDavid du Colombier return 1;
522*80ee5cbfSDavid du Colombier }
523*80ee5cbfSDavid du Colombier
524*80ee5cbfSDavid du Colombier static int
revcode(int c,int b)525*80ee5cbfSDavid du Colombier revcode(int c, int b)
526*80ee5cbfSDavid du Colombier {
527*80ee5cbfSDavid du Colombier /* shift encode up so it starts on bit 15 then reverse */
528*80ee5cbfSDavid du Colombier c <<= (16-b);
529*80ee5cbfSDavid du Colombier c = revtab[c>>8] | (revtab[c&0xff]<<8);
530*80ee5cbfSDavid du Colombier return c;
531*80ee5cbfSDavid du Colombier }
532*80ee5cbfSDavid du Colombier
533*80ee5cbfSDavid du Colombier /*
534*80ee5cbfSDavid du Colombier * construct the huffman decoding arrays and a fast lookup table.
535*80ee5cbfSDavid du Colombier * the fast lookup is a table indexed by the next flatbits bits,
536*80ee5cbfSDavid du Colombier * which returns the symbol matched and the number of bits consumed,
537*80ee5cbfSDavid du Colombier * or the minimum number of bits needed and 0xff if more than flatbits
538*80ee5cbfSDavid du Colombier * bits are needed.
539*80ee5cbfSDavid du Colombier *
540*80ee5cbfSDavid du Colombier * flatbits can be longer than the smallest huffman code,
541*80ee5cbfSDavid du Colombier * because shorter codes are assigned smaller lexical prefixes.
542*80ee5cbfSDavid du Colombier * this means assuming zeros for the next few bits will give a
543*80ee5cbfSDavid du Colombier * conservative answer, in the sense that it will either give the
544*80ee5cbfSDavid du Colombier * correct answer, or return the minimum number of bits which
545*80ee5cbfSDavid du Colombier * are needed for an answer.
546*80ee5cbfSDavid du Colombier */
547*80ee5cbfSDavid du Colombier static int
hufftab(Huff * h,char * hb,int maxleaf,int flatbits)548*80ee5cbfSDavid du Colombier hufftab(Huff *h, char *hb, int maxleaf, int flatbits)
549*80ee5cbfSDavid du Colombier {
550*80ee5cbfSDavid du Colombier ulong bitcount[MaxHuffBits];
551*80ee5cbfSDavid du Colombier ulong c, fc, ec, mincode, code, nc[MaxHuffBits];
552*80ee5cbfSDavid du Colombier int i, b, minbits, maxbits;
553*80ee5cbfSDavid du Colombier
554*80ee5cbfSDavid du Colombier for(i = 0; i < MaxHuffBits; i++)
555*80ee5cbfSDavid du Colombier bitcount[i] = 0;
556*80ee5cbfSDavid du Colombier maxbits = -1;
557*80ee5cbfSDavid du Colombier minbits = MaxHuffBits + 1;
558*80ee5cbfSDavid du Colombier for(i=0; i < maxleaf; i++){
559*80ee5cbfSDavid du Colombier b = hb[i];
560*80ee5cbfSDavid du Colombier if(b){
561*80ee5cbfSDavid du Colombier bitcount[b]++;
562*80ee5cbfSDavid du Colombier if(b < minbits)
563*80ee5cbfSDavid du Colombier minbits = b;
564*80ee5cbfSDavid du Colombier if(b > maxbits)
565*80ee5cbfSDavid du Colombier maxbits = b;
566*80ee5cbfSDavid du Colombier }
567*80ee5cbfSDavid du Colombier }
568*80ee5cbfSDavid du Colombier
569*80ee5cbfSDavid du Colombier h->maxbits = maxbits;
570*80ee5cbfSDavid du Colombier if(maxbits <= 0){
571*80ee5cbfSDavid du Colombier h->maxbits = 0;
572*80ee5cbfSDavid du Colombier h->minbits = 0;
573*80ee5cbfSDavid du Colombier h->flatmask = 0;
574*80ee5cbfSDavid du Colombier return 1;
575*80ee5cbfSDavid du Colombier }
576*80ee5cbfSDavid du Colombier code = 0;
577*80ee5cbfSDavid du Colombier c = 0;
578*80ee5cbfSDavid du Colombier for(b = 0; b <= maxbits; b++){
579*80ee5cbfSDavid du Colombier h->last[b] = c;
580*80ee5cbfSDavid du Colombier c += bitcount[b];
581*80ee5cbfSDavid du Colombier mincode = code << 1;
582*80ee5cbfSDavid du Colombier nc[b] = mincode;
583*80ee5cbfSDavid du Colombier code = mincode + bitcount[b];
584*80ee5cbfSDavid du Colombier if(code > (1 << b))
585*80ee5cbfSDavid du Colombier return 0;
586*80ee5cbfSDavid du Colombier h->maxcode[b] = code - 1;
587*80ee5cbfSDavid du Colombier h->last[b] += code - 1;
588*80ee5cbfSDavid du Colombier }
589*80ee5cbfSDavid du Colombier
590*80ee5cbfSDavid du Colombier if(flatbits > maxbits)
591*80ee5cbfSDavid du Colombier flatbits = maxbits;
592*80ee5cbfSDavid du Colombier h->flatmask = (1 << flatbits) - 1;
593*80ee5cbfSDavid du Colombier if(minbits > flatbits)
594*80ee5cbfSDavid du Colombier minbits = flatbits;
595*80ee5cbfSDavid du Colombier h->minbits = minbits;
596*80ee5cbfSDavid du Colombier
597*80ee5cbfSDavid du Colombier b = 1 << flatbits;
598*80ee5cbfSDavid du Colombier for(i = 0; i < b; i++)
599*80ee5cbfSDavid du Colombier h->flat[i] = ~0;
600*80ee5cbfSDavid du Colombier
601*80ee5cbfSDavid du Colombier /*
602*80ee5cbfSDavid du Colombier * initialize the flat table to include the minimum possible
603*80ee5cbfSDavid du Colombier * bit length for each code prefix
604*80ee5cbfSDavid du Colombier */
605*80ee5cbfSDavid du Colombier for(b = maxbits; b > flatbits; b--){
606*80ee5cbfSDavid du Colombier code = h->maxcode[b];
607*80ee5cbfSDavid du Colombier if(code == -1)
608*80ee5cbfSDavid du Colombier break;
609*80ee5cbfSDavid du Colombier mincode = code + 1 - bitcount[b];
610*80ee5cbfSDavid du Colombier mincode >>= b - flatbits;
611*80ee5cbfSDavid du Colombier code >>= b - flatbits;
612*80ee5cbfSDavid du Colombier for(; mincode <= code; mincode++)
613*80ee5cbfSDavid du Colombier h->flat[revcode(mincode, flatbits)] = (b << 8) | 0xff;
614*80ee5cbfSDavid du Colombier }
615*80ee5cbfSDavid du Colombier
616*80ee5cbfSDavid du Colombier for(i = 0; i < maxleaf; i++){
617*80ee5cbfSDavid du Colombier b = hb[i];
618*80ee5cbfSDavid du Colombier if(b <= 0)
619*80ee5cbfSDavid du Colombier continue;
620*80ee5cbfSDavid du Colombier c = nc[b]++;
621*80ee5cbfSDavid du Colombier if(b <= flatbits){
622*80ee5cbfSDavid du Colombier code = (i << 8) | b;
623*80ee5cbfSDavid du Colombier ec = (c + 1) << (flatbits - b);
624*80ee5cbfSDavid du Colombier if(ec > (1<<flatbits))
625*80ee5cbfSDavid du Colombier return 0; /* this is actually an internal error */
626*80ee5cbfSDavid du Colombier for(fc = c << (flatbits - b); fc < ec; fc++)
627*80ee5cbfSDavid du Colombier h->flat[revcode(fc, flatbits)] = code;
628*80ee5cbfSDavid du Colombier }
629*80ee5cbfSDavid du Colombier if(b > minbits){
630*80ee5cbfSDavid du Colombier c = h->last[b] - c;
631*80ee5cbfSDavid du Colombier if(c >= maxleaf)
632*80ee5cbfSDavid du Colombier return 0;
633*80ee5cbfSDavid du Colombier h->decode[c] = i;
634*80ee5cbfSDavid du Colombier }
635*80ee5cbfSDavid du Colombier }
636*80ee5cbfSDavid du Colombier return 1;
637*80ee5cbfSDavid du Colombier }
638*80ee5cbfSDavid du Colombier
639*80ee5cbfSDavid du Colombier static int
hdecsym(Input * in,Huff * h,int nb)640*80ee5cbfSDavid du Colombier hdecsym(Input *in, Huff *h, int nb)
641*80ee5cbfSDavid du Colombier {
642*80ee5cbfSDavid du Colombier long c;
643*80ee5cbfSDavid du Colombier
644*80ee5cbfSDavid du Colombier if((nb & 0xff) == 0xff)
645*80ee5cbfSDavid du Colombier nb = nb >> 8;
646*80ee5cbfSDavid du Colombier else
647*80ee5cbfSDavid du Colombier nb = nb & 0xff;
648*80ee5cbfSDavid du Colombier for(; nb <= h->maxbits; nb++){
649*80ee5cbfSDavid du Colombier if(in->nbits<nb && !sregfill(in, nb))
650*80ee5cbfSDavid du Colombier return -1;
651*80ee5cbfSDavid du Colombier c = revtab[in->sreg&0xff]<<8;
652*80ee5cbfSDavid du Colombier c |= revtab[(in->sreg>>8)&0xff];
653*80ee5cbfSDavid du Colombier c >>= (16-nb);
654*80ee5cbfSDavid du Colombier if(c <= h->maxcode[nb]){
655*80ee5cbfSDavid du Colombier in->sreg >>= nb;
656*80ee5cbfSDavid du Colombier in->nbits -= nb;
657*80ee5cbfSDavid du Colombier return h->decode[h->last[nb] - c];
658*80ee5cbfSDavid du Colombier }
659*80ee5cbfSDavid du Colombier }
660*80ee5cbfSDavid du Colombier in->error = FlateCorrupted;
661*80ee5cbfSDavid du Colombier return -1;
662*80ee5cbfSDavid du Colombier }
663*80ee5cbfSDavid du Colombier
664*80ee5cbfSDavid du Colombier static int
sregfill(Input * in,int n)665*80ee5cbfSDavid du Colombier sregfill(Input *in, int n)
666*80ee5cbfSDavid du Colombier {
667*80ee5cbfSDavid du Colombier int c;
668*80ee5cbfSDavid du Colombier
669*80ee5cbfSDavid du Colombier while(n > in->nbits) {
670*80ee5cbfSDavid du Colombier c = (*in->get)(in->getr);
671*80ee5cbfSDavid du Colombier if(c < 0){
672*80ee5cbfSDavid du Colombier in->error = FlateInputFail;
673*80ee5cbfSDavid du Colombier return 0;
674*80ee5cbfSDavid du Colombier }
675*80ee5cbfSDavid du Colombier in->sreg |= c<<in->nbits;
676*80ee5cbfSDavid du Colombier in->nbits += 8;
677*80ee5cbfSDavid du Colombier }
678*80ee5cbfSDavid du Colombier return 1;
679*80ee5cbfSDavid du Colombier }
680*80ee5cbfSDavid du Colombier
681*80ee5cbfSDavid du Colombier static int
sregunget(Input * in)682*80ee5cbfSDavid du Colombier sregunget(Input *in)
683*80ee5cbfSDavid du Colombier {
684*80ee5cbfSDavid du Colombier if(in->nbits >= 8) {
685*80ee5cbfSDavid du Colombier in->error = FlateInternal;
686*80ee5cbfSDavid du Colombier return 0;
687*80ee5cbfSDavid du Colombier }
688*80ee5cbfSDavid du Colombier
689*80ee5cbfSDavid du Colombier /* throw other bits on the floor */
690*80ee5cbfSDavid du Colombier in->nbits = 0;
691*80ee5cbfSDavid du Colombier in->sreg = 0;
692*80ee5cbfSDavid du Colombier return 1;
693*80ee5cbfSDavid du Colombier }
694