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 -}