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