emul/mini/src/main/java/java/util/zip/Inflater.java
brancharithmetic
changeset 755 5652acd48509
parent 687 a9e506a27b55
     1.1 --- a/emul/mini/src/main/java/java/util/zip/Inflater.java	Wed Feb 06 15:47:06 2013 +0100
     1.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java	Mon Feb 25 19:00:08 2013 +0100
     1.3 @@ -1,44 +1,30 @@
     1.4 -/* Inflater.java - Decompress a data stream
     1.5 -   Copyright (C) 1999, 2000, 2001, 2003  Free Software Foundation, Inc.
     1.6 -
     1.7 -This file is part of GNU Classpath.
     1.8 -
     1.9 -GNU Classpath is free software; you can redistribute it and/or modify
    1.10 -it under the terms of the GNU General Public License as published by
    1.11 -the Free Software Foundation; either version 2, or (at your option)
    1.12 -any later version.
    1.13 - 
    1.14 -GNU Classpath is distributed in the hope that it will be useful, but
    1.15 -WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.17 -General Public License for more details.
    1.18 -
    1.19 -You should have received a copy of the GNU General Public License
    1.20 -along with GNU Classpath; see the file COPYING.  If not, write to the
    1.21 -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    1.22 -02111-1307 USA.
    1.23 -
    1.24 -Linking this library statically or dynamically with other modules is
    1.25 -making a combined work based on this library.  Thus, the terms and
    1.26 -conditions of the GNU General Public License cover the whole
    1.27 -combination.
    1.28 -
    1.29 -As a special exception, the copyright holders of this library give you
    1.30 -permission to link this library with independent modules to produce an
    1.31 -executable, regardless of the license terms of these independent
    1.32 -modules, and to copy and distribute the resulting executable under
    1.33 -terms of your choice, provided that you also meet, for each linked
    1.34 -independent module, the terms and conditions of the license of that
    1.35 -module.  An independent module is a module which is not derived from
    1.36 -or based on this library.  If you modify this library, you may extend
    1.37 -this exception to your version of the library, but you are not
    1.38 -obligated to do so.  If you do not wish to do so, delete this
    1.39 -exception statement from your version. */
    1.40 +/*
    1.41 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
    1.42 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    1.43 + *
    1.44 + * This code is free software; you can redistribute it and/or modify it
    1.45 + * under the terms of the GNU General Public License version 2 only, as
    1.46 + * published by the Free Software Foundation.  Oracle designates this
    1.47 + * particular file as subject to the "Classpath" exception as provided
    1.48 + * by Oracle in the LICENSE file that accompanied this code.
    1.49 + *
    1.50 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.51 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.52 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.53 + * version 2 for more details (a copy is included in the LICENSE file that
    1.54 + * accompanied this code).
    1.55 + *
    1.56 + * You should have received a copy of the GNU General Public License version
    1.57 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.58 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.59 + *
    1.60 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.61 + * or visit www.oracle.com if you need additional information or have any
    1.62 + * questions.
    1.63 + */
    1.64  
    1.65  package java.util.zip;
    1.66  
    1.67 -import org.apidesign.bck2brwsr.emul.lang.System;
    1.68 -
    1.69  /**
    1.70   * This class provides support for general purpose decompression using the
    1.71   * popular ZLIB compression library. The ZLIB compression library was
    1.72 @@ -84,1399 +70,241 @@
    1.73   * @author      David Connelly
    1.74   *
    1.75   */
    1.76 -
    1.77 -/* Written using on-line Java Platform 1.2 API Specification
    1.78 - * and JCL book.
    1.79 - * Believed complete and correct.
    1.80 - */
    1.81 -
    1.82 -/**
    1.83 - * Inflater is used to decompress data that has been compressed according 
    1.84 - * to the "deflate" standard described in rfc1950.
    1.85 - *
    1.86 - * The usage is as following.  First you have to set some input with
    1.87 - * <code>setInput()</code>, then inflate() it.  If inflate doesn't
    1.88 - * inflate any bytes there may be three reasons:
    1.89 - * <ul>
    1.90 - * <li>needsInput() returns true because the input buffer is empty.
    1.91 - * You have to provide more input with <code>setInput()</code>.  
    1.92 - * NOTE: needsInput() also returns true when, the stream is finished.
    1.93 - * </li>
    1.94 - * <li>needsDictionary() returns true, you have to provide a preset 
    1.95 - *     dictionary with <code>setDictionary()</code>.</li>
    1.96 - * <li>finished() returns true, the inflater has finished.</li>
    1.97 - * </ul>
    1.98 - * Once the first output byte is produced, a dictionary will not be
    1.99 - * needed at a later stage.
   1.100 - *
   1.101 - * @author John Leuner, Jochen Hoenicke
   1.102 - * @author Tom Tromey
   1.103 - * @date May 17, 1999
   1.104 - * @since JDK 1.1
   1.105 - */
   1.106 -public class Inflater
   1.107 -{
   1.108 -  /* Copy lengths for literal codes 257..285 */
   1.109 -  private static final int CPLENS[] = 
   1.110 -  { 
   1.111 -    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
   1.112 -    35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
   1.113 -  };
   1.114 -  
   1.115 -  /* Extra bits for literal codes 257..285 */  
   1.116 -  private static final int CPLEXT[] = 
   1.117 -  { 
   1.118 -    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
   1.119 -    3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
   1.120 -  };
   1.121 -
   1.122 -  /* Copy offsets for distance codes 0..29 */
   1.123 -  private static final int CPDIST[] = {
   1.124 -    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
   1.125 -    257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
   1.126 -    8193, 12289, 16385, 24577
   1.127 -  };
   1.128 -  
   1.129 -  /* Extra bits for distance codes */
   1.130 -  private static final int CPDEXT[] = {
   1.131 -    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
   1.132 -    7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 
   1.133 -    12, 12, 13, 13
   1.134 -  };
   1.135 -
   1.136 -  /* This are the state in which the inflater can be.  */
   1.137 -  private static final int DECODE_HEADER           = 0;
   1.138 -  private static final int DECODE_DICT             = 1;
   1.139 -  private static final int DECODE_BLOCKS           = 2;
   1.140 -  private static final int DECODE_STORED_LEN1      = 3;
   1.141 -  private static final int DECODE_STORED_LEN2      = 4;
   1.142 -  private static final int DECODE_STORED           = 5;
   1.143 -  private static final int DECODE_DYN_HEADER       = 6;
   1.144 -  private static final int DECODE_HUFFMAN          = 7;
   1.145 -  private static final int DECODE_HUFFMAN_LENBITS  = 8;
   1.146 -  private static final int DECODE_HUFFMAN_DIST     = 9;
   1.147 -  private static final int DECODE_HUFFMAN_DISTBITS = 10;
   1.148 -  private static final int DECODE_CHKSUM           = 11;
   1.149 -  private static final int FINISHED                = 12;
   1.150 -
   1.151 -  /** This variable contains the current state. */
   1.152 -  private int mode;
   1.153 -
   1.154 -  /**
   1.155 -   * The adler checksum of the dictionary or of the decompressed
   1.156 -   * stream, as it is written in the header resp. footer of the
   1.157 -   * compressed stream.  <br>
   1.158 -   *
   1.159 -   * Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
   1.160 -   */
   1.161 -  private int readAdler;
   1.162 -  /** 
   1.163 -   * The number of bits needed to complete the current state.  This
   1.164 -   * is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
   1.165 -   * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.  
   1.166 -   */
   1.167 -  private int neededBits;
   1.168 -  private int repLength, repDist;
   1.169 -  private int uncomprLen;
   1.170 -  /**
   1.171 -   * True, if the last block flag was set in the last block of the
   1.172 -   * inflated stream.  This means that the stream ends after the
   1.173 -   * current block.  
   1.174 -   */
   1.175 -  private boolean isLastBlock;
   1.176 -
   1.177 -  /**
   1.178 -   * The total number of inflated bytes.
   1.179 -   */
   1.180 -  private long totalOut;
   1.181 -  /**
   1.182 -   * The total number of bytes set with setInput().  This is not the
   1.183 -   * value returned by getTotalIn(), since this also includes the 
   1.184 -   * unprocessed input.
   1.185 -   */
   1.186 -  private long totalIn;
   1.187 -  /**
   1.188 -   * This variable stores the nowrap flag that was given to the constructor.
   1.189 -   * True means, that the inflated stream doesn't contain a header nor the
   1.190 -   * checksum in the footer.
   1.191 -   */
   1.192 -  private boolean nowrap;
   1.193 -
   1.194 -  private StreamManipulator input;
   1.195 -  private OutputWindow outputWindow;
   1.196 -  private InflaterDynHeader dynHeader;
   1.197 -  private InflaterHuffmanTree litlenTree, distTree;
   1.198 -  private Adler32 adler;
   1.199 -
   1.200 -  /**
   1.201 -   * Creates a new inflater.
   1.202 -   */
   1.203 -  public Inflater ()
   1.204 -  {
   1.205 -    this (false);
   1.206 -  }
   1.207 -
   1.208 -  /**
   1.209 -   * Creates a new inflater.
   1.210 -   * @param nowrap true if no header and checksum field appears in the
   1.211 -   * stream.  This is used for GZIPed input.  For compatibility with
   1.212 -   * Sun JDK you should provide one byte of input more than needed in
   1.213 -   * this case.
   1.214 -   */
   1.215 -  public Inflater (boolean nowrap)
   1.216 -  {
   1.217 -    this.nowrap = nowrap;
   1.218 -    this.adler = new Adler32();
   1.219 -    input = new StreamManipulator();
   1.220 -    outputWindow = new OutputWindow();
   1.221 -    mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
   1.222 -  }
   1.223 -
   1.224 -  /**
   1.225 -   * Finalizes this object.
   1.226 -   */
   1.227 -  protected void finalize ()
   1.228 -  {
   1.229 -    /* Exists only for compatibility */
   1.230 -  }
   1.231 -
   1.232 -  /**
   1.233 -   * Frees all objects allocated by the inflater.  There's no reason
   1.234 -   * to call this, since you can just rely on garbage collection (even
   1.235 -   * for the Sun implementation).  Exists only for compatibility
   1.236 -   * with Sun's JDK, where the compressor allocates native memory.
   1.237 -   * If you call any method (even reset) afterwards the behaviour is
   1.238 -   * <i>undefined</i>.  
   1.239 -   * @deprecated Just clear all references to inflater instead.
   1.240 -   */
   1.241 -  public void end ()
   1.242 -  {
   1.243 -    outputWindow = null;
   1.244 -    input = null;
   1.245 -    dynHeader = null;
   1.246 -    litlenTree = null;
   1.247 -    distTree = null;
   1.248 -    adler = null;
   1.249 -  }
   1.250 -
   1.251 -  /**
   1.252 -   * Returns true, if the inflater has finished.  This means, that no
   1.253 -   * input is needed and no output can be produced.
   1.254 -   */
   1.255 -  public boolean finished() 
   1.256 -  {
   1.257 -    return mode == FINISHED && outputWindow.getAvailable() == 0;
   1.258 -  }
   1.259 -
   1.260 -  /**
   1.261 -   * Gets the adler checksum.  This is either the checksum of all
   1.262 -   * uncompressed bytes returned by inflate(), or if needsDictionary()
   1.263 -   * returns true (and thus no output was yet produced) this is the
   1.264 -   * adler checksum of the expected dictionary.
   1.265 -   * @returns the adler checksum.
   1.266 -   */
   1.267 -  public int getAdler()
   1.268 -  {
   1.269 -    return needsDictionary() ? readAdler : (int) adler.getValue();
   1.270 -  }
   1.271 -  
   1.272 -  /**
   1.273 -   * Gets the number of unprocessed input.  Useful, if the end of the
   1.274 -   * stream is reached and you want to further process the bytes after
   1.275 -   * the deflate stream.  
   1.276 -   * @return the number of bytes of the input which were not processed.
   1.277 -   */
   1.278 -  public int getRemaining()
   1.279 -  {
   1.280 -    return input.getAvailableBytes();
   1.281 -  }
   1.282 -  
   1.283 -  /**
   1.284 -   * Gets the total number of processed compressed input bytes.
   1.285 -   * @return the total number of bytes of processed input bytes.
   1.286 -   */
   1.287 -  public int getTotalIn()
   1.288 -  {
   1.289 -    return (int)getBytesRead();
   1.290 -  }
   1.291 -  
   1.292 -  /**
   1.293 -   * Gets the total number of output bytes returned by inflate().
   1.294 -   * @return the total number of output bytes.
   1.295 -   */
   1.296 -  public int getTotalOut()
   1.297 -  {
   1.298 -    return (int)totalOut;
   1.299 -  }
   1.300 -  
   1.301 -  public long getBytesWritten() {
   1.302 -     return totalOut;
   1.303 -  }
   1.304 -
   1.305 -  public long getBytesRead() {
   1.306 -    return totalIn - getRemaining();
   1.307 -  }
   1.308 -  
   1.309 -
   1.310 -  /**
   1.311 -   * Inflates the compressed stream to the output buffer.  If this
   1.312 -   * returns 0, you should check, whether needsDictionary(),
   1.313 -   * needsInput() or finished() returns true, to determine why no 
   1.314 -   * further output is produced.
   1.315 -   * @param buffer the output buffer.
   1.316 -   * @return the number of bytes written to the buffer, 0 if no further
   1.317 -   * output can be produced.  
   1.318 -   * @exception DataFormatException if deflated stream is invalid.
   1.319 -   * @exception IllegalArgumentException if buf has length 0.
   1.320 -   */
   1.321 -  public int inflate (byte[] buf) throws DataFormatException
   1.322 -  {
   1.323 -    return inflate (buf, 0, buf.length);
   1.324 -  }
   1.325 -
   1.326 -  /**
   1.327 -   * Inflates the compressed stream to the output buffer.  If this
   1.328 -   * returns 0, you should check, whether needsDictionary(),
   1.329 -   * needsInput() or finished() returns true, to determine why no 
   1.330 -   * further output is produced.
   1.331 -   * @param buffer the output buffer.
   1.332 -   * @param off the offset into buffer where the output should start.
   1.333 -   * @param len the maximum length of the output.
   1.334 -   * @return the number of bytes written to the buffer, 0 if no further
   1.335 -   * output can be produced.  
   1.336 -   * @exception DataFormatException if deflated stream is invalid.
   1.337 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
   1.338 -   */
   1.339 -  public int inflate (byte[] buf, int off, int len) throws DataFormatException
   1.340 -  {
   1.341 -    /* Special case: len may be zero */
   1.342 -    if (len == 0)
   1.343 -      return 0;
   1.344 -    /* Check for correct buff, off, len triple */
   1.345 -    if (0 > off || off > off + len || off + len > buf.length)
   1.346 -      throw new ArrayIndexOutOfBoundsException();
   1.347 -    int count = 0;
   1.348 -    int more;
   1.349 -    do
   1.350 -      {
   1.351 -	if (mode != DECODE_CHKSUM)
   1.352 -	  {
   1.353 -	    /* Don't give away any output, if we are waiting for the
   1.354 -	     * checksum in the input stream.
   1.355 -	     *
   1.356 -	     * With this trick we have always:
   1.357 -	     *   needsInput() and not finished() 
   1.358 -	     *   implies more output can be produced.  
   1.359 -	     */
   1.360 -	    more = outputWindow.copyOutput(buf, off, len);
   1.361 -	    adler.update(buf, off, more);
   1.362 -	    off += more;
   1.363 -	    count += more;
   1.364 -	    totalOut += more;
   1.365 -	    len -= more;
   1.366 -	    if (len == 0)
   1.367 -	      return count;
   1.368 -	  }
   1.369 -      }
   1.370 -    while (decode() || (outputWindow.getAvailable() > 0
   1.371 -			&& mode != DECODE_CHKSUM));
   1.372 -    return count;
   1.373 -  }
   1.374 -
   1.375 -  /**
   1.376 -   * Returns true, if a preset dictionary is needed to inflate the input.
   1.377 -   */
   1.378 -  public boolean needsDictionary ()
   1.379 -  {
   1.380 -    return mode == DECODE_DICT && neededBits == 0;
   1.381 -  }
   1.382 -
   1.383 -  /**
   1.384 -   * Returns true, if the input buffer is empty.
   1.385 -   * You should then call setInput(). <br>
   1.386 -   *
   1.387 -   * <em>NOTE</em>: This method also returns true when the stream is finished.
   1.388 -   */
   1.389 -  public boolean needsInput () 
   1.390 -  {
   1.391 -    return input.needsInput ();
   1.392 -  }
   1.393 -
   1.394 -  /**
   1.395 -   * Resets the inflater so that a new stream can be decompressed.  All
   1.396 -   * pending input and output will be discarded.
   1.397 -   */
   1.398 -  public void reset ()
   1.399 -  {
   1.400 -    mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
   1.401 -    totalIn = totalOut = 0;
   1.402 -    input.reset();
   1.403 -    outputWindow.reset();
   1.404 -    dynHeader = null;
   1.405 -    litlenTree = null;
   1.406 -    distTree = null;
   1.407 -    isLastBlock = false;
   1.408 -    adler.reset();
   1.409 -  }
   1.410 -
   1.411 -  /**
   1.412 -   * Sets the preset dictionary.  This should only be called, if
   1.413 -   * needsDictionary() returns true and it should set the same
   1.414 -   * dictionary, that was used for deflating.  The getAdler()
   1.415 -   * function returns the checksum of the dictionary needed.
   1.416 -   * @param buffer the dictionary.
   1.417 -   * @exception IllegalStateException if no dictionary is needed.
   1.418 -   * @exception IllegalArgumentException if the dictionary checksum is
   1.419 -   * wrong.  
   1.420 -   */
   1.421 -  public void setDictionary (byte[] buffer)
   1.422 -  {
   1.423 -    setDictionary(buffer, 0, buffer.length);
   1.424 -  }
   1.425 -
   1.426 -  /**
   1.427 -   * Sets the preset dictionary.  This should only be called, if
   1.428 -   * needsDictionary() returns true and it should set the same
   1.429 -   * dictionary, that was used for deflating.  The getAdler()
   1.430 -   * function returns the checksum of the dictionary needed.
   1.431 -   * @param buffer the dictionary.
   1.432 -   * @param off the offset into buffer where the dictionary starts.
   1.433 -   * @param len the length of the dictionary.
   1.434 -   * @exception IllegalStateException if no dictionary is needed.
   1.435 -   * @exception IllegalArgumentException if the dictionary checksum is
   1.436 -   * wrong.  
   1.437 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
   1.438 -   */
   1.439 -  public void setDictionary (byte[] buffer, int off, int len)
   1.440 -  {
   1.441 -    if (!needsDictionary())
   1.442 -      throw new IllegalStateException();
   1.443 -
   1.444 -    adler.update(buffer, off, len);
   1.445 -    if ((int) adler.getValue() != readAdler)
   1.446 -      throw new IllegalArgumentException("Wrong adler checksum");
   1.447 -    adler.reset();
   1.448 -    outputWindow.copyDict(buffer, off, len);
   1.449 -    mode = DECODE_BLOCKS;
   1.450 -  }
   1.451 -
   1.452 -  /**
   1.453 -   * Sets the input.  This should only be called, if needsInput()
   1.454 -   * returns true.
   1.455 -   * @param buffer the input.
   1.456 -   * @exception IllegalStateException if no input is needed.
   1.457 -   */
   1.458 -  public void setInput (byte[] buf) 
   1.459 -  {
   1.460 -    setInput (buf, 0, buf.length);
   1.461 -  }
   1.462 -
   1.463 -  /**
   1.464 -   * Sets the input.  This should only be called, if needsInput()
   1.465 -   * returns true.
   1.466 -   * @param buffer the input.
   1.467 -   * @param off the offset into buffer where the input starts.
   1.468 -   * @param len the length of the input.  
   1.469 -   * @exception IllegalStateException if no input is needed.
   1.470 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
   1.471 -   */
   1.472 -  public void setInput (byte[] buf, int off, int len) 
   1.473 -  {
   1.474 -    input.setInput (buf, off, len);
   1.475 -    totalIn += len;
   1.476 -  }
   1.477 -  private static final int DEFLATED = 8;
   1.478 -  /**
   1.479 -   * Decodes the deflate header.
   1.480 -   * @return false if more input is needed. 
   1.481 -   * @exception DataFormatException if header is invalid.
   1.482 -   */
   1.483 -  private boolean decodeHeader () throws DataFormatException
   1.484 -  {
   1.485 -    int header = input.peekBits(16);
   1.486 -    if (header < 0)
   1.487 -      return false;
   1.488 -    input.dropBits(16);
   1.489 +public
   1.490 +class Inflater {
   1.491 +    private final org.apidesign.bck2brwsr.emul.zip.Inflater impl;
   1.492      
   1.493 -    /* The header is written in "wrong" byte order */
   1.494 -    header = ((header << 8) | (header >> 8)) & 0xffff;
   1.495 -    if (header % 31 != 0)
   1.496 -      throw new DataFormatException("Header checksum illegal");
   1.497 -    
   1.498 -    if ((header & 0x0f00) != (DEFLATED << 8))
   1.499 -      throw new DataFormatException("Compression Method unknown");
   1.500 -
   1.501 -    /* Maximum size of the backwards window in bits. 
   1.502 -     * We currently ignore this, but we could use it to make the
   1.503 -     * inflater window more space efficient. On the other hand the
   1.504 -     * full window (15 bits) is needed most times, anyway.
   1.505 -     int max_wbits = ((header & 0x7000) >> 12) + 8;
   1.506 +    /**
   1.507 +     * Creates a new decompressor. If the parameter 'nowrap' is true then
   1.508 +     * the ZLIB header and checksum fields will not be used. This provides
   1.509 +     * compatibility with the compression format used by both GZIP and PKZIP.
   1.510 +     * <p>
   1.511 +     * Note: When using the 'nowrap' option it is also necessary to provide
   1.512 +     * an extra "dummy" byte as input. This is required by the ZLIB native
   1.513 +     * library in order to support certain optimizations.
   1.514 +     *
   1.515 +     * @param nowrap if true then support GZIP compatible compression
   1.516       */
   1.517 -    
   1.518 -    if ((header & 0x0020) == 0) // Dictionary flag?
   1.519 -      {
   1.520 -	mode = DECODE_BLOCKS;
   1.521 -      }
   1.522 -    else
   1.523 -      {
   1.524 -	mode = DECODE_DICT;
   1.525 -	neededBits = 32;      
   1.526 -      }
   1.527 -    return true;
   1.528 -  }
   1.529 -   
   1.530 -  /**
   1.531 -   * Decodes the dictionary checksum after the deflate header.
   1.532 -   * @return false if more input is needed. 
   1.533 -   */
   1.534 -  private boolean decodeDict ()
   1.535 -  {
   1.536 -    while (neededBits > 0)
   1.537 -      {
   1.538 -	int dictByte = input.peekBits(8);
   1.539 -	if (dictByte < 0)
   1.540 -	  return false;
   1.541 -	input.dropBits(8);
   1.542 -	readAdler = (readAdler << 8) | dictByte;
   1.543 -	neededBits -= 8;
   1.544 -      }
   1.545 -    return false;
   1.546 -  }
   1.547 -
   1.548 -  /**
   1.549 -   * Decodes the huffman encoded symbols in the input stream.
   1.550 -   * @return false if more input is needed, true if output window is
   1.551 -   * full or the current block ends.
   1.552 -   * @exception DataFormatException if deflated stream is invalid.  
   1.553 -   */
   1.554 -  private boolean decodeHuffman () throws DataFormatException
   1.555 -  {
   1.556 -    int free = outputWindow.getFreeSpace();
   1.557 -    while (free >= 258)
   1.558 -      {
   1.559 -	int symbol;
   1.560 -	switch (mode)
   1.561 -	  {
   1.562 -	  case DECODE_HUFFMAN:
   1.563 -	    /* This is the inner loop so it is optimized a bit */
   1.564 -	    while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0)
   1.565 -	      {
   1.566 -		outputWindow.write(symbol);
   1.567 -		if (--free < 258)
   1.568 -		  return true;
   1.569 -	      } 
   1.570 -	    if (symbol < 257)
   1.571 -	      {
   1.572 -		if (symbol < 0)
   1.573 -		  return false;
   1.574 -		else
   1.575 -		  {
   1.576 -		    /* symbol == 256: end of block */
   1.577 -		    distTree = null;
   1.578 -		    litlenTree = null;
   1.579 -		    mode = DECODE_BLOCKS;
   1.580 -		    return true;
   1.581 -		  }
   1.582 -	      }
   1.583 -		
   1.584 -	    try
   1.585 -	      {
   1.586 -		repLength = CPLENS[symbol - 257];
   1.587 -		neededBits = CPLEXT[symbol - 257];
   1.588 -	      }
   1.589 -	    catch (ArrayIndexOutOfBoundsException ex)
   1.590 -	      {
   1.591 -		throw new DataFormatException("Illegal rep length code");
   1.592 -	      }
   1.593 -	    /* fall through */
   1.594 -	  case DECODE_HUFFMAN_LENBITS:
   1.595 -	    if (neededBits > 0)
   1.596 -	      {
   1.597 -		mode = DECODE_HUFFMAN_LENBITS;
   1.598 -		int i = input.peekBits(neededBits);
   1.599 -		if (i < 0)
   1.600 -		  return false;
   1.601 -		input.dropBits(neededBits);
   1.602 -		repLength += i;
   1.603 -	      }
   1.604 -	    mode = DECODE_HUFFMAN_DIST;
   1.605 -	    /* fall through */
   1.606 -	  case DECODE_HUFFMAN_DIST:
   1.607 -	    symbol = distTree.getSymbol(input);
   1.608 -	    if (symbol < 0)
   1.609 -	      return false;
   1.610 -	    try 
   1.611 -	      {
   1.612 -		repDist = CPDIST[symbol];
   1.613 -		neededBits = CPDEXT[symbol];
   1.614 -	      }
   1.615 -	    catch (ArrayIndexOutOfBoundsException ex)
   1.616 -	      {
   1.617 -		throw new DataFormatException("Illegal rep dist code");
   1.618 -	      }
   1.619 -	    /* fall through */
   1.620 -	  case DECODE_HUFFMAN_DISTBITS:
   1.621 -	    if (neededBits > 0)
   1.622 -	      {
   1.623 -		mode = DECODE_HUFFMAN_DISTBITS;
   1.624 -		int i = input.peekBits(neededBits);
   1.625 -		if (i < 0)
   1.626 -		  return false;
   1.627 -		input.dropBits(neededBits);
   1.628 -		repDist += i;
   1.629 -	      }
   1.630 -	    outputWindow.repeat(repLength, repDist);
   1.631 -	    free -= repLength;
   1.632 -	    mode = DECODE_HUFFMAN;
   1.633 -	    break;
   1.634 -	  default:
   1.635 -	    throw new IllegalStateException();
   1.636 -	  }
   1.637 -      }
   1.638 -    return true;
   1.639 -  }
   1.640 -
   1.641 -  /**
   1.642 -   * Decodes the adler checksum after the deflate stream.
   1.643 -   * @return false if more input is needed. 
   1.644 -   * @exception DataFormatException if checksum doesn't match.
   1.645 -   */
   1.646 -  private boolean decodeChksum () throws DataFormatException
   1.647 -  {
   1.648 -    while (neededBits > 0)
   1.649 -      {
   1.650 -	int chkByte = input.peekBits(8);
   1.651 -	if (chkByte < 0)
   1.652 -	  return false;
   1.653 -	input.dropBits(8);
   1.654 -	readAdler = (readAdler << 8) | chkByte;
   1.655 -	neededBits -= 8;
   1.656 -      }
   1.657 -    if ((int) adler.getValue() != readAdler)
   1.658 -      throw new DataFormatException("Adler chksum doesn't match: "
   1.659 -				    +Integer.toHexString((int)adler.getValue())
   1.660 -				    +" vs. "+Integer.toHexString(readAdler));
   1.661 -    mode = FINISHED;
   1.662 -    return false;
   1.663 -  }
   1.664 -
   1.665 -  /**
   1.666 -   * Decodes the deflated stream.
   1.667 -   * @return false if more input is needed, or if finished. 
   1.668 -   * @exception DataFormatException if deflated stream is invalid.
   1.669 -   */
   1.670 -  private boolean decode () throws DataFormatException
   1.671 -  {
   1.672 -    switch (mode) 
   1.673 -      {
   1.674 -      case DECODE_HEADER:
   1.675 -	return decodeHeader();
   1.676 -      case DECODE_DICT:
   1.677 -	return decodeDict();
   1.678 -      case DECODE_CHKSUM:
   1.679 -	return decodeChksum();
   1.680 -
   1.681 -      case DECODE_BLOCKS:
   1.682 -	if (isLastBlock)
   1.683 -	  {
   1.684 -	    if (nowrap)
   1.685 -	      {
   1.686 -		mode = FINISHED;
   1.687 -		return false;
   1.688 -	      }
   1.689 -	    else
   1.690 -	      {
   1.691 -		input.skipToByteBoundary();
   1.692 -		neededBits = 32;
   1.693 -		mode = DECODE_CHKSUM;
   1.694 -		return true;
   1.695 -	      }
   1.696 -	  }
   1.697 -
   1.698 -	int type = input.peekBits(3);
   1.699 -	if (type < 0)
   1.700 -	  return false;
   1.701 -	input.dropBits(3);
   1.702 -
   1.703 -	if ((type & 1) != 0)
   1.704 -	  isLastBlock = true;
   1.705 -	switch (type >> 1)
   1.706 -	  {
   1.707 -	  case DeflaterConstants.STORED_BLOCK:
   1.708 -	    input.skipToByteBoundary();
   1.709 -	    mode = DECODE_STORED_LEN1;
   1.710 -	    break;
   1.711 -	  case DeflaterConstants.STATIC_TREES:
   1.712 -	    litlenTree = InflaterHuffmanTree.defLitLenTree;
   1.713 -	    distTree = InflaterHuffmanTree.defDistTree;
   1.714 -	    mode = DECODE_HUFFMAN;
   1.715 -	    break;
   1.716 -	  case DeflaterConstants.DYN_TREES:
   1.717 -	    dynHeader = new InflaterDynHeader();
   1.718 -	    mode = DECODE_DYN_HEADER;
   1.719 -	    break;
   1.720 -	  default:
   1.721 -	    throw new DataFormatException("Unknown block type "+type);
   1.722 -	  }
   1.723 -	return true;
   1.724 -
   1.725 -      case DECODE_STORED_LEN1:
   1.726 -	{
   1.727 -	  if ((uncomprLen = input.peekBits(16)) < 0)
   1.728 -	    return false;
   1.729 -	  input.dropBits(16);
   1.730 -	  mode = DECODE_STORED_LEN2;
   1.731 -	}
   1.732 -	/* fall through */
   1.733 -      case DECODE_STORED_LEN2:
   1.734 -	{
   1.735 -	  int nlen = input.peekBits(16);
   1.736 -	  if (nlen < 0)
   1.737 -	    return false;
   1.738 -	  input.dropBits(16);
   1.739 -	  if (nlen != (uncomprLen ^ 0xffff))
   1.740 -	    throw new DataFormatException("broken uncompressed block");
   1.741 -	  mode = DECODE_STORED;
   1.742 -	}
   1.743 -	/* fall through */
   1.744 -      case DECODE_STORED:
   1.745 -	{
   1.746 -	  int more = outputWindow.copyStored(input, uncomprLen);
   1.747 -	  uncomprLen -= more;
   1.748 -	  if (uncomprLen == 0)
   1.749 -	    {
   1.750 -	      mode = DECODE_BLOCKS;
   1.751 -	      return true;
   1.752 -	    }
   1.753 -	  return !input.needsInput();
   1.754 -	}
   1.755 -
   1.756 -      case DECODE_DYN_HEADER:
   1.757 -	if (!dynHeader.decode(input))
   1.758 -	  return false;
   1.759 -	litlenTree = dynHeader.buildLitLenTree();
   1.760 -	distTree = dynHeader.buildDistTree();
   1.761 -	mode = DECODE_HUFFMAN;
   1.762 -	/* fall through */
   1.763 -      case DECODE_HUFFMAN:
   1.764 -      case DECODE_HUFFMAN_LENBITS:
   1.765 -      case DECODE_HUFFMAN_DIST:
   1.766 -      case DECODE_HUFFMAN_DISTBITS:
   1.767 -	return decodeHuffman();
   1.768 -      case FINISHED:
   1.769 -	return false;
   1.770 -      default:
   1.771 -	throw new IllegalStateException();
   1.772 -      }	
   1.773 -  }
   1.774 -
   1.775 -
   1.776 -    interface DeflaterConstants {
   1.777 -      final static boolean DEBUGGING = false;
   1.778 -
   1.779 -      final static int STORED_BLOCK = 0;
   1.780 -      final static int STATIC_TREES = 1;
   1.781 -      final static int DYN_TREES    = 2;
   1.782 -      final static int PRESET_DICT  = 0x20;
   1.783 -
   1.784 -      final static int DEFAULT_MEM_LEVEL = 8;
   1.785 -
   1.786 -      final static int MAX_MATCH = 258;
   1.787 -      final static int MIN_MATCH = 3;
   1.788 -
   1.789 -      final static int MAX_WBITS = 15;
   1.790 -      final static int WSIZE = 1 << MAX_WBITS;
   1.791 -      final static int WMASK = WSIZE - 1;
   1.792 -
   1.793 -      final static int HASH_BITS = DEFAULT_MEM_LEVEL + 7;
   1.794 -      final static int HASH_SIZE = 1 << HASH_BITS;
   1.795 -      final static int HASH_MASK = HASH_SIZE - 1;
   1.796 -      final static int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH;
   1.797 -
   1.798 -      final static int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
   1.799 -      final static int MAX_DIST = WSIZE - MIN_LOOKAHEAD;
   1.800 -
   1.801 -      final static int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8);
   1.802 -      final static int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE-5);
   1.803 -
   1.804 -      final static int DEFLATE_STORED = 0;
   1.805 -      final static int DEFLATE_FAST   = 1;
   1.806 -      final static int DEFLATE_SLOW   = 2;
   1.807 -
   1.808 -      final static int GOOD_LENGTH[] = { 0,4, 4, 4, 4, 8,  8,  8,  32,  32 };
   1.809 -      final static int MAX_LAZY[]    = { 0,4, 5, 6, 4,16, 16, 32, 128, 258 };
   1.810 -      final static int NICE_LENGTH[] = { 0,8,16,32,16,32,128,128, 258, 258 };
   1.811 -      final static int MAX_CHAIN[]   = { 0,4, 8,32,16,32,128,256,1024,4096 };
   1.812 -      final static int COMPR_FUNC[]  = { 0,1, 1, 1, 1, 2,  2,  2,   2,   2 };
   1.813 -    }
   1.814 -    private static class InflaterHuffmanTree {
   1.815 -      private final static int MAX_BITLEN = 15;
   1.816 -      private short[] tree;
   1.817 -
   1.818 -      public static InflaterHuffmanTree defLitLenTree, defDistTree;
   1.819 -
   1.820 -      static
   1.821 -      {
   1.822 -        try 
   1.823 -          {
   1.824 -        byte[] codeLengths = new byte[288];
   1.825 -        int i = 0;
   1.826 -        while (i < 144)
   1.827 -          codeLengths[i++] = 8;
   1.828 -        while (i < 256)
   1.829 -          codeLengths[i++] = 9;
   1.830 -        while (i < 280)
   1.831 -          codeLengths[i++] = 7;
   1.832 -        while (i < 288)
   1.833 -          codeLengths[i++] = 8;
   1.834 -        defLitLenTree = new InflaterHuffmanTree(codeLengths);
   1.835 -
   1.836 -        codeLengths = new byte[32];
   1.837 -        i = 0;
   1.838 -        while (i < 32)
   1.839 -          codeLengths[i++] = 5;
   1.840 -        defDistTree = new InflaterHuffmanTree(codeLengths);
   1.841 -          } 
   1.842 -        catch (DataFormatException ex)
   1.843 -          {
   1.844 -        throw new IllegalStateException
   1.845 -          ("InflaterHuffmanTree: static tree length illegal");
   1.846 -          }
   1.847 -      }
   1.848 -
   1.849 -      /**
   1.850 -       * Constructs a Huffman tree from the array of code lengths.
   1.851 -       *
   1.852 -       * @param codeLengths the array of code lengths
   1.853 -       */
   1.854 -      public InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException
   1.855 -      {
   1.856 -        buildTree(codeLengths);
   1.857 -      }
   1.858 -
   1.859 -      private void buildTree(byte[] codeLengths) throws DataFormatException
   1.860 -      {
   1.861 -        int[] blCount = new int[MAX_BITLEN+1];
   1.862 -        int[] nextCode = new int[MAX_BITLEN+1];
   1.863 -        for (int i = 0; i < codeLengths.length; i++)
   1.864 -          {
   1.865 -        int bits = codeLengths[i];
   1.866 -        if (bits > 0)
   1.867 -          blCount[bits]++;
   1.868 -          }
   1.869 -
   1.870 -        int code = 0;
   1.871 -        int treeSize = 512;
   1.872 -        for (int bits = 1; bits <= MAX_BITLEN; bits++)
   1.873 -          {
   1.874 -        nextCode[bits] = code;
   1.875 -        code += blCount[bits] << (16 - bits);
   1.876 -        if (bits >= 10)
   1.877 -          {
   1.878 -            /* We need an extra table for bit lengths >= 10. */
   1.879 -            int start = nextCode[bits] & 0x1ff80;
   1.880 -            int end   = code & 0x1ff80;
   1.881 -            treeSize += (end - start) >> (16 - bits);
   1.882 -          }
   1.883 -          }
   1.884 -        if (code != 65536)
   1.885 -          throw new DataFormatException("Code lengths don't add up properly.");
   1.886 -
   1.887 -        fillTable1(treeSize, code, blCount);
   1.888 -
   1.889 -        for (int i = 0; i < codeLengths.length; i++)
   1.890 -          {
   1.891 -        int bits = codeLengths[i];
   1.892 -        if (bits == 0)
   1.893 -          continue;
   1.894 -        code = nextCode[bits];
   1.895 -        int revcode = bitReverse(code);
   1.896 -        if (bits <= 9)
   1.897 -          {
   1.898 -            do
   1.899 -              {
   1.900 -            tree[revcode] = (short) ((i << 4) | bits);
   1.901 -            revcode += 1 << bits;
   1.902 -              }
   1.903 -            while (revcode < 512);
   1.904 -          }
   1.905 -        else
   1.906 -          {
   1.907 -            int subTree = tree[revcode & 511];
   1.908 -            int treeLen = 1 << (subTree & 15);
   1.909 -            subTree = -(subTree >> 4);
   1.910 -            do
   1.911 -              { 
   1.912 -            tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits);
   1.913 -            revcode += 1 << bits;
   1.914 -              }
   1.915 -            while (revcode < treeLen);
   1.916 -          }
   1.917 -        nextCode[bits] = code + (1 << (16 - bits));
   1.918 -          }
   1.919 -      }
   1.920 -      private final static String bit4Reverse =
   1.921 -        "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017";
   1.922 -      static short bitReverse(int value) {
   1.923 -            return (short) (bit4Reverse.charAt(value & 0xf) << 12
   1.924 -                    | bit4Reverse.charAt((value >> 4) & 0xf) << 8
   1.925 -                    | bit4Reverse.charAt((value >> 8) & 0xf) << 4
   1.926 -                    | bit4Reverse.charAt(value >> 12));
   1.927 -      }
   1.928 -      
   1.929 -      /**
   1.930 -       * Reads the next symbol from input.  The symbol is encoded using the
   1.931 -       * huffman tree.
   1.932 -       * @param input the input source.
   1.933 -       * @return the next symbol, or -1 if not enough input is available.
   1.934 -       */
   1.935 -      public int getSymbol(StreamManipulator input) throws DataFormatException
   1.936 -      {
   1.937 -        int lookahead, symbol;
   1.938 -        if ((lookahead = input.peekBits(9)) >= 0)
   1.939 -          {
   1.940 -        if ((symbol = tree[lookahead]) >= 0)
   1.941 -          {
   1.942 -            input.dropBits(symbol & 15);
   1.943 -            return symbol >> 4;
   1.944 -          }
   1.945 -        int subtree = -(symbol >> 4);
   1.946 -        int bitlen = symbol & 15;
   1.947 -        if ((lookahead = input.peekBits(bitlen)) >= 0)
   1.948 -          {
   1.949 -            symbol = tree[subtree | (lookahead >> 9)];
   1.950 -            input.dropBits(symbol & 15);
   1.951 -            return symbol >> 4;
   1.952 -          }
   1.953 -        else
   1.954 -          {
   1.955 -            int bits = input.getAvailableBits();
   1.956 -            lookahead = input.peekBits(bits);
   1.957 -            symbol = tree[subtree | (lookahead >> 9)];
   1.958 -            if ((symbol & 15) <= bits)
   1.959 -              {
   1.960 -            input.dropBits(symbol & 15);
   1.961 -            return symbol >> 4;
   1.962 -              }
   1.963 -            else
   1.964 -              return -1;
   1.965 -          }
   1.966 -          }
   1.967 -        else
   1.968 -          {
   1.969 -        int bits = input.getAvailableBits();
   1.970 -        lookahead = input.peekBits(bits);
   1.971 -        symbol = tree[lookahead];
   1.972 -        if (symbol >= 0 && (symbol & 15) <= bits)
   1.973 -          {
   1.974 -            input.dropBits(symbol & 15);
   1.975 -            return symbol >> 4;
   1.976 -          }
   1.977 -        else
   1.978 -          return -1;
   1.979 -          }
   1.980 -      }
   1.981 -
   1.982 -        private void fillTable1(int treeSize, int code, int[] blCount) {
   1.983 -            /* Now create and fill the extra tables from longest to shortest
   1.984 -             * bit len.  This way the sub trees will be aligned.
   1.985 -             */
   1.986 -            tree = new short[treeSize];
   1.987 -            int treePtr = 512;
   1.988 -            for (int bits = MAX_BITLEN; bits >= 10; bits--) {
   1.989 -                int end = code & 0x1ff80;
   1.990 -                code -= blCount[bits] << (16 - bits);
   1.991 -                int start = code & 0x1ff80;
   1.992 -                final int inc = 1 << 7;
   1.993 -                fillTable2(start, end, inc, treePtr, bits);
   1.994 -            }
   1.995 -        }
   1.996 -
   1.997 -        private void fillTable2(int start, int end, final int inc, int treePtr, int bits) {
   1.998 -            for (int i = start; i < end; i += inc) {
   1.999 -                final short br = bitReverse(i);
  1.1000 -                tree[br] = (short) ((-treePtr << 4) | bits);
  1.1001 -                treePtr += 1 << (bits - 9);
  1.1002 -            }
  1.1003 +    public Inflater(boolean nowrap) {
  1.1004 +        if (getClass() == org.apidesign.bck2brwsr.emul.zip.Inflater.class) {
  1.1005 +            impl = null;
  1.1006 +        } else {
  1.1007 +            impl = new org.apidesign.bck2brwsr.emul.zip.Inflater(nowrap);
  1.1008          }
  1.1009      }
  1.1010 -    private static class InflaterDynHeader
  1.1011 +
  1.1012 +    /**
  1.1013 +     * Creates a new decompressor.
  1.1014 +     */
  1.1015 +    public Inflater() {
  1.1016 +        this(false);
  1.1017 +    }
  1.1018 +
  1.1019 +    /**
  1.1020 +     * Sets input data for decompression. Should be called whenever
  1.1021 +     * needsInput() returns true indicating that more input data is
  1.1022 +     * required.
  1.1023 +     * @param b the input data bytes
  1.1024 +     * @param off the start offset of the input data
  1.1025 +     * @param len the length of the input data
  1.1026 +     * @see Inflater#needsInput
  1.1027 +     */
  1.1028 +    public void setInput(byte[] b, int off, int len) {
  1.1029 +        impl.setInput(b, off, len);
  1.1030 +    }
  1.1031 +
  1.1032 +    /**
  1.1033 +     * Sets input data for decompression. Should be called whenever
  1.1034 +     * needsInput() returns true indicating that more input data is
  1.1035 +     * required.
  1.1036 +     * @param b the input data bytes
  1.1037 +     * @see Inflater#needsInput
  1.1038 +     */
  1.1039 +    public void setInput(byte[] b) {
  1.1040 +        impl.setInput(b);
  1.1041 +    }
  1.1042 +
  1.1043 +    /**
  1.1044 +     * Sets the preset dictionary to the given array of bytes. Should be
  1.1045 +     * called when inflate() returns 0 and needsDictionary() returns true
  1.1046 +     * indicating that a preset dictionary is required. The method getAdler()
  1.1047 +     * can be used to get the Adler-32 value of the dictionary needed.
  1.1048 +     * @param b the dictionary data bytes
  1.1049 +     * @param off the start offset of the data
  1.1050 +     * @param len the length of the data
  1.1051 +     * @see Inflater#needsDictionary
  1.1052 +     * @see Inflater#getAdler
  1.1053 +     */
  1.1054 +    public void setDictionary(byte[] b, int off, int len) {
  1.1055 +        impl.setDictionary(b, off, len);
  1.1056 +    }
  1.1057 +
  1.1058 +    /**
  1.1059 +     * Sets the preset dictionary to the given array of bytes. Should be
  1.1060 +     * called when inflate() returns 0 and needsDictionary() returns true
  1.1061 +     * indicating that a preset dictionary is required. The method getAdler()
  1.1062 +     * can be used to get the Adler-32 value of the dictionary needed.
  1.1063 +     * @param b the dictionary data bytes
  1.1064 +     * @see Inflater#needsDictionary
  1.1065 +     * @see Inflater#getAdler
  1.1066 +     */
  1.1067 +    public void setDictionary(byte[] b) {
  1.1068 +        impl.setDictionary(b);
  1.1069 +    }
  1.1070 +
  1.1071 +    /**
  1.1072 +     * Returns the total number of bytes remaining in the input buffer.
  1.1073 +     * This can be used to find out what bytes still remain in the input
  1.1074 +     * buffer after decompression has finished.
  1.1075 +     * @return the total number of bytes remaining in the input buffer
  1.1076 +     */
  1.1077 +    public int getRemaining() {
  1.1078 +        return impl.getRemaining();
  1.1079 +    }
  1.1080 +
  1.1081 +    /**
  1.1082 +     * Returns true if no data remains in the input buffer. This can
  1.1083 +     * be used to determine if #setInput should be called in order
  1.1084 +     * to provide more input.
  1.1085 +     * @return true if no data remains in the input buffer
  1.1086 +     */
  1.1087 +    public boolean needsInput() {
  1.1088 +        return impl.needsInput();
  1.1089 +    }
  1.1090 +
  1.1091 +    /**
  1.1092 +     * Returns true if a preset dictionary is needed for decompression.
  1.1093 +     * @return true if a preset dictionary is needed for decompression
  1.1094 +     * @see Inflater#setDictionary
  1.1095 +     */
  1.1096 +    public boolean needsDictionary() {
  1.1097 +        return impl.needsDictionary();
  1.1098 +    }
  1.1099 +
  1.1100 +    /**
  1.1101 +     * Returns true if the end of the compressed data stream has been
  1.1102 +     * reached.
  1.1103 +     * @return true if the end of the compressed data stream has been
  1.1104 +     * reached
  1.1105 +     */
  1.1106 +    public boolean finished() {
  1.1107 +        return impl.finished();
  1.1108 +    }
  1.1109 +
  1.1110 +    /**
  1.1111 +     * Uncompresses bytes into specified buffer. Returns actual number
  1.1112 +     * of bytes uncompressed. A return value of 0 indicates that
  1.1113 +     * needsInput() or needsDictionary() should be called in order to
  1.1114 +     * determine if more input data or a preset dictionary is required.
  1.1115 +     * In the latter case, getAdler() can be used to get the Adler-32
  1.1116 +     * value of the dictionary required.
  1.1117 +     * @param b the buffer for the uncompressed data
  1.1118 +     * @param off the start offset of the data
  1.1119 +     * @param len the maximum number of uncompressed bytes
  1.1120 +     * @return the actual number of uncompressed bytes
  1.1121 +     * @exception DataFormatException if the compressed data format is invalid
  1.1122 +     * @see Inflater#needsInput
  1.1123 +     * @see Inflater#needsDictionary
  1.1124 +     */
  1.1125 +    public int inflate(byte[] b, int off, int len)
  1.1126 +        throws DataFormatException
  1.1127      {
  1.1128 -      private static final int LNUM   = 0;
  1.1129 -      private static final int DNUM   = 1;
  1.1130 -      private static final int BLNUM  = 2;
  1.1131 -      private static final int BLLENS = 3;
  1.1132 -      private static final int LENS   = 4;
  1.1133 -      private static final int REPS   = 5;
  1.1134 +        return impl.inflate(b, off, len);
  1.1135 +    }
  1.1136  
  1.1137 -      private static final int repMin[]  = { 3, 3, 11 };
  1.1138 -      private static final int repBits[] = { 2, 3,  7 };
  1.1139 +    /**
  1.1140 +     * Uncompresses bytes into specified buffer. Returns actual number
  1.1141 +     * of bytes uncompressed. A return value of 0 indicates that
  1.1142 +     * needsInput() or needsDictionary() should be called in order to
  1.1143 +     * determine if more input data or a preset dictionary is required.
  1.1144 +     * In the latter case, getAdler() can be used to get the Adler-32
  1.1145 +     * value of the dictionary required.
  1.1146 +     * @param b the buffer for the uncompressed data
  1.1147 +     * @return the actual number of uncompressed bytes
  1.1148 +     * @exception DataFormatException if the compressed data format is invalid
  1.1149 +     * @see Inflater#needsInput
  1.1150 +     * @see Inflater#needsDictionary
  1.1151 +     */
  1.1152 +    public int inflate(byte[] b) throws DataFormatException {
  1.1153 +        return impl.inflate(b);
  1.1154 +    }
  1.1155  
  1.1156 +    /**
  1.1157 +     * Returns the ADLER-32 value of the uncompressed data.
  1.1158 +     * @return the ADLER-32 value of the uncompressed data
  1.1159 +     */
  1.1160 +    public int getAdler() {
  1.1161 +        return impl.getAdler();
  1.1162 +    }
  1.1163  
  1.1164 -      private byte[] blLens;
  1.1165 -      private byte[] litdistLens;
  1.1166 +    /**
  1.1167 +     * Returns the total number of compressed bytes input so far.
  1.1168 +     *
  1.1169 +     * <p>Since the number of bytes may be greater than
  1.1170 +     * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
  1.1171 +     * the preferred means of obtaining this information.</p>
  1.1172 +     *
  1.1173 +     * @return the total number of compressed bytes input so far
  1.1174 +     */
  1.1175 +    public int getTotalIn() {
  1.1176 +        return impl.getTotalIn();
  1.1177 +    }
  1.1178  
  1.1179 -      private InflaterHuffmanTree blTree;
  1.1180 +    /**
  1.1181 +     * Returns the total number of compressed bytes input so far.</p>
  1.1182 +     *
  1.1183 +     * @return the total (non-negative) number of compressed bytes input so far
  1.1184 +     * @since 1.5
  1.1185 +     */
  1.1186 +    public long getBytesRead() {
  1.1187 +        return impl.getBytesRead();
  1.1188 +    }
  1.1189  
  1.1190 -      private int mode;
  1.1191 -      private int lnum, dnum, blnum, num;
  1.1192 -      private int repSymbol;
  1.1193 -      private byte lastLen;
  1.1194 -      private int ptr;
  1.1195 +    /**
  1.1196 +     * Returns the total number of uncompressed bytes output so far.
  1.1197 +     *
  1.1198 +     * <p>Since the number of bytes may be greater than
  1.1199 +     * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
  1.1200 +     * the preferred means of obtaining this information.</p>
  1.1201 +     *
  1.1202 +     * @return the total number of uncompressed bytes output so far
  1.1203 +     */
  1.1204 +    public int getTotalOut() {
  1.1205 +        return impl.getTotalOut();
  1.1206 +    }
  1.1207  
  1.1208 -      private static final int[] BL_ORDER =
  1.1209 -      { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
  1.1210 +    /**
  1.1211 +     * Returns the total number of uncompressed bytes output so far.</p>
  1.1212 +     *
  1.1213 +     * @return the total (non-negative) number of uncompressed bytes output so far
  1.1214 +     * @since 1.5
  1.1215 +     */
  1.1216 +    public long getBytesWritten() {
  1.1217 +        return impl.getBytesWritten();
  1.1218 +    }
  1.1219  
  1.1220 -      public InflaterDynHeader()
  1.1221 -      {
  1.1222 -      }
  1.1223 +    /**
  1.1224 +     * Resets inflater so that a new set of input data can be processed.
  1.1225 +     */
  1.1226 +    public void reset() {
  1.1227 +        impl.reset();
  1.1228 +    }
  1.1229  
  1.1230 -      public boolean decode(StreamManipulator input) throws DataFormatException
  1.1231 -      {
  1.1232 -      decode_loop:
  1.1233 -        for (;;)
  1.1234 -          {
  1.1235 -        switch (mode)
  1.1236 -          {
  1.1237 -          case LNUM:
  1.1238 -            lnum = input.peekBits(5);
  1.1239 -            if (lnum < 0)
  1.1240 -              return false;
  1.1241 -            lnum += 257;
  1.1242 -            input.dropBits(5);
  1.1243 -    //  	    System.err.println("LNUM: "+lnum);
  1.1244 -            mode = DNUM;
  1.1245 -            /* fall through */
  1.1246 -          case DNUM:
  1.1247 -            dnum = input.peekBits(5);
  1.1248 -            if (dnum < 0)
  1.1249 -              return false;
  1.1250 -            dnum++;
  1.1251 -            input.dropBits(5);
  1.1252 -    //  	    System.err.println("DNUM: "+dnum);
  1.1253 -            num = lnum+dnum;
  1.1254 -            litdistLens = new byte[num];
  1.1255 -            mode = BLNUM;
  1.1256 -            /* fall through */
  1.1257 -          case BLNUM:
  1.1258 -            blnum = input.peekBits(4);
  1.1259 -            if (blnum < 0)
  1.1260 -              return false;
  1.1261 -            blnum += 4;
  1.1262 -            input.dropBits(4);
  1.1263 -            blLens = new byte[19];
  1.1264 -            ptr = 0;
  1.1265 -    //  	    System.err.println("BLNUM: "+blnum);
  1.1266 -            mode = BLLENS;
  1.1267 -            /* fall through */
  1.1268 -          case BLLENS:
  1.1269 -            while (ptr < blnum)
  1.1270 -              {
  1.1271 -            int len = input.peekBits(3);
  1.1272 -            if (len < 0)
  1.1273 -              return false;
  1.1274 -            input.dropBits(3);
  1.1275 -    //  		System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
  1.1276 -            blLens[BL_ORDER[ptr]] = (byte) len;
  1.1277 -            ptr++;
  1.1278 -              }
  1.1279 -            blTree = new InflaterHuffmanTree(blLens);
  1.1280 -            blLens = null;
  1.1281 -            ptr = 0;
  1.1282 -            mode = LENS;
  1.1283 -            /* fall through */
  1.1284 -          case LENS:
  1.1285 -            {
  1.1286 -              int symbol;
  1.1287 -              while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
  1.1288 -            {
  1.1289 -              /* Normal case: symbol in [0..15] */
  1.1290 +    /**
  1.1291 +     * Closes the decompressor and discards any unprocessed input.
  1.1292 +     * This method should be called when the decompressor is no longer
  1.1293 +     * being used, but will also be called automatically by the finalize()
  1.1294 +     * method. Once this method is called, the behavior of the Inflater
  1.1295 +     * object is undefined.
  1.1296 +     */
  1.1297 +    public void end() {
  1.1298 +        impl.end();
  1.1299 +    }
  1.1300  
  1.1301 -    //  		  System.err.println("litdistLens["+ptr+"]: "+symbol);
  1.1302 -              litdistLens[ptr++] = lastLen = (byte) symbol;
  1.1303 -
  1.1304 -              if (ptr == num)
  1.1305 -                {
  1.1306 -                  /* Finished */
  1.1307 -                  return true;
  1.1308 -                }
  1.1309 -            }
  1.1310 -
  1.1311 -              /* need more input ? */
  1.1312 -              if (symbol < 0)
  1.1313 -            return false;
  1.1314 -
  1.1315 -              /* otherwise repeat code */
  1.1316 -              if (symbol >= 17)
  1.1317 -            {
  1.1318 -              /* repeat zero */
  1.1319 -    //  		  System.err.println("repeating zero");
  1.1320 -              lastLen = 0;
  1.1321 -            }
  1.1322 -              else
  1.1323 -            {
  1.1324 -              if (ptr == 0)
  1.1325 -                throw new DataFormatException();
  1.1326 -            }
  1.1327 -              repSymbol = symbol-16;
  1.1328 -              mode = REPS;
  1.1329 -            }
  1.1330 -            /* fall through */
  1.1331 -
  1.1332 -          case REPS:
  1.1333 -            {
  1.1334 -              int bits = repBits[repSymbol];
  1.1335 -              int count = input.peekBits(bits);
  1.1336 -              if (count < 0)
  1.1337 -            return false;
  1.1338 -              input.dropBits(bits);
  1.1339 -              count += repMin[repSymbol];
  1.1340 -    //  	      System.err.println("litdistLens repeated: "+count);
  1.1341 -
  1.1342 -              if (ptr + count > num)
  1.1343 -            throw new DataFormatException();
  1.1344 -              while (count-- > 0)
  1.1345 -            litdistLens[ptr++] = lastLen;
  1.1346 -
  1.1347 -              if (ptr == num)
  1.1348 -            {
  1.1349 -              /* Finished */
  1.1350 -              return true;
  1.1351 -            }
  1.1352 -            }
  1.1353 -            mode = LENS;
  1.1354 -            continue decode_loop;
  1.1355 -          }
  1.1356 -          }
  1.1357 -      }
  1.1358 -
  1.1359 -      public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
  1.1360 -      {
  1.1361 -        byte[] litlenLens = new byte[lnum];
  1.1362 -        System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
  1.1363 -        return new InflaterHuffmanTree(litlenLens);
  1.1364 -      }
  1.1365 -
  1.1366 -      public InflaterHuffmanTree buildDistTree() throws DataFormatException
  1.1367 -      {
  1.1368 -        byte[] distLens = new byte[dnum];
  1.1369 -        System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
  1.1370 -        return new InflaterHuffmanTree(distLens);
  1.1371 -      }
  1.1372 +    /**
  1.1373 +     * Closes the decompressor when garbage is collected.
  1.1374 +     */
  1.1375 +    protected void finalize() {
  1.1376 +        end();
  1.1377      }
  1.1378 -    /**
  1.1379 -     * This class allows us to retrieve a specified amount of bits from
  1.1380 -     * the input buffer, as well as copy big byte blocks.
  1.1381 -     *
  1.1382 -     * It uses an int buffer to store up to 31 bits for direct
  1.1383 -     * manipulation.  This guarantees that we can get at least 16 bits,
  1.1384 -     * but we only need at most 15, so this is all safe.
  1.1385 -     *
  1.1386 -     * There are some optimizations in this class, for example, you must
  1.1387 -     * never peek more then 8 bits more than needed, and you must first 
  1.1388 -     * peek bits before you may drop them.  This is not a general purpose
  1.1389 -     * class but optimized for the behaviour of the Inflater.
  1.1390 -     *
  1.1391 -     * @author John Leuner, Jochen Hoenicke
  1.1392 -     */
  1.1393 -
  1.1394 -    private static class StreamManipulator
  1.1395 -    {
  1.1396 -      private byte[] window;
  1.1397 -      private int window_start = 0;
  1.1398 -      private int window_end = 0;
  1.1399 -
  1.1400 -      private int buffer = 0;
  1.1401 -      private int bits_in_buffer = 0;
  1.1402 -
  1.1403 -      /**
  1.1404 -       * Get the next n bits but don't increase input pointer.  n must be
  1.1405 -       * less or equal 16 and if you if this call succeeds, you must drop
  1.1406 -       * at least n-8 bits in the next call.
  1.1407 -       * 
  1.1408 -       * @return the value of the bits, or -1 if not enough bits available.  */
  1.1409 -      public final int peekBits(int n)
  1.1410 -      {
  1.1411 -        if (bits_in_buffer < n)
  1.1412 -          {
  1.1413 -        if (window_start == window_end)
  1.1414 -          return -1;
  1.1415 -        buffer |= (window[window_start++] & 0xff
  1.1416 -               | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
  1.1417 -        bits_in_buffer += 16;
  1.1418 -          }
  1.1419 -        return buffer & ((1 << n) - 1);
  1.1420 -      }
  1.1421 -
  1.1422 -      /* Drops the next n bits from the input.  You should have called peekBits
  1.1423 -       * with a bigger or equal n before, to make sure that enough bits are in
  1.1424 -       * the bit buffer.
  1.1425 -       */
  1.1426 -      public final void dropBits(int n)
  1.1427 -      {
  1.1428 -        buffer >>>= n;
  1.1429 -        bits_in_buffer -= n;
  1.1430 -      }
  1.1431 -
  1.1432 -      /**
  1.1433 -       * Gets the next n bits and increases input pointer.  This is equivalent
  1.1434 -       * to peekBits followed by dropBits, except for correct error handling.
  1.1435 -       * @return the value of the bits, or -1 if not enough bits available. 
  1.1436 -       */
  1.1437 -      public final int getBits(int n)
  1.1438 -      {
  1.1439 -        int bits = peekBits(n);
  1.1440 -        if (bits >= 0)
  1.1441 -          dropBits(n);
  1.1442 -        return bits;
  1.1443 -      }
  1.1444 -      /**
  1.1445 -       * Gets the number of bits available in the bit buffer.  This must be
  1.1446 -       * only called when a previous peekBits() returned -1.
  1.1447 -       * @return the number of bits available.
  1.1448 -       */
  1.1449 -      public final int getAvailableBits()
  1.1450 -      {
  1.1451 -        return bits_in_buffer;
  1.1452 -      }
  1.1453 -
  1.1454 -      /**
  1.1455 -       * Gets the number of bytes available.  
  1.1456 -       * @return the number of bytes available.
  1.1457 -       */
  1.1458 -      public final int getAvailableBytes()
  1.1459 -      {
  1.1460 -        return window_end - window_start + (bits_in_buffer >> 3);
  1.1461 -      }
  1.1462 -
  1.1463 -      /**
  1.1464 -       * Skips to the next byte boundary.
  1.1465 -       */
  1.1466 -      public void skipToByteBoundary()
  1.1467 -      {
  1.1468 -        buffer >>= (bits_in_buffer & 7);
  1.1469 -        bits_in_buffer &= ~7;
  1.1470 -      }
  1.1471 -
  1.1472 -      public final boolean needsInput() {
  1.1473 -        return window_start == window_end;
  1.1474 -      }
  1.1475 -
  1.1476 -
  1.1477 -      /* Copies length bytes from input buffer to output buffer starting
  1.1478 -       * at output[offset].  You have to make sure, that the buffer is
  1.1479 -       * byte aligned.  If not enough bytes are available, copies fewer
  1.1480 -       * bytes.
  1.1481 -       * @param length the length to copy, 0 is allowed.
  1.1482 -       * @return the number of bytes copied, 0 if no byte is available.  
  1.1483 -       */
  1.1484 -      public int copyBytes(byte[] output, int offset, int length)
  1.1485 -      {
  1.1486 -        if (length < 0)
  1.1487 -          throw new IllegalArgumentException("length negative");
  1.1488 -        if ((bits_in_buffer & 7) != 0)  
  1.1489 -          /* bits_in_buffer may only be 0 or 8 */
  1.1490 -          throw new IllegalStateException("Bit buffer is not aligned!");
  1.1491 -
  1.1492 -        int count = 0;
  1.1493 -        while (bits_in_buffer > 0 && length > 0)
  1.1494 -          {
  1.1495 -        output[offset++] = (byte) buffer;
  1.1496 -        buffer >>>= 8;
  1.1497 -        bits_in_buffer -= 8;
  1.1498 -        length--;
  1.1499 -        count++;
  1.1500 -          }
  1.1501 -        if (length == 0)
  1.1502 -          return count;
  1.1503 -
  1.1504 -        int avail = window_end - window_start;
  1.1505 -        if (length > avail)
  1.1506 -          length = avail;
  1.1507 -        System.arraycopy(window, window_start, output, offset, length);
  1.1508 -        window_start += length;
  1.1509 -
  1.1510 -        if (((window_start - window_end) & 1) != 0)
  1.1511 -          {
  1.1512 -        /* We always want an even number of bytes in input, see peekBits */
  1.1513 -        buffer = (window[window_start++] & 0xff);
  1.1514 -        bits_in_buffer = 8;
  1.1515 -          }
  1.1516 -        return count + length;
  1.1517 -      }
  1.1518 -
  1.1519 -      public StreamManipulator()
  1.1520 -      {
  1.1521 -      }
  1.1522 -
  1.1523 -      public void reset()
  1.1524 -      {
  1.1525 -        window_start = window_end = buffer = bits_in_buffer = 0;
  1.1526 -      }
  1.1527 -
  1.1528 -      public void setInput(byte[] buf, int off, int len)
  1.1529 -      {
  1.1530 -        if (window_start < window_end)
  1.1531 -          throw new IllegalStateException
  1.1532 -        ("Old input was not completely processed");
  1.1533 -
  1.1534 -        int end = off + len;
  1.1535 -
  1.1536 -        /* We want to throw an ArrayIndexOutOfBoundsException early.  The
  1.1537 -         * check is very tricky: it also handles integer wrap around.  
  1.1538 -         */
  1.1539 -        if (0 > off || off > end || end > buf.length)
  1.1540 -          throw new ArrayIndexOutOfBoundsException();
  1.1541 -
  1.1542 -        if ((len & 1) != 0)
  1.1543 -          {
  1.1544 -        /* We always want an even number of bytes in input, see peekBits */
  1.1545 -        buffer |= (buf[off++] & 0xff) << bits_in_buffer;
  1.1546 -        bits_in_buffer += 8;
  1.1547 -          }
  1.1548 -
  1.1549 -        window = buf;
  1.1550 -        window_start = off;
  1.1551 -        window_end = end;
  1.1552 -      }
  1.1553 -    }
  1.1554 -    /*
  1.1555 -     * Contains the output from the Inflation process.
  1.1556 -     *
  1.1557 -     * We need to have a window so that we can refer backwards into the output stream
  1.1558 -     * to repeat stuff.
  1.1559 -     *
  1.1560 -     * @author John Leuner
  1.1561 -     * @since JDK 1.1
  1.1562 -     */
  1.1563 -
  1.1564 -    private static class OutputWindow
  1.1565 -    {
  1.1566 -      private final int WINDOW_SIZE = 1 << 15;
  1.1567 -      private final int WINDOW_MASK = WINDOW_SIZE - 1;
  1.1568 -
  1.1569 -      private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
  1.1570 -      private int window_end  = 0;
  1.1571 -      private int window_filled = 0;
  1.1572 -
  1.1573 -      public void write(int abyte)
  1.1574 -      {
  1.1575 -        if (window_filled++ == WINDOW_SIZE)
  1.1576 -          throw new IllegalStateException("Window full");
  1.1577 -        window[window_end++] = (byte) abyte;
  1.1578 -        window_end &= WINDOW_MASK;
  1.1579 -      }
  1.1580 -
  1.1581 -
  1.1582 -      private final void slowRepeat(int rep_start, int len, int dist)
  1.1583 -      {
  1.1584 -        while (len-- > 0)
  1.1585 -          {
  1.1586 -        window[window_end++] = window[rep_start++];
  1.1587 -        window_end &= WINDOW_MASK;
  1.1588 -        rep_start &= WINDOW_MASK;
  1.1589 -          }
  1.1590 -      }
  1.1591 -
  1.1592 -      public void repeat(int len, int dist)
  1.1593 -      {
  1.1594 -        if ((window_filled += len) > WINDOW_SIZE)
  1.1595 -          throw new IllegalStateException("Window full");
  1.1596 -
  1.1597 -        int rep_start = (window_end - dist) & WINDOW_MASK;
  1.1598 -        int border = WINDOW_SIZE - len;
  1.1599 -        if (rep_start <= border && window_end < border)
  1.1600 -          {
  1.1601 -        if (len <= dist)
  1.1602 -          {
  1.1603 -            System.arraycopy(window, rep_start, window, window_end, len);
  1.1604 -            window_end += len;
  1.1605 -          }
  1.1606 -        else
  1.1607 -          {
  1.1608 -            /* We have to copy manually, since the repeat pattern overlaps.
  1.1609 -             */
  1.1610 -            while (len-- > 0)
  1.1611 -              window[window_end++] = window[rep_start++];
  1.1612 -          }
  1.1613 -          }
  1.1614 -        else
  1.1615 -          slowRepeat(rep_start, len, dist);
  1.1616 -      }
  1.1617 -
  1.1618 -      public int copyStored(StreamManipulator input, int len)
  1.1619 -      {
  1.1620 -        len = Math.min(Math.min(len, WINDOW_SIZE - window_filled), 
  1.1621 -               input.getAvailableBytes());
  1.1622 -        int copied;
  1.1623 -
  1.1624 -        int tailLen = WINDOW_SIZE - window_end;
  1.1625 -        if (len > tailLen)
  1.1626 -          {
  1.1627 -        copied = input.copyBytes(window, window_end, tailLen);
  1.1628 -        if (copied == tailLen)
  1.1629 -          copied += input.copyBytes(window, 0, len - tailLen);
  1.1630 -          }
  1.1631 -        else
  1.1632 -          copied = input.copyBytes(window, window_end, len);
  1.1633 -
  1.1634 -        window_end = (window_end + copied) & WINDOW_MASK;
  1.1635 -        window_filled += copied;
  1.1636 -        return copied;
  1.1637 -      }
  1.1638 -
  1.1639 -      public void copyDict(byte[] dict, int offset, int len)
  1.1640 -      {
  1.1641 -        if (window_filled > 0)
  1.1642 -          throw new IllegalStateException();
  1.1643 -
  1.1644 -        if (len > WINDOW_SIZE)
  1.1645 -          {
  1.1646 -        offset += len - WINDOW_SIZE;
  1.1647 -        len = WINDOW_SIZE;
  1.1648 -          }
  1.1649 -        System.arraycopy(dict, offset, window, 0, len);
  1.1650 -        window_end = len & WINDOW_MASK;
  1.1651 -      }
  1.1652 -
  1.1653 -      public int getFreeSpace()
  1.1654 -      {
  1.1655 -        return WINDOW_SIZE - window_filled;
  1.1656 -      }
  1.1657 -
  1.1658 -      public int getAvailable()
  1.1659 -      {
  1.1660 -        return window_filled;
  1.1661 -      }
  1.1662 -
  1.1663 -      public int copyOutput(byte[] output, int offset, int len)
  1.1664 -      {
  1.1665 -        int copy_end = window_end;
  1.1666 -        if (len > window_filled)
  1.1667 -          len = window_filled;
  1.1668 -        else
  1.1669 -          copy_end = (window_end - window_filled + len) & WINDOW_MASK;
  1.1670 -
  1.1671 -        int copied = len;
  1.1672 -        int tailLen = len - copy_end;
  1.1673 -
  1.1674 -        if (tailLen > 0)
  1.1675 -          {
  1.1676 -        System.arraycopy(window, WINDOW_SIZE - tailLen,
  1.1677 -                 output, offset, tailLen);
  1.1678 -        offset += tailLen;
  1.1679 -        len = copy_end;
  1.1680 -          }
  1.1681 -        System.arraycopy(window, copy_end - len, output, offset, len);
  1.1682 -        window_filled -= copied;
  1.1683 -        if (window_filled < 0)
  1.1684 -          throw new IllegalStateException();
  1.1685 -        return copied;
  1.1686 -      }
  1.1687 -
  1.1688 -      public void reset() {
  1.1689 -        window_filled = window_end = 0;
  1.1690 -      }
  1.1691 -    }
  1.1692 -  
  1.1693  }