ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / lib / zlib_inflate / infcodes.c
1 /* infcodes.c -- process literals and length/distance pairs
2  * Copyright (C) 1995-1998 Mark Adler
3  * For conditions of distribution and use, see copyright notice in zlib.h 
4  */
5
6 #include <linux/zutil.h>
7 #include "inftrees.h"
8 #include "infblock.h"
9 #include "infcodes.h"
10 #include "infutil.h"
11 #include "inffast.h"
12
13 /* simplify the use of the inflate_huft type with some defines */
14 #define exop word.what.Exop
15 #define bits word.what.Bits
16
17 inflate_codes_statef *zlib_inflate_codes_new(
18         uInt bl,
19         uInt bd,
20         inflate_huft *tl,
21         inflate_huft *td, /* need separate declaration for Borland C++ */
22         z_streamp z
23 )
24 {
25   inflate_codes_statef *c;
26
27   c = &WS(z)->working_state;
28   {
29     c->mode = START;
30     c->lbits = (Byte)bl;
31     c->dbits = (Byte)bd;
32     c->ltree = tl;
33     c->dtree = td;
34   }
35   return c;
36 }
37
38
39 int zlib_inflate_codes(
40         inflate_blocks_statef *s,
41         z_streamp z,
42         int r
43 )
44 {
45   uInt j;               /* temporary storage */
46   inflate_huft *t;      /* temporary pointer */
47   uInt e;               /* extra bits or operation */
48   uLong b;              /* bit buffer */
49   uInt k;               /* bits in bit buffer */
50   Byte *p;              /* input data pointer */
51   uInt n;               /* bytes available there */
52   Byte *q;              /* output window write pointer */
53   uInt m;               /* bytes to end of window or read pointer */
54   Byte *f;              /* pointer to copy strings from */
55   inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
56
57   /* copy input/output information to locals (UPDATE macro restores) */
58   LOAD
59
60   /* process input and output based on current state */
61   while (1) switch (c->mode)
62   {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
63     case START:         /* x: set up for LEN */
64 #ifndef SLOW
65       if (m >= 258 && n >= 10)
66       {
67         UPDATE
68         r = zlib_inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
69         LOAD
70         if (r != Z_OK)
71         {
72           c->mode = r == Z_STREAM_END ? WASH : BADCODE;
73           break;
74         }
75       }
76 #endif /* !SLOW */
77       c->sub.code.need = c->lbits;
78       c->sub.code.tree = c->ltree;
79       c->mode = LEN;
80     case LEN:           /* i: get length/literal/eob next */
81       j = c->sub.code.need;
82       NEEDBITS(j)
83       t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]);
84       DUMPBITS(t->bits)
85       e = (uInt)(t->exop);
86       if (e == 0)               /* literal */
87       {
88         c->sub.lit = t->base;
89         c->mode = LIT;
90         break;
91       }
92       if (e & 16)               /* length */
93       {
94         c->sub.copy.get = e & 15;
95         c->len = t->base;
96         c->mode = LENEXT;
97         break;
98       }
99       if ((e & 64) == 0)        /* next table */
100       {
101         c->sub.code.need = e;
102         c->sub.code.tree = t + t->base;
103         break;
104       }
105       if (e & 32)               /* end of block */
106       {
107         c->mode = WASH;
108         break;
109       }
110       c->mode = BADCODE;        /* invalid code */
111       z->msg = (char*)"invalid literal/length code";
112       r = Z_DATA_ERROR;
113       LEAVE
114     case LENEXT:        /* i: getting length extra (have base) */
115       j = c->sub.copy.get;
116       NEEDBITS(j)
117       c->len += (uInt)b & zlib_inflate_mask[j];
118       DUMPBITS(j)
119       c->sub.code.need = c->dbits;
120       c->sub.code.tree = c->dtree;
121       c->mode = DIST;
122     case DIST:          /* i: get distance next */
123       j = c->sub.code.need;
124       NEEDBITS(j)
125       t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]);
126       DUMPBITS(t->bits)
127       e = (uInt)(t->exop);
128       if (e & 16)               /* distance */
129       {
130         c->sub.copy.get = e & 15;
131         c->sub.copy.dist = t->base;
132         c->mode = DISTEXT;
133         break;
134       }
135       if ((e & 64) == 0)        /* next table */
136       {
137         c->sub.code.need = e;
138         c->sub.code.tree = t + t->base;
139         break;
140       }
141       c->mode = BADCODE;        /* invalid code */
142       z->msg = (char*)"invalid distance code";
143       r = Z_DATA_ERROR;
144       LEAVE
145     case DISTEXT:       /* i: getting distance extra */
146       j = c->sub.copy.get;
147       NEEDBITS(j)
148       c->sub.copy.dist += (uInt)b & zlib_inflate_mask[j];
149       DUMPBITS(j)
150       c->mode = COPY;
151     case COPY:          /* o: copying bytes in window, waiting for space */
152       f = q - c->sub.copy.dist;
153       while (f < s->window)             /* modulo window size-"while" instead */
154         f += s->end - s->window;        /* of "if" handles invalid distances */
155       while (c->len)
156       {
157         NEEDOUT
158         OUTBYTE(*f++)
159         if (f == s->end)
160           f = s->window;
161         c->len--;
162       }
163       c->mode = START;
164       break;
165     case LIT:           /* o: got literal, waiting for output space */
166       NEEDOUT
167       OUTBYTE(c->sub.lit)
168       c->mode = START;
169       break;
170     case WASH:          /* o: got eob, possibly more output */
171       if (k > 7)        /* return unused byte, if any */
172       {
173         k -= 8;
174         n++;
175         p--;            /* can always return one */
176       }
177       FLUSH
178       if (s->read != s->write)
179         LEAVE
180       c->mode = END;
181     case END:
182       r = Z_STREAM_END;
183       LEAVE
184     case BADCODE:       /* x: got error */
185       r = Z_DATA_ERROR;
186       LEAVE
187     default:
188       r = Z_STREAM_ERROR;
189       LEAVE
190   }
191 #ifdef NEED_DUMMY_RETURN
192   return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
193 #endif
194 }
195
196
197 void zlib_inflate_codes_free(
198         inflate_codes_statef *c,
199         z_streamp z
200 )
201 {
202 }