emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflate.java
branchemul
changeset 694 0d277415ed02
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflate.java	Thu Feb 07 12:58:12 2013 +0100
     1.3 @@ -0,0 +1,727 @@
     1.4 +/* -*-mode:java; c-basic-offset:2; -*- */
     1.5 +/*
     1.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
     1.7 +
     1.8 +Redistribution and use in source and binary forms, with or without
     1.9 +modification, are permitted provided that the following conditions are met:
    1.10 +
    1.11 +  1. Redistributions of source code must retain the above copyright notice,
    1.12 +     this list of conditions and the following disclaimer.
    1.13 +
    1.14 +  2. Redistributions in binary form must reproduce the above copyright 
    1.15 +     notice, this list of conditions and the following disclaimer in 
    1.16 +     the documentation and/or other materials provided with the distribution.
    1.17 +
    1.18 +  3. The names of the authors may not be used to endorse or promote products
    1.19 +     derived from this software without specific prior written permission.
    1.20 +
    1.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    1.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    1.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
    1.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
    1.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    1.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    1.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    1.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    1.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.31 + */
    1.32 +/*
    1.33 + * This program is based on zlib-1.1.3, so all credit should go authors
    1.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
    1.35 + * and contributors of zlib.
    1.36 + */
    1.37 +
    1.38 +package org.apidesign.bck2brwsr.emul.zip;
    1.39 +
    1.40 +import org.apidesign.bck2brwsr.emul.lang.System;
    1.41 +
    1.42 +final class Inflate{
    1.43 +  
    1.44 +  static final private int MAX_WBITS=15; // 32K LZ77 window
    1.45 +
    1.46 +  // preset dictionary flag in zlib header
    1.47 +  static final private int PRESET_DICT=0x20;
    1.48 +
    1.49 +  static final int Z_NO_FLUSH=0;
    1.50 +  static final int Z_PARTIAL_FLUSH=1;
    1.51 +  static final int Z_SYNC_FLUSH=2;
    1.52 +  static final int Z_FULL_FLUSH=3;
    1.53 +  static final int Z_FINISH=4;
    1.54 +
    1.55 +  static final private int Z_DEFLATED=8;
    1.56 +
    1.57 +  static final private int Z_OK=0;
    1.58 +  static final private int Z_STREAM_END=1;
    1.59 +  static final private int Z_NEED_DICT=2;
    1.60 +  static final private int Z_ERRNO=-1;
    1.61 +  static final private int Z_STREAM_ERROR=-2;
    1.62 +  static final private int Z_DATA_ERROR=-3;
    1.63 +  static final private int Z_MEM_ERROR=-4;
    1.64 +  static final private int Z_BUF_ERROR=-5;
    1.65 +  static final private int Z_VERSION_ERROR=-6;
    1.66 +
    1.67 +  static final private int METHOD=0;   // waiting for method byte
    1.68 +  static final private int FLAG=1;     // waiting for flag byte
    1.69 +  static final private int DICT4=2;    // four dictionary check bytes to go
    1.70 +  static final private int DICT3=3;    // three dictionary check bytes to go
    1.71 +  static final private int DICT2=4;    // two dictionary check bytes to go
    1.72 +  static final private int DICT1=5;    // one dictionary check byte to go
    1.73 +  static final int DICT0=6;    // waiting for inflateSetDictionary
    1.74 +  static final private int BLOCKS=7;   // decompressing blocks
    1.75 +  static final private int CHECK4=8;   // four check bytes to go
    1.76 +  static final private int CHECK3=9;   // three check bytes to go
    1.77 +  static final private int CHECK2=10;  // two check bytes to go
    1.78 +  static final private int CHECK1=11;  // one check byte to go
    1.79 +  static final private int DONE=12;    // finished check, done
    1.80 +  static final private int BAD=13;     // got an error--stay here
    1.81 +
    1.82 +  static final private int HEAD=14;
    1.83 +  static final private int LENGTH=15;
    1.84 +  static final private int TIME=16;
    1.85 +  static final private int OS=17;
    1.86 +  static final private int EXLEN=18;
    1.87 +  static final private int EXTRA=19;
    1.88 +  static final private int NAME=20;
    1.89 +  static final private int COMMENT=21;
    1.90 +  static final private int HCRC=22;
    1.91 +  static final private int FLAGS=23;
    1.92 +
    1.93 +  int mode;                            // current inflate mode
    1.94 +
    1.95 +  // mode dependent information
    1.96 +  int method;        // if FLAGS, method byte
    1.97 +
    1.98 +  // if CHECK, check values to compare
    1.99 +  long was = -1;           // computed check value
   1.100 +  long need;               // stream check value
   1.101 +
   1.102 +  // if BAD, inflateSync's marker bytes count
   1.103 +  int marker;
   1.104 +
   1.105 +  // mode independent information
   1.106 +  int  wrap;          // flag for no wrapper
   1.107 +  int wbits;            // log2(window size)  (8..15, defaults to 15)
   1.108 +
   1.109 +  InfBlocks blocks;     // current inflate_blocks state
   1.110 +
   1.111 +  private final ZStream z;
   1.112 +
   1.113 +  private int flags; 
   1.114 +
   1.115 +  private int need_bytes = -1;
   1.116 +  private byte[] crcbuf=new byte[4];
   1.117 +
   1.118 +  GZIPHeader gheader = null;
   1.119 +
   1.120 +  int inflateReset(){
   1.121 +    if(z == null) return Z_STREAM_ERROR;
   1.122 +    
   1.123 +    z.total_in = z.total_out = 0;
   1.124 +    z.msg = null;
   1.125 +    this.mode = HEAD;
   1.126 +    this.need_bytes = -1;
   1.127 +    this.blocks.reset();
   1.128 +    return Z_OK;
   1.129 +  }
   1.130 +
   1.131 +  int inflateEnd(){
   1.132 +    if(blocks != null){
   1.133 +      blocks.free();
   1.134 +    }
   1.135 +    return Z_OK;
   1.136 +  }
   1.137 +
   1.138 +  Inflate(ZStream z){
   1.139 +    this.z=z;
   1.140 +  }
   1.141 +
   1.142 +  int inflateInit(int w){
   1.143 +    z.msg = null;
   1.144 +    blocks = null;
   1.145 +
   1.146 +    // handle undocumented wrap option (no zlib header or check)
   1.147 +    wrap = 0;
   1.148 +    if(w < 0){
   1.149 +      w = - w;
   1.150 +    }
   1.151 +    else {
   1.152 +      wrap = (w >> 4) + 1;
   1.153 +      if(w < 48)
   1.154 +        w &= 15;
   1.155 +    }
   1.156 +
   1.157 +    if(w<8 ||w>15){
   1.158 +      inflateEnd();
   1.159 +      return Z_STREAM_ERROR;
   1.160 +    }
   1.161 +    if(blocks != null && wbits != w){
   1.162 +      blocks.free();
   1.163 +      blocks=null;
   1.164 +    }
   1.165 +
   1.166 +    // set window size
   1.167 +    wbits=w;
   1.168 +
   1.169 +    this.blocks=new InfBlocks(z, 1<<w);
   1.170 +
   1.171 +    // reset state
   1.172 +    inflateReset();
   1.173 +
   1.174 +    return Z_OK;
   1.175 +  }
   1.176 +
   1.177 +  int inflate(int f){
   1.178 +    int hold = 0;
   1.179 +
   1.180 +    int r;
   1.181 +    int b;
   1.182 +
   1.183 +    if(z == null || z.next_in == null){
   1.184 +      if(f == Z_FINISH && this.mode==HEAD)
   1.185 +        return Z_OK; 
   1.186 +      return Z_STREAM_ERROR;
   1.187 +    }
   1.188 +
   1.189 +    f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
   1.190 +    r = Z_BUF_ERROR;
   1.191 +    while (true){
   1.192 +
   1.193 +      switch (this.mode){
   1.194 +      case HEAD:
   1.195 +        if(wrap==0){
   1.196 +	  this.mode = BLOCKS;
   1.197 +          break;
   1.198 +        } 
   1.199 +
   1.200 +        try { r=readBytes(2, r, f); }
   1.201 +        catch(Return e){ return e.r; }
   1.202 +
   1.203 +        if((wrap&2)!=0 && this.need == 0x8b1fL) {   // gzip header
   1.204 +	  z.adler=new CRC32();
   1.205 +          checksum(2, this.need);
   1.206 +
   1.207 +          if(gheader==null) 
   1.208 +            gheader=new GZIPHeader();
   1.209 +
   1.210 +          this.mode = FLAGS;
   1.211 +          break;
   1.212 +        }
   1.213 +
   1.214 +        flags = 0;
   1.215 +
   1.216 +        this.method = ((int)this.need)&0xff;
   1.217 +        b=((int)(this.need>>8))&0xff;
   1.218 +
   1.219 +        if((wrap&1)==0 ||  // check if zlib header allowed
   1.220 +           (((this.method << 8)+b) % 31)!=0){
   1.221 +          this.mode = BAD;
   1.222 +          z.msg = "incorrect header check";
   1.223 +          // since zlib 1.2, it is allowted to inflateSync for this case.
   1.224 +          /*
   1.225 +          this.marker = 5;       // can't try inflateSync
   1.226 +          */
   1.227 +          break;
   1.228 +        }
   1.229 +
   1.230 +        if((this.method&0xf)!=Z_DEFLATED){
   1.231 +          this.mode = BAD;
   1.232 +          z.msg="unknown compression method";
   1.233 +          // since zlib 1.2, it is allowted to inflateSync for this case.
   1.234 +	  /*
   1.235 +          this.marker = 5;       // can't try inflateSync
   1.236 +	  */
   1.237 +          break;
   1.238 +        }
   1.239 +
   1.240 +        if((this.method>>4)+8>this.wbits){
   1.241 +          this.mode = BAD;
   1.242 +          z.msg="invalid window size";
   1.243 +          // since zlib 1.2, it is allowted to inflateSync for this case.
   1.244 +	  /*
   1.245 +          this.marker = 5;       // can't try inflateSync
   1.246 +	  */
   1.247 +          break;
   1.248 +        }
   1.249 +
   1.250 +        z.adler=new Adler32();
   1.251 +
   1.252 +        if((b&PRESET_DICT)==0){
   1.253 +          this.mode = BLOCKS;
   1.254 +          break;
   1.255 +        }
   1.256 +        this.mode = DICT4;
   1.257 +      case DICT4:
   1.258 +
   1.259 +        if(z.avail_in==0)return r;r=f;
   1.260 +
   1.261 +        z.avail_in--; z.total_in++;
   1.262 +        this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
   1.263 +        this.mode=DICT3;
   1.264 +      case DICT3:
   1.265 +
   1.266 +        if(z.avail_in==0)return r;r=f;
   1.267 +
   1.268 +        z.avail_in--; z.total_in++;
   1.269 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
   1.270 +        this.mode=DICT2;
   1.271 +      case DICT2:
   1.272 +
   1.273 +        if(z.avail_in==0)return r;r=f;
   1.274 +
   1.275 +        z.avail_in--; z.total_in++;
   1.276 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
   1.277 +        this.mode=DICT1;
   1.278 +      case DICT1:
   1.279 +
   1.280 +        if(z.avail_in==0)return r;r=f;
   1.281 +
   1.282 +        z.avail_in--; z.total_in++;
   1.283 +        this.need += (z.next_in[z.next_in_index++]&0xffL);
   1.284 +        z.adler.reset(this.need);
   1.285 +        this.mode = DICT0;
   1.286 +        return Z_NEED_DICT;
   1.287 +      case DICT0:
   1.288 +        this.mode = BAD;
   1.289 +        z.msg = "need dictionary";
   1.290 +        this.marker = 0;       // can try inflateSync
   1.291 +        return Z_STREAM_ERROR;
   1.292 +      case BLOCKS:
   1.293 +        r = this.blocks.proc(r);
   1.294 +        if(r == Z_DATA_ERROR){
   1.295 +          this.mode = BAD;
   1.296 +          this.marker = 0;     // can try inflateSync
   1.297 +          break;
   1.298 +        }
   1.299 +        if(r == Z_OK){
   1.300 +          r = f;
   1.301 +        }
   1.302 +        if(r != Z_STREAM_END){
   1.303 +          return r;
   1.304 +        }
   1.305 +        r = f;
   1.306 +        this.was=z.adler.getValue();
   1.307 +        this.blocks.reset();
   1.308 +        if(this.wrap==0){
   1.309 +          this.mode=DONE;
   1.310 +          break;
   1.311 +        }
   1.312 +        this.mode=CHECK4;
   1.313 +      case CHECK4:
   1.314 +
   1.315 +        if(z.avail_in==0)return r;r=f;
   1.316 +
   1.317 +        z.avail_in--; z.total_in++;
   1.318 +        this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
   1.319 +        this.mode=CHECK3;
   1.320 +      case CHECK3:
   1.321 +
   1.322 +        if(z.avail_in==0)return r;r=f;
   1.323 +
   1.324 +        z.avail_in--; z.total_in++;
   1.325 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
   1.326 +        this.mode = CHECK2;
   1.327 +      case CHECK2:
   1.328 +
   1.329 +        if(z.avail_in==0)return r;r=f;
   1.330 +
   1.331 +        z.avail_in--; z.total_in++;
   1.332 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
   1.333 +        this.mode = CHECK1;
   1.334 +      case CHECK1:
   1.335 +
   1.336 +        if(z.avail_in==0)return r;r=f;
   1.337 +
   1.338 +        z.avail_in--; z.total_in++;
   1.339 +        this.need+=(z.next_in[z.next_in_index++]&0xffL);
   1.340 +
   1.341 +        if(flags!=0){  // gzip
   1.342 +          this.need = ((this.need&0xff000000)>>24 | 
   1.343 +                          (this.need&0x00ff0000)>>8 | 
   1.344 +                          (this.need&0x0000ff00)<<8 | 
   1.345 +                          (this.need&0x0000ffff)<<24)&0xffffffffL;
   1.346 +        }
   1.347 +
   1.348 +        if(((int)(this.was)) != ((int)(this.need))){
   1.349 +          z.msg = "incorrect data check";
   1.350 +          // chack is delayed
   1.351 +          /*
   1.352 +          this.mode = BAD;
   1.353 +          this.marker = 5;       // can't try inflateSync
   1.354 +          break;
   1.355 +	  */
   1.356 +        }
   1.357 +        else if(flags!=0 && gheader!=null){
   1.358 +          gheader.crc = this.need; 
   1.359 +        }
   1.360 +
   1.361 +        this.mode = LENGTH;
   1.362 +      case LENGTH:
   1.363 +        if (wrap!=0 && flags!=0) {
   1.364 +
   1.365 +          try { r=readBytes(4, r, f); }
   1.366 +          catch(Return e){ return e.r; }
   1.367 +
   1.368 +          if(z.msg!=null && z.msg.equals("incorrect data check")){
   1.369 +            this.mode = BAD;
   1.370 +            this.marker = 5;       // can't try inflateSync
   1.371 +            break;
   1.372 +          }
   1.373 +
   1.374 +          if (this.need != (z.total_out & 0xffffffffL)) {
   1.375 +            z.msg = "incorrect length check";
   1.376 +            this.mode = BAD;
   1.377 +            break;
   1.378 +          }
   1.379 +          z.msg = null;
   1.380 +        }
   1.381 +        else {
   1.382 +          if(z.msg!=null && z.msg.equals("incorrect data check")){
   1.383 +            this.mode = BAD;
   1.384 +            this.marker = 5;       // can't try inflateSync
   1.385 +            break;
   1.386 +          }
   1.387 +        }
   1.388 +
   1.389 +        this.mode = DONE;
   1.390 +      case DONE:
   1.391 +        return Z_STREAM_END;
   1.392 +      case BAD:
   1.393 +        return Z_DATA_ERROR;
   1.394 +
   1.395 +      case FLAGS:
   1.396 +
   1.397 +        try { r=readBytes(2, r, f); }
   1.398 +        catch(Return e){ return e.r; }
   1.399 +
   1.400 +        flags = ((int)this.need)&0xffff;
   1.401 +
   1.402 +        if ((flags & 0xff) != Z_DEFLATED) {
   1.403 +          z.msg = "unknown compression method";
   1.404 +          this.mode = BAD; 
   1.405 +          break;
   1.406 +        }
   1.407 +        if ((flags & 0xe000)!=0) {
   1.408 +          z.msg = "unknown header flags set";
   1.409 +          this.mode = BAD; 
   1.410 +          break;
   1.411 +        }
   1.412 +
   1.413 +        if ((flags & 0x0200)!=0){
   1.414 +          checksum(2, this.need);
   1.415 +        } 
   1.416 +
   1.417 +        this.mode = TIME;
   1.418 +
   1.419 +      case TIME:
   1.420 +        try { r=readBytes(4, r, f); }
   1.421 +        catch(Return e){ return e.r; }
   1.422 +        if(gheader!=null)
   1.423 +          gheader.time = this.need;
   1.424 +        if ((flags & 0x0200)!=0){
   1.425 +          checksum(4, this.need);
   1.426 +        }
   1.427 +        this.mode = OS;
   1.428 +      case OS:
   1.429 +        try { r=readBytes(2, r, f); }
   1.430 +        catch(Return e){ return e.r; }
   1.431 +        if(gheader!=null){
   1.432 +          gheader.xflags = ((int)this.need)&0xff;
   1.433 +          gheader.os = (((int)this.need)>>8)&0xff;
   1.434 +        }
   1.435 +        if ((flags & 0x0200)!=0){
   1.436 +          checksum(2, this.need);
   1.437 +        }
   1.438 +        this.mode = EXLEN;
   1.439 +      case EXLEN:
   1.440 +        if ((flags & 0x0400)!=0) {
   1.441 +          try { r=readBytes(2, r, f); }
   1.442 +          catch(Return e){ return e.r; }
   1.443 +          if(gheader!=null){
   1.444 +            gheader.extra = new byte[((int)this.need)&0xffff];
   1.445 +          }
   1.446 +          if ((flags & 0x0200)!=0){
   1.447 +            checksum(2, this.need);
   1.448 +          }
   1.449 +        }
   1.450 +        else if(gheader!=null){
   1.451 +          gheader.extra=null;
   1.452 +        }
   1.453 +        this.mode = EXTRA;
   1.454 +
   1.455 +      case EXTRA:
   1.456 +        if ((flags & 0x0400)!=0) {
   1.457 +          try { 
   1.458 +            r=readBytes(r, f);
   1.459 +            if(gheader!=null){
   1.460 +              byte[] foo = tmp_array;
   1.461 +              tmp_array=null;
   1.462 +              if(foo.length == gheader.extra.length){
   1.463 +                System.arraycopy(foo, 0, gheader.extra, 0, foo.length);
   1.464 +	      }
   1.465 +              else{
   1.466 +                z.msg = "bad extra field length";
   1.467 +                this.mode = BAD; 
   1.468 +                break;
   1.469 +	      }
   1.470 +            }
   1.471 +          }
   1.472 +          catch(Return e){ return e.r; }
   1.473 +        }
   1.474 +        else if(gheader!=null){
   1.475 +          gheader.extra=null;
   1.476 +	}
   1.477 +	this.mode = NAME;
   1.478 +      case NAME:
   1.479 +	if ((flags & 0x0800)!=0) {
   1.480 +          try { 
   1.481 +            r=readString(r, f);
   1.482 +            if(gheader!=null){
   1.483 +              gheader.name=tmp_array;
   1.484 +            }
   1.485 +            tmp_array=null;
   1.486 +          }
   1.487 +          catch(Return e){ return e.r; }
   1.488 +        }
   1.489 +        else if(gheader!=null){
   1.490 +          gheader.name=null;
   1.491 +	}
   1.492 +        this.mode = COMMENT;
   1.493 +      case COMMENT:
   1.494 +        if ((flags & 0x1000)!=0) {
   1.495 +          try { 
   1.496 +            r=readString(r, f);
   1.497 +            if(gheader!=null){
   1.498 +              gheader.comment=tmp_array;
   1.499 +            }
   1.500 +            tmp_array=null;
   1.501 +          }
   1.502 +          catch(Return e){ return e.r; }
   1.503 +        }
   1.504 +        else if(gheader!=null){
   1.505 +          gheader.comment=null;
   1.506 +	}
   1.507 +        this.mode = HCRC;
   1.508 +      case HCRC:
   1.509 +	if ((flags & 0x0200)!=0) {
   1.510 +          try { r=readBytes(2, r, f); }
   1.511 +          catch(Return e){ return e.r; }
   1.512 +          if(gheader!=null){
   1.513 +            gheader.hcrc=(int)(this.need&0xffff);
   1.514 +          }
   1.515 +          if(this.need != (z.adler.getValue()&0xffffL)){
   1.516 +            this.mode = BAD;
   1.517 +            z.msg = "header crc mismatch";
   1.518 +            this.marker = 5;       // can't try inflateSync
   1.519 +            break;
   1.520 +          }
   1.521 +        }
   1.522 +        z.adler = new CRC32();
   1.523 +
   1.524 +        this.mode = BLOCKS;
   1.525 +        break;
   1.526 +      default:
   1.527 +        return Z_STREAM_ERROR;
   1.528 +      }
   1.529 +    }
   1.530 +  }
   1.531 +
   1.532 +  int inflateSetDictionary(byte[] dictionary, int dictLength){
   1.533 +    if(z==null || (this.mode != DICT0 && this.wrap != 0)){
   1.534 +      return Z_STREAM_ERROR;
   1.535 +    }
   1.536 +
   1.537 +    int index=0;
   1.538 +    int length = dictLength;
   1.539 +
   1.540 +    if(this.mode==DICT0){
   1.541 +      long adler_need=z.adler.getValue();
   1.542 +      z.adler.reset();
   1.543 +      z.adler.update(dictionary, 0, dictLength);
   1.544 +      if(z.adler.getValue()!=adler_need){
   1.545 +        return Z_DATA_ERROR;
   1.546 +      }
   1.547 +    }
   1.548 +
   1.549 +    z.adler.reset();
   1.550 +
   1.551 +    if(length >= (1<<this.wbits)){
   1.552 +      length = (1<<this.wbits)-1;
   1.553 +      index=dictLength - length;
   1.554 +    }
   1.555 +    this.blocks.set_dictionary(dictionary, index, length);
   1.556 +    this.mode = BLOCKS;
   1.557 +    return Z_OK;
   1.558 +  }
   1.559 +
   1.560 +  static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};
   1.561 +
   1.562 +  int inflateSync(){
   1.563 +    int n;       // number of bytes to look at
   1.564 +    int p;       // pointer to bytes
   1.565 +    int m;       // number of marker bytes found in a row
   1.566 +    long r, w;   // temporaries to save total_in and total_out
   1.567 +
   1.568 +    // set up
   1.569 +    if(z == null)
   1.570 +      return Z_STREAM_ERROR;
   1.571 +    if(this.mode != BAD){
   1.572 +      this.mode = BAD;
   1.573 +      this.marker = 0;
   1.574 +    }
   1.575 +    if((n=z.avail_in)==0)
   1.576 +      return Z_BUF_ERROR;
   1.577 +
   1.578 +    p=z.next_in_index;
   1.579 +    m=this.marker;
   1.580 +    // search
   1.581 +    while (n!=0 && m < 4){
   1.582 +      if(z.next_in[p] == mark[m]){
   1.583 +        m++;
   1.584 +      }
   1.585 +      else if(z.next_in[p]!=0){
   1.586 +        m = 0;
   1.587 +      }
   1.588 +      else{
   1.589 +        m = 4 - m;
   1.590 +      }
   1.591 +      p++; n--;
   1.592 +    }
   1.593 +
   1.594 +    // restore
   1.595 +    z.total_in += p-z.next_in_index;
   1.596 +    z.next_in_index = p;
   1.597 +    z.avail_in = n;
   1.598 +    this.marker = m;
   1.599 +
   1.600 +    // return no joy or set up to restart on a new block
   1.601 +    if(m != 4){
   1.602 +      return Z_DATA_ERROR;
   1.603 +    }
   1.604 +    r=z.total_in;  w=z.total_out;
   1.605 +    inflateReset();
   1.606 +    z.total_in=r;  z.total_out = w;
   1.607 +    this.mode = BLOCKS;
   1.608 +
   1.609 +    return Z_OK;
   1.610 +  }
   1.611 +
   1.612 +  // Returns true if inflate is currently at the end of a block generated
   1.613 +  // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
   1.614 +  // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
   1.615 +  // but removes the length bytes of the resulting empty stored block. When
   1.616 +  // decompressing, PPP checks that at the end of input packet, inflate is
   1.617 +  // waiting for these length bytes.
   1.618 +  int inflateSyncPoint(){
   1.619 +    if(z == null || this.blocks == null)
   1.620 +      return Z_STREAM_ERROR;
   1.621 +    return this.blocks.sync_point();
   1.622 +  }
   1.623 +
   1.624 +  private int readBytes(int n, int r, int f) throws Return{
   1.625 +    if(need_bytes == -1){
   1.626 +      need_bytes=n;
   1.627 +      this.need=0;
   1.628 +    }
   1.629 +    while(need_bytes>0){
   1.630 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
   1.631 +      z.avail_in--; z.total_in++;
   1.632 +      this.need = this.need | 
   1.633 +	((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));
   1.634 +      need_bytes--;
   1.635 +    }
   1.636 +    if(n==2){
   1.637 +      this.need&=0xffffL;
   1.638 +    }
   1.639 +    else if(n==4) {
   1.640 +      this.need&=0xffffffffL;
   1.641 +    }
   1.642 +    need_bytes=-1;
   1.643 +    return r;
   1.644 +  }
   1.645 +  class Return extends Exception{
   1.646 +    int r;
   1.647 +    Return(int r){this.r=r; }
   1.648 +  }
   1.649 +
   1.650 +  private byte[] tmp_array;
   1.651 +  private int readString(int r, int f) throws Return{
   1.652 +    int b=0; 
   1.653 +    byte[] arr = new byte[4092];
   1.654 +    int at = 0;
   1.655 +    do {
   1.656 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
   1.657 +      z.avail_in--; z.total_in++;
   1.658 +      b = z.next_in[z.next_in_index];
   1.659 +      if(b!=0) arr = append(arr, z.next_in[z.next_in_index], at++);
   1.660 +      z.adler.update(z.next_in, z.next_in_index, 1);
   1.661 +      z.next_in_index++;
   1.662 +    }while(b!=0);
   1.663 +    
   1.664 +    tmp_array = copy(arr, at);
   1.665 +    
   1.666 +    return r;
   1.667 +  }
   1.668 +
   1.669 +  private int readBytes(int r, int f) throws Return{
   1.670 +    int b=0; 
   1.671 +    byte[] arr = new byte[4092];
   1.672 +    int at = 0;
   1.673 +    while(this.need>0){
   1.674 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
   1.675 +      z.avail_in--; z.total_in++;
   1.676 +      b = z.next_in[z.next_in_index];
   1.677 +      arr = append(arr, z.next_in[z.next_in_index], at++);
   1.678 +      z.adler.update(z.next_in, z.next_in_index, 1);
   1.679 +      z.next_in_index++;
   1.680 +      this.need--;
   1.681 +    }
   1.682 +    
   1.683 +    tmp_array = copy(arr, at);
   1.684 +    
   1.685 +    return r;
   1.686 +  }
   1.687 +  
   1.688 +  private static byte[] copy(byte[] arr, int len) {
   1.689 +      byte[] ret = new byte[len];
   1.690 +      org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, 0, ret, 0, len);
   1.691 +      return ret;
   1.692 +  }
   1.693 +  private static byte[] append(byte[] arr, byte b, int index) {
   1.694 +      arr[index] = b;
   1.695 +      return arr;
   1.696 +  }
   1.697 +
   1.698 +  private void checksum(int n, long v){
   1.699 +    for(int i=0; i<n; i++){
   1.700 +      crcbuf[i]=(byte)(v&0xff);
   1.701 +      v>>=8;
   1.702 +    }
   1.703 +    z.adler.update(crcbuf, 0, n);
   1.704 +  }
   1.705 +
   1.706 +  public GZIPHeader getGZIPHeader(){
   1.707 +    return gheader;
   1.708 +  }
   1.709 +
   1.710 +  boolean inParsingHeader(){
   1.711 +    switch(mode){
   1.712 +      case HEAD:
   1.713 +      case DICT4:
   1.714 +      case DICT3:
   1.715 +      case DICT2:
   1.716 +      case DICT1:
   1.717 +      case FLAGS:
   1.718 +      case TIME:
   1.719 +      case OS:
   1.720 +      case EXLEN:
   1.721 +      case EXTRA:
   1.722 +      case NAME:
   1.723 +      case COMMENT:
   1.724 +      case HCRC:
   1.725 +	return true;
   1.726 +      default:
   1.727 +	return false;
   1.728 +    }
   1.729 +  }
   1.730 +}