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