summaryrefslogtreecommitdiff
path: root/infcodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'infcodes.c')
-rw-r--r--infcodes.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/infcodes.c b/infcodes.c
new file mode 100644
index 0000000..ffae26d
--- /dev/null
+++ b/infcodes.c
@@ -0,0 +1,217 @@
1/* infcodes.c -- process literals and length/distance pairs
2 * Copyright (C) 1995 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6#include "zutil.h"
7#include "inftrees.h"
8#include "infutil.h"
9#include "infcodes.h"
10
11/* simplify the use of the inflate_huft type with some defines */
12#define base more.Base
13#define next more.Next
14#define exop word.what.Exop
15#define bits word.what.Bits
16
17/* inflate codes private state */
18struct inflate_codes_state {
19
20 /* mode */
21 enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
22 START, /* x: set up for LEN */
23 LEN, /* i: get length/literal/eob next */
24 LENEXT, /* i: getting length extra (have base) */
25 DIST, /* i: get distance next */
26 DISTEXT, /* i: getting distance extra */
27 COPY, /* o: copying bytes in window, waiting for space */
28 LIT, /* o: got literal, waiting for output space */
29 WASH, /* o: got eob, possibly still output waiting */
30 END, /* x: got eob and all data flushed */
31 BAD} /* x: got error */
32 mode; /* current inflate_codes mode */
33
34 /* mode dependent information */
35 uInt len;
36 union {
37 struct {
38 inflate_huft *tree; /* pointer into tree */
39 uInt need; /* bits needed */
40 } code; /* if LEN or DIST, where in tree */
41 uInt lit; /* if LIT, literal */
42 struct {
43 uInt get; /* bits to get for extra */
44 uInt dist; /* distance back to copy from */
45 } copy; /* if EXT or COPY, where and how much */
46 } sub; /* submode */
47
48 /* mode independent information */
49 Byte lbits; /* ltree bits decoded per branch */
50 Byte dbits; /* dtree bits decoder per branch */
51 inflate_huft *ltree; /* literal/length/eob tree */
52 inflate_huft *dtree; /* distance tree */
53
54};
55
56
57struct inflate_codes_state *inflate_codes_new(bl, bd, tl, td, z)
58uInt bl, bd;
59inflate_huft *tl, *td;
60z_stream *z;
61{
62 struct inflate_codes_state *c;
63
64 if ((c = (struct inflate_codes_state *)
65 ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
66 {
67 c->mode = START;
68 c->lbits = (Byte)bl;
69 c->dbits = (Byte)bd;
70 c->ltree = tl;
71 c->dtree = td;
72 }
73 return c;
74}
75
76
77int inflate_codes(s, z, r)
78struct inflate_blocks_state *s;
79z_stream *z;
80int r;
81{
82 uInt j; /* temporary storage */
83 inflate_huft *t; /* temporary pointer */
84 int e; /* extra bits or operation */
85 uLong b; /* bit buffer */
86 uInt k; /* bits in bit buffer */
87 Byte *p; /* input data pointer */
88 uInt n; /* bytes available there */
89 Byte *q; /* output window write pointer */
90 uInt m; /* bytes to end of window or read pointer */
91 Byte *f; /* pointer to copy strings from */
92 struct inflate_codes_state *c = s->sub.codes; /* codes state */
93
94 /* copy input/output information to locals (UPDATE macro restores) */
95 LOAD
96
97 /* process input and output based on current state */
98 while (1) switch (c->mode)
99 { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
100 case START: /* x: set up for LEN */
101 /* %%% check for avail in and out to do fast loop %%% */
102 c->sub.code.need = c->lbits;
103 c->sub.code.tree = c->ltree;
104 c->mode = LEN;
105 case LEN: /* i: get length/literal/eob next */
106 j = c->sub.code.need;
107 NEEDBITS(j)
108 t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
109 DUMPBITS(t->bits)
110 if ((e = (int)(t->exop)) < 0)
111 {
112 if (e == -128) /* invalid code */
113 {
114 c->mode = BAD;
115 z->msg = "invalid huffman code";
116 r = Z_DATA_ERROR;
117 LEAVE
118 }
119 e = -e;
120 if (e & 64) /* end of block */
121 {
122 c->mode = END;
123 break;
124 }
125 c->sub.code.need = e;
126 c->sub.code.tree = t->next;
127 break;
128 }
129 if (e & 16) /* literal */
130 {
131 c->sub.lit = t->base;
132 c->mode = LIT;
133 break;
134 }
135 c->sub.copy.get = e;
136 c->len = t->base;
137 c->mode = LENEXT;
138 case LENEXT: /* i: getting length extra (have base) */
139 j = c->sub.copy.get;
140 NEEDBITS(j)
141 c->len += (uInt)b & inflate_mask[j];
142 DUMPBITS(j)
143 c->sub.code.need = c->dbits;
144 c->sub.code.tree = c->dtree;
145 c->mode = DIST;
146 case DIST: /* i: get distance next */
147 j = c->sub.code.need;
148 NEEDBITS(j)
149 t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
150 DUMPBITS(t->bits)
151 if ((e = (int)(t->exop)) < 0)
152 {
153 if (e == -128)
154 {
155 c->mode = BAD;
156 z->msg = "invalid huffman code";
157 r = Z_DATA_ERROR;
158 LEAVE
159 }
160 c->sub.code.need = -e;
161 c->sub.code.tree = t->next;
162 break;
163 }
164 c->sub.copy.dist = t->base;
165 c->sub.copy.get = e;
166 c->mode = DISTEXT;
167 case DISTEXT: /* i: getting distance extra */
168 j = c->sub.copy.get;
169 NEEDBITS(j)
170 c->sub.copy.dist += (uInt)b & inflate_mask[j];
171 DUMPBITS(j)
172 c->mode = COPY;
173 case COPY: /* o: copying bytes in window, waiting for space */
174 f = q - s->window < c->sub.copy.dist ?
175 s->end - (c->sub.copy.dist - (q - s->window)) :
176 q - c->sub.copy.dist;
177 while (c->len)
178 {
179 NEEDOUT
180 OUTBYTE(*f++)
181 if (f == s->end)
182 f = s->window;
183 c->len--;
184 }
185 c->mode = START;
186 break;
187 case LIT: /* o: got literal, waiting for output space */
188 NEEDOUT
189 OUTBYTE(c->sub.lit)
190 c->mode = START;
191 break;
192 case WASH: /* o: got eob, possibly more output */
193 FLUSH
194 if (s->read != s->write)
195 LEAVE
196 c->mode = END;
197 case END:
198 r = Z_STREAM_END;
199 LEAVE
200 case BAD: /* x: got error */
201 r = Z_DATA_ERROR;
202 LEAVE
203 default:
204 r = Z_STREAM_ERROR;
205 LEAVE
206 }
207}
208
209
210void inflate_codes_free(c, z)
211struct inflate_codes_state *c;
212z_stream *z;
213{
214 inflate_trees_free(c->dtree, z);
215 inflate_trees_free(c->ltree, z);
216 ZFREE(z, c);
217}