jaroslav@694
|
1 |
/* -*-mode:java; c-basic-offset:2; -*- */
|
jaroslav@694
|
2 |
/*
|
jaroslav@694
|
3 |
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
|
jaroslav@694
|
4 |
|
jaroslav@694
|
5 |
Redistribution and use in source and binary forms, with or without
|
jaroslav@694
|
6 |
modification, are permitted provided that the following conditions are met:
|
jaroslav@694
|
7 |
|
jaroslav@694
|
8 |
1. Redistributions of source code must retain the above copyright notice,
|
jaroslav@694
|
9 |
this list of conditions and the following disclaimer.
|
jaroslav@694
|
10 |
|
jaroslav@694
|
11 |
2. Redistributions in binary form must reproduce the above copyright
|
jaroslav@694
|
12 |
notice, this list of conditions and the following disclaimer in
|
jaroslav@694
|
13 |
the documentation and/or other materials provided with the distribution.
|
jaroslav@694
|
14 |
|
jaroslav@694
|
15 |
3. The names of the authors may not be used to endorse or promote products
|
jaroslav@694
|
16 |
derived from this software without specific prior written permission.
|
jaroslav@694
|
17 |
|
jaroslav@694
|
18 |
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
jaroslav@694
|
19 |
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
jaroslav@694
|
20 |
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
jaroslav@694
|
21 |
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
jaroslav@694
|
22 |
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
jaroslav@694
|
23 |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
jaroslav@694
|
24 |
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
jaroslav@694
|
25 |
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
jaroslav@694
|
26 |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
jaroslav@694
|
27 |
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
jaroslav@694
|
28 |
*/
|
jaroslav@694
|
29 |
/*
|
jaroslav@694
|
30 |
* This program is based on zlib-1.1.3, so all credit should go authors
|
jaroslav@694
|
31 |
* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
|
jaroslav@694
|
32 |
* and contributors of zlib.
|
jaroslav@694
|
33 |
*/
|
jaroslav@694
|
34 |
|
jaroslav@694
|
35 |
package org.apidesign.bck2brwsr.emul.zip;
|
jaroslav@694
|
36 |
|
jaroslav@694
|
37 |
import org.apidesign.bck2brwsr.emul.lang.System;
|
jaroslav@694
|
38 |
|
jaroslav@694
|
39 |
final class InfCodes{
|
jaroslav@694
|
40 |
|
jaroslav@694
|
41 |
static final private int[] inflate_mask = {
|
jaroslav@694
|
42 |
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
|
jaroslav@694
|
43 |
0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
|
jaroslav@694
|
44 |
0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
|
jaroslav@694
|
45 |
0x00007fff, 0x0000ffff
|
jaroslav@694
|
46 |
};
|
jaroslav@694
|
47 |
|
jaroslav@694
|
48 |
static final private int Z_OK=0;
|
jaroslav@694
|
49 |
static final private int Z_STREAM_END=1;
|
jaroslav@694
|
50 |
static final private int Z_NEED_DICT=2;
|
jaroslav@694
|
51 |
static final private int Z_ERRNO=-1;
|
jaroslav@694
|
52 |
static final private int Z_STREAM_ERROR=-2;
|
jaroslav@694
|
53 |
static final private int Z_DATA_ERROR=-3;
|
jaroslav@694
|
54 |
static final private int Z_MEM_ERROR=-4;
|
jaroslav@694
|
55 |
static final private int Z_BUF_ERROR=-5;
|
jaroslav@694
|
56 |
static final private int Z_VERSION_ERROR=-6;
|
jaroslav@694
|
57 |
|
jaroslav@694
|
58 |
// waiting for "i:"=input,
|
jaroslav@694
|
59 |
// "o:"=output,
|
jaroslav@694
|
60 |
// "x:"=nothing
|
jaroslav@694
|
61 |
static final private int START=0; // x: set up for LEN
|
jaroslav@694
|
62 |
static final private int LEN=1; // i: get length/literal/eob next
|
jaroslav@694
|
63 |
static final private int LENEXT=2; // i: getting length extra (have base)
|
jaroslav@694
|
64 |
static final private int DIST=3; // i: get distance next
|
jaroslav@694
|
65 |
static final private int DISTEXT=4;// i: getting distance extra
|
jaroslav@694
|
66 |
static final private int COPY=5; // o: copying bytes in window, waiting for space
|
jaroslav@694
|
67 |
static final private int LIT=6; // o: got literal, waiting for output space
|
jaroslav@694
|
68 |
static final private int WASH=7; // o: got eob, possibly still output waiting
|
jaroslav@694
|
69 |
static final private int END=8; // x: got eob and all data flushed
|
jaroslav@694
|
70 |
static final private int BADCODE=9;// x: got error
|
jaroslav@694
|
71 |
|
jaroslav@694
|
72 |
int mode; // current inflate_codes mode
|
jaroslav@694
|
73 |
|
jaroslav@694
|
74 |
// mode dependent information
|
jaroslav@694
|
75 |
int len;
|
jaroslav@694
|
76 |
|
jaroslav@694
|
77 |
int[] tree; // pointer into tree
|
jaroslav@694
|
78 |
int tree_index=0;
|
jaroslav@694
|
79 |
int need; // bits needed
|
jaroslav@694
|
80 |
|
jaroslav@694
|
81 |
int lit;
|
jaroslav@694
|
82 |
|
jaroslav@694
|
83 |
// if EXT or COPY, where and how much
|
jaroslav@694
|
84 |
int get; // bits to get for extra
|
jaroslav@694
|
85 |
int dist; // distance back to copy from
|
jaroslav@694
|
86 |
|
jaroslav@694
|
87 |
byte lbits; // ltree bits decoded per branch
|
jaroslav@694
|
88 |
byte dbits; // dtree bits decoder per branch
|
jaroslav@694
|
89 |
int[] ltree; // literal/length/eob tree
|
jaroslav@694
|
90 |
int ltree_index; // literal/length/eob tree
|
jaroslav@694
|
91 |
int[] dtree; // distance tree
|
jaroslav@694
|
92 |
int dtree_index; // distance tree
|
jaroslav@694
|
93 |
|
jaroslav@694
|
94 |
private final ZStream z;
|
jaroslav@694
|
95 |
private final InfBlocks s;
|
jaroslav@694
|
96 |
InfCodes(ZStream z, InfBlocks s){
|
jaroslav@694
|
97 |
this.z=z;
|
jaroslav@694
|
98 |
this.s=s;
|
jaroslav@694
|
99 |
}
|
jaroslav@694
|
100 |
|
jaroslav@694
|
101 |
void init(int bl, int bd,
|
jaroslav@694
|
102 |
int[] tl, int tl_index,
|
jaroslav@694
|
103 |
int[] td, int td_index){
|
jaroslav@694
|
104 |
mode=START;
|
jaroslav@694
|
105 |
lbits=(byte)bl;
|
jaroslav@694
|
106 |
dbits=(byte)bd;
|
jaroslav@694
|
107 |
ltree=tl;
|
jaroslav@694
|
108 |
ltree_index=tl_index;
|
jaroslav@694
|
109 |
dtree = td;
|
jaroslav@694
|
110 |
dtree_index=td_index;
|
jaroslav@694
|
111 |
tree=null;
|
jaroslav@694
|
112 |
}
|
jaroslav@694
|
113 |
|
jaroslav@694
|
114 |
int proc(int r){
|
jaroslav@694
|
115 |
int j; // temporary storage
|
jaroslav@694
|
116 |
int[] t; // temporary pointer
|
jaroslav@694
|
117 |
int tindex; // temporary pointer
|
jaroslav@694
|
118 |
int e; // extra bits or operation
|
jaroslav@694
|
119 |
int b=0; // bit buffer
|
jaroslav@694
|
120 |
int k=0; // bits in bit buffer
|
jaroslav@694
|
121 |
int p=0; // input data pointer
|
jaroslav@694
|
122 |
int n; // bytes available there
|
jaroslav@694
|
123 |
int q; // output window write pointer
|
jaroslav@694
|
124 |
int m; // bytes to end of window or read pointer
|
jaroslav@694
|
125 |
int f; // pointer to copy strings from
|
jaroslav@694
|
126 |
|
jaroslav@694
|
127 |
// copy input/output information to locals (UPDATE macro restores)
|
jaroslav@694
|
128 |
p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
|
jaroslav@694
|
129 |
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
jaroslav@694
|
130 |
|
jaroslav@694
|
131 |
// process input and output based on current state
|
jaroslav@694
|
132 |
while (true){
|
jaroslav@694
|
133 |
switch (mode){
|
jaroslav@694
|
134 |
// waiting for "i:"=input, "o:"=output, "x:"=nothing
|
jaroslav@694
|
135 |
case START: // x: set up for LEN
|
jaroslav@694
|
136 |
if (m >= 258 && n >= 10){
|
jaroslav@694
|
137 |
|
jaroslav@694
|
138 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
139 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
140 |
s.write=q;
|
jaroslav@694
|
141 |
r = inflate_fast(lbits, dbits,
|
jaroslav@694
|
142 |
ltree, ltree_index,
|
jaroslav@694
|
143 |
dtree, dtree_index,
|
jaroslav@694
|
144 |
s, z);
|
jaroslav@694
|
145 |
|
jaroslav@694
|
146 |
p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
|
jaroslav@694
|
147 |
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
jaroslav@694
|
148 |
|
jaroslav@694
|
149 |
if (r != Z_OK){
|
jaroslav@694
|
150 |
mode = r == Z_STREAM_END ? WASH : BADCODE;
|
jaroslav@694
|
151 |
break;
|
jaroslav@694
|
152 |
}
|
jaroslav@694
|
153 |
}
|
jaroslav@694
|
154 |
need = lbits;
|
jaroslav@694
|
155 |
tree = ltree;
|
jaroslav@694
|
156 |
tree_index=ltree_index;
|
jaroslav@694
|
157 |
|
jaroslav@694
|
158 |
mode = LEN;
|
jaroslav@694
|
159 |
case LEN: // i: get length/literal/eob next
|
jaroslav@694
|
160 |
j = need;
|
jaroslav@694
|
161 |
|
jaroslav@694
|
162 |
while(k<(j)){
|
jaroslav@694
|
163 |
if(n!=0)r=Z_OK;
|
jaroslav@694
|
164 |
else{
|
jaroslav@694
|
165 |
|
jaroslav@694
|
166 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
167 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
168 |
s.write=q;
|
jaroslav@694
|
169 |
return s.inflate_flush(r);
|
jaroslav@694
|
170 |
}
|
jaroslav@694
|
171 |
n--;
|
jaroslav@694
|
172 |
b|=(z.next_in[p++]&0xff)<<k;
|
jaroslav@694
|
173 |
k+=8;
|
jaroslav@694
|
174 |
}
|
jaroslav@694
|
175 |
|
jaroslav@694
|
176 |
tindex=(tree_index+(b&inflate_mask[j]))*3;
|
jaroslav@694
|
177 |
|
jaroslav@694
|
178 |
b>>>=(tree[tindex+1]);
|
jaroslav@694
|
179 |
k-=(tree[tindex+1]);
|
jaroslav@694
|
180 |
|
jaroslav@694
|
181 |
e=tree[tindex];
|
jaroslav@694
|
182 |
|
jaroslav@694
|
183 |
if(e == 0){ // literal
|
jaroslav@694
|
184 |
lit = tree[tindex+2];
|
jaroslav@694
|
185 |
mode = LIT;
|
jaroslav@694
|
186 |
break;
|
jaroslav@694
|
187 |
}
|
jaroslav@694
|
188 |
if((e & 16)!=0 ){ // length
|
jaroslav@694
|
189 |
get = e & 15;
|
jaroslav@694
|
190 |
len = tree[tindex+2];
|
jaroslav@694
|
191 |
mode = LENEXT;
|
jaroslav@694
|
192 |
break;
|
jaroslav@694
|
193 |
}
|
jaroslav@694
|
194 |
if ((e & 64) == 0){ // next table
|
jaroslav@694
|
195 |
need = e;
|
jaroslav@694
|
196 |
tree_index = tindex/3+tree[tindex+2];
|
jaroslav@694
|
197 |
break;
|
jaroslav@694
|
198 |
}
|
jaroslav@694
|
199 |
if ((e & 32)!=0){ // end of block
|
jaroslav@694
|
200 |
mode = WASH;
|
jaroslav@694
|
201 |
break;
|
jaroslav@694
|
202 |
}
|
jaroslav@694
|
203 |
mode = BADCODE; // invalid code
|
jaroslav@694
|
204 |
z.msg = "invalid literal/length code";
|
jaroslav@694
|
205 |
r = Z_DATA_ERROR;
|
jaroslav@694
|
206 |
|
jaroslav@694
|
207 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
208 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
209 |
s.write=q;
|
jaroslav@694
|
210 |
return s.inflate_flush(r);
|
jaroslav@694
|
211 |
|
jaroslav@694
|
212 |
case LENEXT: // i: getting length extra (have base)
|
jaroslav@694
|
213 |
j = get;
|
jaroslav@694
|
214 |
|
jaroslav@694
|
215 |
while(k<(j)){
|
jaroslav@694
|
216 |
if(n!=0)r=Z_OK;
|
jaroslav@694
|
217 |
else{
|
jaroslav@694
|
218 |
|
jaroslav@694
|
219 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
220 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
221 |
s.write=q;
|
jaroslav@694
|
222 |
return s.inflate_flush(r);
|
jaroslav@694
|
223 |
}
|
jaroslav@694
|
224 |
n--; b|=(z.next_in[p++]&0xff)<<k;
|
jaroslav@694
|
225 |
k+=8;
|
jaroslav@694
|
226 |
}
|
jaroslav@694
|
227 |
|
jaroslav@694
|
228 |
len += (b & inflate_mask[j]);
|
jaroslav@694
|
229 |
|
jaroslav@694
|
230 |
b>>=j;
|
jaroslav@694
|
231 |
k-=j;
|
jaroslav@694
|
232 |
|
jaroslav@694
|
233 |
need = dbits;
|
jaroslav@694
|
234 |
tree = dtree;
|
jaroslav@694
|
235 |
tree_index=dtree_index;
|
jaroslav@694
|
236 |
mode = DIST;
|
jaroslav@694
|
237 |
case DIST: // i: get distance next
|
jaroslav@694
|
238 |
j = need;
|
jaroslav@694
|
239 |
|
jaroslav@694
|
240 |
while(k<(j)){
|
jaroslav@694
|
241 |
if(n!=0)r=Z_OK;
|
jaroslav@694
|
242 |
else{
|
jaroslav@694
|
243 |
|
jaroslav@694
|
244 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
245 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
246 |
s.write=q;
|
jaroslav@694
|
247 |
return s.inflate_flush(r);
|
jaroslav@694
|
248 |
}
|
jaroslav@694
|
249 |
n--; b|=(z.next_in[p++]&0xff)<<k;
|
jaroslav@694
|
250 |
k+=8;
|
jaroslav@694
|
251 |
}
|
jaroslav@694
|
252 |
|
jaroslav@694
|
253 |
tindex=(tree_index+(b & inflate_mask[j]))*3;
|
jaroslav@694
|
254 |
|
jaroslav@694
|
255 |
b>>=tree[tindex+1];
|
jaroslav@694
|
256 |
k-=tree[tindex+1];
|
jaroslav@694
|
257 |
|
jaroslav@694
|
258 |
e = (tree[tindex]);
|
jaroslav@694
|
259 |
if((e & 16)!=0){ // distance
|
jaroslav@694
|
260 |
get = e & 15;
|
jaroslav@694
|
261 |
dist = tree[tindex+2];
|
jaroslav@694
|
262 |
mode = DISTEXT;
|
jaroslav@694
|
263 |
break;
|
jaroslav@694
|
264 |
}
|
jaroslav@694
|
265 |
if ((e & 64) == 0){ // next table
|
jaroslav@694
|
266 |
need = e;
|
jaroslav@694
|
267 |
tree_index = tindex/3 + tree[tindex+2];
|
jaroslav@694
|
268 |
break;
|
jaroslav@694
|
269 |
}
|
jaroslav@694
|
270 |
mode = BADCODE; // invalid code
|
jaroslav@694
|
271 |
z.msg = "invalid distance code";
|
jaroslav@694
|
272 |
r = Z_DATA_ERROR;
|
jaroslav@694
|
273 |
|
jaroslav@694
|
274 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
275 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
276 |
s.write=q;
|
jaroslav@694
|
277 |
return s.inflate_flush(r);
|
jaroslav@694
|
278 |
|
jaroslav@694
|
279 |
case DISTEXT: // i: getting distance extra
|
jaroslav@694
|
280 |
j = get;
|
jaroslav@694
|
281 |
|
jaroslav@694
|
282 |
while(k<(j)){
|
jaroslav@694
|
283 |
if(n!=0)r=Z_OK;
|
jaroslav@694
|
284 |
else{
|
jaroslav@694
|
285 |
|
jaroslav@694
|
286 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
287 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
288 |
s.write=q;
|
jaroslav@694
|
289 |
return s.inflate_flush(r);
|
jaroslav@694
|
290 |
}
|
jaroslav@694
|
291 |
n--; b|=(z.next_in[p++]&0xff)<<k;
|
jaroslav@694
|
292 |
k+=8;
|
jaroslav@694
|
293 |
}
|
jaroslav@694
|
294 |
|
jaroslav@694
|
295 |
dist += (b & inflate_mask[j]);
|
jaroslav@694
|
296 |
|
jaroslav@694
|
297 |
b>>=j;
|
jaroslav@694
|
298 |
k-=j;
|
jaroslav@694
|
299 |
|
jaroslav@694
|
300 |
mode = COPY;
|
jaroslav@694
|
301 |
case COPY: // o: copying bytes in window, waiting for space
|
jaroslav@694
|
302 |
f = q - dist;
|
jaroslav@694
|
303 |
while(f < 0){ // modulo window size-"while" instead
|
jaroslav@694
|
304 |
f += s.end; // of "if" handles invalid distances
|
jaroslav@694
|
305 |
}
|
jaroslav@694
|
306 |
while (len!=0){
|
jaroslav@694
|
307 |
|
jaroslav@694
|
308 |
if(m==0){
|
jaroslav@694
|
309 |
if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
|
jaroslav@694
|
310 |
if(m==0){
|
jaroslav@694
|
311 |
s.write=q; r=s.inflate_flush(r);
|
jaroslav@694
|
312 |
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
jaroslav@694
|
313 |
|
jaroslav@694
|
314 |
if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
|
jaroslav@694
|
315 |
|
jaroslav@694
|
316 |
if(m==0){
|
jaroslav@694
|
317 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
318 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
319 |
s.write=q;
|
jaroslav@694
|
320 |
return s.inflate_flush(r);
|
jaroslav@694
|
321 |
}
|
jaroslav@694
|
322 |
}
|
jaroslav@694
|
323 |
}
|
jaroslav@694
|
324 |
|
jaroslav@694
|
325 |
s.window[q++]=s.window[f++]; m--;
|
jaroslav@694
|
326 |
|
jaroslav@694
|
327 |
if (f == s.end)
|
jaroslav@694
|
328 |
f = 0;
|
jaroslav@694
|
329 |
len--;
|
jaroslav@694
|
330 |
}
|
jaroslav@694
|
331 |
mode = START;
|
jaroslav@694
|
332 |
break;
|
jaroslav@694
|
333 |
case LIT: // o: got literal, waiting for output space
|
jaroslav@694
|
334 |
if(m==0){
|
jaroslav@694
|
335 |
if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
|
jaroslav@694
|
336 |
if(m==0){
|
jaroslav@694
|
337 |
s.write=q; r=s.inflate_flush(r);
|
jaroslav@694
|
338 |
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
jaroslav@694
|
339 |
|
jaroslav@694
|
340 |
if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
|
jaroslav@694
|
341 |
if(m==0){
|
jaroslav@694
|
342 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
343 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
344 |
s.write=q;
|
jaroslav@694
|
345 |
return s.inflate_flush(r);
|
jaroslav@694
|
346 |
}
|
jaroslav@694
|
347 |
}
|
jaroslav@694
|
348 |
}
|
jaroslav@694
|
349 |
r=Z_OK;
|
jaroslav@694
|
350 |
|
jaroslav@694
|
351 |
s.window[q++]=(byte)lit; m--;
|
jaroslav@694
|
352 |
|
jaroslav@694
|
353 |
mode = START;
|
jaroslav@694
|
354 |
break;
|
jaroslav@694
|
355 |
case WASH: // o: got eob, possibly more output
|
jaroslav@694
|
356 |
if (k > 7){ // return unused byte, if any
|
jaroslav@694
|
357 |
k -= 8;
|
jaroslav@694
|
358 |
n++;
|
jaroslav@694
|
359 |
p--; // can always return one
|
jaroslav@694
|
360 |
}
|
jaroslav@694
|
361 |
|
jaroslav@694
|
362 |
s.write=q; r=s.inflate_flush(r);
|
jaroslav@694
|
363 |
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
jaroslav@694
|
364 |
|
jaroslav@694
|
365 |
if (s.read != s.write){
|
jaroslav@694
|
366 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
367 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
368 |
s.write=q;
|
jaroslav@694
|
369 |
return s.inflate_flush(r);
|
jaroslav@694
|
370 |
}
|
jaroslav@694
|
371 |
mode = END;
|
jaroslav@694
|
372 |
case END:
|
jaroslav@694
|
373 |
r = Z_STREAM_END;
|
jaroslav@694
|
374 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
375 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
376 |
s.write=q;
|
jaroslav@694
|
377 |
return s.inflate_flush(r);
|
jaroslav@694
|
378 |
|
jaroslav@694
|
379 |
case BADCODE: // x: got error
|
jaroslav@694
|
380 |
|
jaroslav@694
|
381 |
r = Z_DATA_ERROR;
|
jaroslav@694
|
382 |
|
jaroslav@694
|
383 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
384 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
385 |
s.write=q;
|
jaroslav@694
|
386 |
return s.inflate_flush(r);
|
jaroslav@694
|
387 |
|
jaroslav@694
|
388 |
default:
|
jaroslav@694
|
389 |
r = Z_STREAM_ERROR;
|
jaroslav@694
|
390 |
|
jaroslav@694
|
391 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
392 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
393 |
s.write=q;
|
jaroslav@694
|
394 |
return s.inflate_flush(r);
|
jaroslav@694
|
395 |
}
|
jaroslav@694
|
396 |
}
|
jaroslav@694
|
397 |
}
|
jaroslav@694
|
398 |
|
jaroslav@694
|
399 |
void free(ZStream z){
|
jaroslav@694
|
400 |
// ZFREE(z, c);
|
jaroslav@694
|
401 |
}
|
jaroslav@694
|
402 |
|
jaroslav@694
|
403 |
// Called with number of bytes left to write in window at least 258
|
jaroslav@694
|
404 |
// (the maximum string length) and number of input bytes available
|
jaroslav@694
|
405 |
// at least ten. The ten bytes are six bytes for the longest length/
|
jaroslav@694
|
406 |
// distance pair plus four bytes for overloading the bit buffer.
|
jaroslav@694
|
407 |
|
jaroslav@694
|
408 |
int inflate_fast(int bl, int bd,
|
jaroslav@694
|
409 |
int[] tl, int tl_index,
|
jaroslav@694
|
410 |
int[] td, int td_index,
|
jaroslav@694
|
411 |
InfBlocks s, ZStream z){
|
jaroslav@694
|
412 |
int t; // temporary pointer
|
jaroslav@694
|
413 |
int[] tp; // temporary pointer
|
jaroslav@694
|
414 |
int tp_index; // temporary pointer
|
jaroslav@694
|
415 |
int e; // extra bits or operation
|
jaroslav@694
|
416 |
int b; // bit buffer
|
jaroslav@694
|
417 |
int k; // bits in bit buffer
|
jaroslav@694
|
418 |
int p; // input data pointer
|
jaroslav@694
|
419 |
int n; // bytes available there
|
jaroslav@694
|
420 |
int q; // output window write pointer
|
jaroslav@694
|
421 |
int m; // bytes to end of window or read pointer
|
jaroslav@694
|
422 |
int ml; // mask for literal/length tree
|
jaroslav@694
|
423 |
int md; // mask for distance tree
|
jaroslav@694
|
424 |
int c; // bytes to copy
|
jaroslav@694
|
425 |
int d; // distance back to copy from
|
jaroslav@694
|
426 |
int r; // copy source pointer
|
jaroslav@694
|
427 |
|
jaroslav@694
|
428 |
int tp_index_t_3; // (tp_index+t)*3
|
jaroslav@694
|
429 |
|
jaroslav@694
|
430 |
// load input, output, bit values
|
jaroslav@694
|
431 |
p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
|
jaroslav@694
|
432 |
q=s.write;m=q<s.read?s.read-q-1:s.end-q;
|
jaroslav@694
|
433 |
|
jaroslav@694
|
434 |
// initialize masks
|
jaroslav@694
|
435 |
ml = inflate_mask[bl];
|
jaroslav@694
|
436 |
md = inflate_mask[bd];
|
jaroslav@694
|
437 |
|
jaroslav@694
|
438 |
// do until not enough input or output space for fast loop
|
jaroslav@694
|
439 |
do { // assume called with m >= 258 && n >= 10
|
jaroslav@694
|
440 |
// get literal/length code
|
jaroslav@694
|
441 |
while(k<(20)){ // max bits for literal/length code
|
jaroslav@694
|
442 |
n--;
|
jaroslav@694
|
443 |
b|=(z.next_in[p++]&0xff)<<k;k+=8;
|
jaroslav@694
|
444 |
}
|
jaroslav@694
|
445 |
|
jaroslav@694
|
446 |
t= b&ml;
|
jaroslav@694
|
447 |
tp=tl;
|
jaroslav@694
|
448 |
tp_index=tl_index;
|
jaroslav@694
|
449 |
tp_index_t_3=(tp_index+t)*3;
|
jaroslav@694
|
450 |
if ((e = tp[tp_index_t_3]) == 0){
|
jaroslav@694
|
451 |
b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
|
jaroslav@694
|
452 |
|
jaroslav@694
|
453 |
s.window[q++] = (byte)tp[tp_index_t_3+2];
|
jaroslav@694
|
454 |
m--;
|
jaroslav@694
|
455 |
continue;
|
jaroslav@694
|
456 |
}
|
jaroslav@694
|
457 |
do {
|
jaroslav@694
|
458 |
|
jaroslav@694
|
459 |
b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
|
jaroslav@694
|
460 |
|
jaroslav@694
|
461 |
if((e&16)!=0){
|
jaroslav@694
|
462 |
e &= 15;
|
jaroslav@694
|
463 |
c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
|
jaroslav@694
|
464 |
|
jaroslav@694
|
465 |
b>>=e; k-=e;
|
jaroslav@694
|
466 |
|
jaroslav@694
|
467 |
// decode distance base of block to copy
|
jaroslav@694
|
468 |
while(k<(15)){ // max bits for distance code
|
jaroslav@694
|
469 |
n--;
|
jaroslav@694
|
470 |
b|=(z.next_in[p++]&0xff)<<k;k+=8;
|
jaroslav@694
|
471 |
}
|
jaroslav@694
|
472 |
|
jaroslav@694
|
473 |
t= b&md;
|
jaroslav@694
|
474 |
tp=td;
|
jaroslav@694
|
475 |
tp_index=td_index;
|
jaroslav@694
|
476 |
tp_index_t_3=(tp_index+t)*3;
|
jaroslav@694
|
477 |
e = tp[tp_index_t_3];
|
jaroslav@694
|
478 |
|
jaroslav@694
|
479 |
do {
|
jaroslav@694
|
480 |
|
jaroslav@694
|
481 |
b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
|
jaroslav@694
|
482 |
|
jaroslav@694
|
483 |
if((e&16)!=0){
|
jaroslav@694
|
484 |
// get extra bits to add to distance base
|
jaroslav@694
|
485 |
e &= 15;
|
jaroslav@694
|
486 |
while(k<(e)){ // get extra bits (up to 13)
|
jaroslav@694
|
487 |
n--;
|
jaroslav@694
|
488 |
b|=(z.next_in[p++]&0xff)<<k;k+=8;
|
jaroslav@694
|
489 |
}
|
jaroslav@694
|
490 |
|
jaroslav@694
|
491 |
d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
|
jaroslav@694
|
492 |
|
jaroslav@694
|
493 |
b>>=(e); k-=(e);
|
jaroslav@694
|
494 |
|
jaroslav@694
|
495 |
// do the copy
|
jaroslav@694
|
496 |
m -= c;
|
jaroslav@694
|
497 |
if (q >= d){ // offset before dest
|
jaroslav@694
|
498 |
// just copy
|
jaroslav@694
|
499 |
r=q-d;
|
jaroslav@694
|
500 |
if(q-r>0 && 2>(q-r)){
|
jaroslav@694
|
501 |
s.window[q++]=s.window[r++]; // minimum count is three,
|
jaroslav@694
|
502 |
s.window[q++]=s.window[r++]; // so unroll loop a little
|
jaroslav@694
|
503 |
c-=2;
|
jaroslav@694
|
504 |
}
|
jaroslav@694
|
505 |
else{
|
jaroslav@694
|
506 |
System.arraycopy(s.window, r, s.window, q, 2);
|
jaroslav@694
|
507 |
q+=2; r+=2; c-=2;
|
jaroslav@694
|
508 |
}
|
jaroslav@694
|
509 |
}
|
jaroslav@694
|
510 |
else{ // else offset after destination
|
jaroslav@694
|
511 |
r=q-d;
|
jaroslav@694
|
512 |
do{
|
jaroslav@694
|
513 |
r+=s.end; // force pointer in window
|
jaroslav@694
|
514 |
}while(r<0); // covers invalid distances
|
jaroslav@694
|
515 |
e=s.end-r;
|
jaroslav@694
|
516 |
if(c>e){ // if source crosses,
|
jaroslav@694
|
517 |
c-=e; // wrapped copy
|
jaroslav@694
|
518 |
if(q-r>0 && e>(q-r)){
|
jaroslav@694
|
519 |
do{s.window[q++] = s.window[r++];}
|
jaroslav@694
|
520 |
while(--e!=0);
|
jaroslav@694
|
521 |
}
|
jaroslav@694
|
522 |
else{
|
jaroslav@694
|
523 |
System.arraycopy(s.window, r, s.window, q, e);
|
jaroslav@694
|
524 |
q+=e; r+=e; e=0;
|
jaroslav@694
|
525 |
}
|
jaroslav@694
|
526 |
r = 0; // copy rest from start of window
|
jaroslav@694
|
527 |
}
|
jaroslav@694
|
528 |
|
jaroslav@694
|
529 |
}
|
jaroslav@694
|
530 |
|
jaroslav@694
|
531 |
// copy all or what's left
|
jaroslav@694
|
532 |
if(q-r>0 && c>(q-r)){
|
jaroslav@694
|
533 |
do{s.window[q++] = s.window[r++];}
|
jaroslav@694
|
534 |
while(--c!=0);
|
jaroslav@694
|
535 |
}
|
jaroslav@694
|
536 |
else{
|
jaroslav@694
|
537 |
System.arraycopy(s.window, r, s.window, q, c);
|
jaroslav@694
|
538 |
q+=c; r+=c; c=0;
|
jaroslav@694
|
539 |
}
|
jaroslav@694
|
540 |
break;
|
jaroslav@694
|
541 |
}
|
jaroslav@694
|
542 |
else if((e&64)==0){
|
jaroslav@694
|
543 |
t+=tp[tp_index_t_3+2];
|
jaroslav@694
|
544 |
t+=(b&inflate_mask[e]);
|
jaroslav@694
|
545 |
tp_index_t_3=(tp_index+t)*3;
|
jaroslav@694
|
546 |
e=tp[tp_index_t_3];
|
jaroslav@694
|
547 |
}
|
jaroslav@694
|
548 |
else{
|
jaroslav@694
|
549 |
z.msg = "invalid distance code";
|
jaroslav@694
|
550 |
|
jaroslav@694
|
551 |
c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
|
jaroslav@694
|
552 |
|
jaroslav@694
|
553 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
554 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
555 |
s.write=q;
|
jaroslav@694
|
556 |
|
jaroslav@694
|
557 |
return Z_DATA_ERROR;
|
jaroslav@694
|
558 |
}
|
jaroslav@694
|
559 |
}
|
jaroslav@694
|
560 |
while(true);
|
jaroslav@694
|
561 |
break;
|
jaroslav@694
|
562 |
}
|
jaroslav@694
|
563 |
|
jaroslav@694
|
564 |
if((e&64)==0){
|
jaroslav@694
|
565 |
t+=tp[tp_index_t_3+2];
|
jaroslav@694
|
566 |
t+=(b&inflate_mask[e]);
|
jaroslav@694
|
567 |
tp_index_t_3=(tp_index+t)*3;
|
jaroslav@694
|
568 |
if((e=tp[tp_index_t_3])==0){
|
jaroslav@694
|
569 |
|
jaroslav@694
|
570 |
b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
|
jaroslav@694
|
571 |
|
jaroslav@694
|
572 |
s.window[q++]=(byte)tp[tp_index_t_3+2];
|
jaroslav@694
|
573 |
m--;
|
jaroslav@694
|
574 |
break;
|
jaroslav@694
|
575 |
}
|
jaroslav@694
|
576 |
}
|
jaroslav@694
|
577 |
else if((e&32)!=0){
|
jaroslav@694
|
578 |
|
jaroslav@694
|
579 |
c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
|
jaroslav@694
|
580 |
|
jaroslav@694
|
581 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
582 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
583 |
s.write=q;
|
jaroslav@694
|
584 |
|
jaroslav@694
|
585 |
return Z_STREAM_END;
|
jaroslav@694
|
586 |
}
|
jaroslav@694
|
587 |
else{
|
jaroslav@694
|
588 |
z.msg="invalid literal/length code";
|
jaroslav@694
|
589 |
|
jaroslav@694
|
590 |
c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
|
jaroslav@694
|
591 |
|
jaroslav@694
|
592 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
593 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
594 |
s.write=q;
|
jaroslav@694
|
595 |
|
jaroslav@694
|
596 |
return Z_DATA_ERROR;
|
jaroslav@694
|
597 |
}
|
jaroslav@694
|
598 |
}
|
jaroslav@694
|
599 |
while(true);
|
jaroslav@694
|
600 |
}
|
jaroslav@694
|
601 |
while(m>=258 && n>= 10);
|
jaroslav@694
|
602 |
|
jaroslav@694
|
603 |
// not enough input or output--restore pointers and return
|
jaroslav@694
|
604 |
c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
|
jaroslav@694
|
605 |
|
jaroslav@694
|
606 |
s.bitb=b;s.bitk=k;
|
jaroslav@694
|
607 |
z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
|
jaroslav@694
|
608 |
s.write=q;
|
jaroslav@694
|
609 |
|
jaroslav@694
|
610 |
return Z_OK;
|
jaroslav@694
|
611 |
}
|
jaroslav@694
|
612 |
}
|