xref: /inferno-os/libfreetype/infcodes.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /* infcodes.c -- process literals and length/distance pairs
2*37da2899SCharles.Forsyth  * Copyright (C) 1995-2002 Mark Adler
3*37da2899SCharles.Forsyth  * For conditions of distribution and use, see copyright notice in zlib.h
4*37da2899SCharles.Forsyth  */
5*37da2899SCharles.Forsyth 
6*37da2899SCharles.Forsyth #include "zutil.h"
7*37da2899SCharles.Forsyth #include "inftrees.h"
8*37da2899SCharles.Forsyth #include "infblock.h"
9*37da2899SCharles.Forsyth #include "infcodes.h"
10*37da2899SCharles.Forsyth #include "infutil.h"
11*37da2899SCharles.Forsyth 
12*37da2899SCharles.Forsyth /* simplify the use of the inflate_huft type with some defines */
13*37da2899SCharles.Forsyth #define exop word.what.Exop
14*37da2899SCharles.Forsyth #define bits word.what.Bits
15*37da2899SCharles.Forsyth 
16*37da2899SCharles.Forsyth typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
17*37da2899SCharles.Forsyth       START,    /* x: set up for LEN */
18*37da2899SCharles.Forsyth       LEN,      /* i: get length/literal/eob next */
19*37da2899SCharles.Forsyth       LENEXT,   /* i: getting length extra (have base) */
20*37da2899SCharles.Forsyth       DIST,     /* i: get distance next */
21*37da2899SCharles.Forsyth       DISTEXT,  /* i: getting distance extra */
22*37da2899SCharles.Forsyth       COPY,     /* o: copying bytes in window, waiting for space */
23*37da2899SCharles.Forsyth       LIT,      /* o: got literal, waiting for output space */
24*37da2899SCharles.Forsyth       WASH,     /* o: got eob, possibly still output waiting */
25*37da2899SCharles.Forsyth       END,      /* x: got eob and all data flushed */
26*37da2899SCharles.Forsyth       BADCODE}  /* x: got error */
27*37da2899SCharles.Forsyth inflate_codes_mode;
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth /* inflate codes private state */
30*37da2899SCharles.Forsyth struct inflate_codes_state {
31*37da2899SCharles.Forsyth 
32*37da2899SCharles.Forsyth   /* mode */
33*37da2899SCharles.Forsyth   inflate_codes_mode mode;      /* current inflate_codes mode */
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth   /* mode dependent information */
36*37da2899SCharles.Forsyth   uInt len;
37*37da2899SCharles.Forsyth   union {
38*37da2899SCharles.Forsyth     struct {
39*37da2899SCharles.Forsyth       inflate_huft *tree;       /* pointer into tree */
40*37da2899SCharles.Forsyth       uInt need;                /* bits needed */
41*37da2899SCharles.Forsyth     } code;             /* if LEN or DIST, where in tree */
42*37da2899SCharles.Forsyth     uInt lit;           /* if LIT, literal */
43*37da2899SCharles.Forsyth     struct {
44*37da2899SCharles.Forsyth       uInt get;                 /* bits to get for extra */
45*37da2899SCharles.Forsyth       uInt dist;                /* distance back to copy from */
46*37da2899SCharles.Forsyth     } copy;             /* if EXT or COPY, where and how much */
47*37da2899SCharles.Forsyth   } sub;                /* submode */
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth   /* mode independent information */
50*37da2899SCharles.Forsyth   Byte lbits;           /* ltree bits decoded per branch */
51*37da2899SCharles.Forsyth   Byte dbits;           /* dtree bits decoder per branch */
52*37da2899SCharles.Forsyth   inflate_huft *ltree;          /* literal/length/eob tree */
53*37da2899SCharles.Forsyth   inflate_huft *dtree;          /* distance tree */
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth };
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth 
inflate_codes_new(bl,bd,tl,td,z)58*37da2899SCharles.Forsyth local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
59*37da2899SCharles.Forsyth uInt bl, bd;
60*37da2899SCharles.Forsyth inflate_huft *tl;
61*37da2899SCharles.Forsyth inflate_huft *td; /* need separate declaration for Borland C++ */
62*37da2899SCharles.Forsyth z_streamp z;
63*37da2899SCharles.Forsyth {
64*37da2899SCharles.Forsyth   inflate_codes_statef *c;
65*37da2899SCharles.Forsyth 
66*37da2899SCharles.Forsyth   if ((c = (inflate_codes_statef *)
67*37da2899SCharles.Forsyth        ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
68*37da2899SCharles.Forsyth   {
69*37da2899SCharles.Forsyth     c->mode = START;
70*37da2899SCharles.Forsyth     c->lbits = (Byte)bl;
71*37da2899SCharles.Forsyth     c->dbits = (Byte)bd;
72*37da2899SCharles.Forsyth     c->ltree = tl;
73*37da2899SCharles.Forsyth     c->dtree = td;
74*37da2899SCharles.Forsyth     Tracev((stderr, "inflate:       codes new\n"));
75*37da2899SCharles.Forsyth   }
76*37da2899SCharles.Forsyth   return c;
77*37da2899SCharles.Forsyth }
78*37da2899SCharles.Forsyth 
79*37da2899SCharles.Forsyth 
inflate_codes(s,z,r)80*37da2899SCharles.Forsyth local int inflate_codes(s, z, r)
81*37da2899SCharles.Forsyth inflate_blocks_statef *s;
82*37da2899SCharles.Forsyth z_streamp z;
83*37da2899SCharles.Forsyth int r;
84*37da2899SCharles.Forsyth {
85*37da2899SCharles.Forsyth   uInt j;               /* temporary storage */
86*37da2899SCharles.Forsyth   inflate_huft *t;      /* temporary pointer */
87*37da2899SCharles.Forsyth   uInt e;               /* extra bits or operation */
88*37da2899SCharles.Forsyth   uLong b;              /* bit buffer */
89*37da2899SCharles.Forsyth   uInt k;               /* bits in bit buffer */
90*37da2899SCharles.Forsyth   Bytef *p;             /* input data pointer */
91*37da2899SCharles.Forsyth   uInt n;               /* bytes available there */
92*37da2899SCharles.Forsyth   Bytef *q;             /* output window write pointer */
93*37da2899SCharles.Forsyth   uInt m;               /* bytes to end of window or read pointer */
94*37da2899SCharles.Forsyth   Bytef *f;             /* pointer to copy strings from */
95*37da2899SCharles.Forsyth   inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth   /* copy input/output information to locals (UPDATE macro restores) */
98*37da2899SCharles.Forsyth   LOAD
99*37da2899SCharles.Forsyth 
100*37da2899SCharles.Forsyth   /* process input and output based on current state */
101*37da2899SCharles.Forsyth   while (1) switch (c->mode)
102*37da2899SCharles.Forsyth   {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
103*37da2899SCharles.Forsyth     case START:         /* x: set up for LEN */
104*37da2899SCharles.Forsyth #ifndef SLOW
105*37da2899SCharles.Forsyth       if (m >= 258 && n >= 10)
106*37da2899SCharles.Forsyth       {
107*37da2899SCharles.Forsyth         UPDATE
108*37da2899SCharles.Forsyth         r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
109*37da2899SCharles.Forsyth         LOAD
110*37da2899SCharles.Forsyth         if (r != Z_OK)
111*37da2899SCharles.Forsyth         {
112*37da2899SCharles.Forsyth           c->mode = r == Z_STREAM_END ? WASH : BADCODE;
113*37da2899SCharles.Forsyth           break;
114*37da2899SCharles.Forsyth         }
115*37da2899SCharles.Forsyth       }
116*37da2899SCharles.Forsyth #endif /* !SLOW */
117*37da2899SCharles.Forsyth       c->sub.code.need = c->lbits;
118*37da2899SCharles.Forsyth       c->sub.code.tree = c->ltree;
119*37da2899SCharles.Forsyth       c->mode = LEN;
120*37da2899SCharles.Forsyth     case LEN:           /* i: get length/literal/eob next */
121*37da2899SCharles.Forsyth       j = c->sub.code.need;
122*37da2899SCharles.Forsyth       NEEDBITS(j)
123*37da2899SCharles.Forsyth       t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
124*37da2899SCharles.Forsyth       DUMPBITS(t->bits)
125*37da2899SCharles.Forsyth       e = (uInt)(t->exop);
126*37da2899SCharles.Forsyth       if (e == 0)               /* literal */
127*37da2899SCharles.Forsyth       {
128*37da2899SCharles.Forsyth         c->sub.lit = t->base;
129*37da2899SCharles.Forsyth         Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
130*37da2899SCharles.Forsyth                  "inflate:         literal '%c'\n" :
131*37da2899SCharles.Forsyth                  "inflate:         literal 0x%02x\n", t->base));
132*37da2899SCharles.Forsyth         c->mode = LIT;
133*37da2899SCharles.Forsyth         break;
134*37da2899SCharles.Forsyth       }
135*37da2899SCharles.Forsyth       if (e & 16)               /* length */
136*37da2899SCharles.Forsyth       {
137*37da2899SCharles.Forsyth         c->sub.copy.get = e & 15;
138*37da2899SCharles.Forsyth         c->len = t->base;
139*37da2899SCharles.Forsyth         c->mode = LENEXT;
140*37da2899SCharles.Forsyth         break;
141*37da2899SCharles.Forsyth       }
142*37da2899SCharles.Forsyth       if ((e & 64) == 0)        /* next table */
143*37da2899SCharles.Forsyth       {
144*37da2899SCharles.Forsyth         c->sub.code.need = e;
145*37da2899SCharles.Forsyth         c->sub.code.tree = t + t->base;
146*37da2899SCharles.Forsyth         break;
147*37da2899SCharles.Forsyth       }
148*37da2899SCharles.Forsyth       if (e & 32)               /* end of block */
149*37da2899SCharles.Forsyth       {
150*37da2899SCharles.Forsyth         Tracevv((stderr, "inflate:         end of block\n"));
151*37da2899SCharles.Forsyth         c->mode = WASH;
152*37da2899SCharles.Forsyth         break;
153*37da2899SCharles.Forsyth       }
154*37da2899SCharles.Forsyth       c->mode = BADCODE;        /* invalid code */
155*37da2899SCharles.Forsyth       z->msg = (char*)"invalid literal/length code";
156*37da2899SCharles.Forsyth       r = Z_DATA_ERROR;
157*37da2899SCharles.Forsyth       LEAVE
158*37da2899SCharles.Forsyth     case LENEXT:        /* i: getting length extra (have base) */
159*37da2899SCharles.Forsyth       j = c->sub.copy.get;
160*37da2899SCharles.Forsyth       NEEDBITS(j)
161*37da2899SCharles.Forsyth       c->len += (uInt)b & inflate_mask[j];
162*37da2899SCharles.Forsyth       DUMPBITS(j)
163*37da2899SCharles.Forsyth       c->sub.code.need = c->dbits;
164*37da2899SCharles.Forsyth       c->sub.code.tree = c->dtree;
165*37da2899SCharles.Forsyth       Tracevv((stderr, "inflate:         length %u\n", c->len));
166*37da2899SCharles.Forsyth       c->mode = DIST;
167*37da2899SCharles.Forsyth     case DIST:          /* i: get distance next */
168*37da2899SCharles.Forsyth       j = c->sub.code.need;
169*37da2899SCharles.Forsyth       NEEDBITS(j)
170*37da2899SCharles.Forsyth       t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
171*37da2899SCharles.Forsyth       DUMPBITS(t->bits)
172*37da2899SCharles.Forsyth       e = (uInt)(t->exop);
173*37da2899SCharles.Forsyth       if (e & 16)               /* distance */
174*37da2899SCharles.Forsyth       {
175*37da2899SCharles.Forsyth         c->sub.copy.get = e & 15;
176*37da2899SCharles.Forsyth         c->sub.copy.dist = t->base;
177*37da2899SCharles.Forsyth         c->mode = DISTEXT;
178*37da2899SCharles.Forsyth         break;
179*37da2899SCharles.Forsyth       }
180*37da2899SCharles.Forsyth       if ((e & 64) == 0)        /* next table */
181*37da2899SCharles.Forsyth       {
182*37da2899SCharles.Forsyth         c->sub.code.need = e;
183*37da2899SCharles.Forsyth         c->sub.code.tree = t + t->base;
184*37da2899SCharles.Forsyth         break;
185*37da2899SCharles.Forsyth       }
186*37da2899SCharles.Forsyth       c->mode = BADCODE;        /* invalid code */
187*37da2899SCharles.Forsyth       z->msg = (char*)"invalid distance code";
188*37da2899SCharles.Forsyth       r = Z_DATA_ERROR;
189*37da2899SCharles.Forsyth       LEAVE
190*37da2899SCharles.Forsyth     case DISTEXT:       /* i: getting distance extra */
191*37da2899SCharles.Forsyth       j = c->sub.copy.get;
192*37da2899SCharles.Forsyth       NEEDBITS(j)
193*37da2899SCharles.Forsyth       c->sub.copy.dist += (uInt)b & inflate_mask[j];
194*37da2899SCharles.Forsyth       DUMPBITS(j)
195*37da2899SCharles.Forsyth       Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
196*37da2899SCharles.Forsyth       c->mode = COPY;
197*37da2899SCharles.Forsyth     case COPY:          /* o: copying bytes in window, waiting for space */
198*37da2899SCharles.Forsyth       f = q - c->sub.copy.dist;
199*37da2899SCharles.Forsyth       while (f < s->window)             /* modulo window size-"while" instead */
200*37da2899SCharles.Forsyth         f += s->end - s->window;        /* of "if" handles invalid distances */
201*37da2899SCharles.Forsyth       while (c->len)
202*37da2899SCharles.Forsyth       {
203*37da2899SCharles.Forsyth         NEEDOUT
204*37da2899SCharles.Forsyth         OUTBYTE(*f++)
205*37da2899SCharles.Forsyth         if (f == s->end)
206*37da2899SCharles.Forsyth           f = s->window;
207*37da2899SCharles.Forsyth         c->len--;
208*37da2899SCharles.Forsyth       }
209*37da2899SCharles.Forsyth       c->mode = START;
210*37da2899SCharles.Forsyth       break;
211*37da2899SCharles.Forsyth     case LIT:           /* o: got literal, waiting for output space */
212*37da2899SCharles.Forsyth       NEEDOUT
213*37da2899SCharles.Forsyth       OUTBYTE(c->sub.lit)
214*37da2899SCharles.Forsyth       c->mode = START;
215*37da2899SCharles.Forsyth       break;
216*37da2899SCharles.Forsyth     case WASH:          /* o: got eob, possibly more output */
217*37da2899SCharles.Forsyth       if (k > 7)        /* return unused byte, if any */
218*37da2899SCharles.Forsyth       {
219*37da2899SCharles.Forsyth         Assert(k < 16, "inflate_codes grabbed too many bytes")
220*37da2899SCharles.Forsyth         k -= 8;
221*37da2899SCharles.Forsyth         n++;
222*37da2899SCharles.Forsyth         p--;            /* can always return one */
223*37da2899SCharles.Forsyth       }
224*37da2899SCharles.Forsyth       FLUSH
225*37da2899SCharles.Forsyth       if (s->read != s->write)
226*37da2899SCharles.Forsyth         LEAVE
227*37da2899SCharles.Forsyth       c->mode = END;
228*37da2899SCharles.Forsyth     case END:
229*37da2899SCharles.Forsyth       r = Z_STREAM_END;
230*37da2899SCharles.Forsyth       LEAVE
231*37da2899SCharles.Forsyth     case BADCODE:       /* x: got error */
232*37da2899SCharles.Forsyth       r = Z_DATA_ERROR;
233*37da2899SCharles.Forsyth       LEAVE
234*37da2899SCharles.Forsyth     default:
235*37da2899SCharles.Forsyth       r = Z_STREAM_ERROR;
236*37da2899SCharles.Forsyth       LEAVE
237*37da2899SCharles.Forsyth   }
238*37da2899SCharles.Forsyth #ifdef NEED_DUMMY_RETURN
239*37da2899SCharles.Forsyth   return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
240*37da2899SCharles.Forsyth #endif
241*37da2899SCharles.Forsyth }
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth 
inflate_codes_free(c,z)244*37da2899SCharles.Forsyth local void inflate_codes_free(c, z)
245*37da2899SCharles.Forsyth inflate_codes_statef *c;
246*37da2899SCharles.Forsyth z_streamp z;
247*37da2899SCharles.Forsyth {
248*37da2899SCharles.Forsyth   ZFREE(z, c);
249*37da2899SCharles.Forsyth   Tracev((stderr, "inflate:       codes free\n"));
250*37da2899SCharles.Forsyth }
251