Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
2 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
26 package org.apidesign.bck2brwsr.emul.zip;
28 import java.util.zip.*;
29 import java.io.IOException;
32 * This class provides support for general purpose decompression using the
33 * popular ZLIB compression library. The ZLIB compression library was
34 * initially developed as part of the PNG graphics standard and is not
35 * protected by patents. It is fully described in the specifications at
36 * the <a href="package-summary.html#package_description">java.util.zip
37 * package description</a>.
39 * <p>The following code fragment demonstrates a trivial compression
40 * and decompression of a string using <tt>Deflater</tt> and
45 * // Encode a String into bytes
46 * String inputString = "blahblahblah\u20AC\u20AC";
47 * byte[] input = inputString.getBytes("UTF-8");
49 * // Compress the bytes
50 * byte[] output = new byte[100];
51 * Deflater compresser = new Deflater();
52 * compresser.setInput(input);
53 * compresser.finish();
54 * int compressedDataLength = compresser.deflate(output);
56 * // Decompress the bytes
57 * Inflater decompresser = new Inflater();
58 * decompresser.setInput(output, 0, compressedDataLength);
59 * byte[] result = new byte[100];
60 * int resultLength = decompresser.inflate(result);
63 * // Decode the bytes into a String
64 * String outputString = new String(result, 0, resultLength, "UTF-8");
65 * } catch(java.io.UnsupportedEncodingException ex) {
67 * } catch (java.util.zip.DataFormatException ex) {
73 * @author David Connelly
77 class Inflater extends java.util.zip.Inflater {
78 private final boolean nowrap;
79 private JzLibInflater impl;
82 * Creates a new decompressor. If the parameter 'nowrap' is true then
83 * the ZLIB header and checksum fields will not be used. This provides
84 * compatibility with the compression format used by both GZIP and PKZIP.
86 * Note: When using the 'nowrap' option it is also necessary to provide
87 * an extra "dummy" byte as input. This is required by the ZLIB native
88 * library in order to support certain optimizations.
90 * @param nowrap if true then support GZIP compatible compression
92 public Inflater(boolean nowrap) {
98 * Creates a new decompressor.
105 * Sets input data for decompression. Should be called whenever
106 * needsInput() returns true indicating that more input data is
108 * @param b the input data bytes
109 * @param off the start offset of the input data
110 * @param len the length of the input data
111 * @see Inflater#needsInput
113 public void setInput(byte[] b, int off, int len) {
115 throw new NullPointerException();
117 if (off < 0 || len < 0 || off > b.length - len) {
118 throw new ArrayIndexOutOfBoundsException();
120 impl.setInput(b, off, len, false);
124 * Sets input data for decompression. Should be called whenever
125 * needsInput() returns true indicating that more input data is
127 * @param b the input data bytes
128 * @see Inflater#needsInput
130 public void setInput(byte[] b) {
131 setInput(b, 0, b.length);
135 * Sets the preset dictionary to the given array of bytes. Should be
136 * called when inflate() returns 0 and needsDictionary() returns true
137 * indicating that a preset dictionary is required. The method getAdler()
138 * can be used to get the Adler-32 value of the dictionary needed.
139 * @param b the dictionary data bytes
140 * @param off the start offset of the data
141 * @param len the length of the data
142 * @see Inflater#needsDictionary
143 * @see Inflater#getAdler
145 public void setDictionary(byte[] b, int off, int len) {
147 throw new NullPointerException();
149 if (off < 0 || len < 0 || off > b.length - len) {
150 throw new ArrayIndexOutOfBoundsException();
157 org.apidesign.bck2brwsr.emul.lang.System.arraycopy(b, off, arr, 0, len);
159 impl.setDictionary(arr, len);
163 * Sets the preset dictionary to the given array of bytes. Should be
164 * called when inflate() returns 0 and needsDictionary() returns true
165 * indicating that a preset dictionary is required. The method getAdler()
166 * can be used to get the Adler-32 value of the dictionary needed.
167 * @param b the dictionary data bytes
168 * @see Inflater#needsDictionary
169 * @see Inflater#getAdler
171 public void setDictionary(byte[] b) {
172 impl.setDictionary(b, b.length);
176 * Returns the total number of bytes remaining in the input buffer.
177 * This can be used to find out what bytes still remain in the input
178 * buffer after decompression has finished.
179 * @return the total number of bytes remaining in the input buffer
181 public int getRemaining() {
182 return impl.getAvailIn();
186 * Returns true if no data remains in the input buffer. This can
187 * be used to determine if #setInput should be called in order
188 * to provide more input.
189 * @return true if no data remains in the input buffer
191 public boolean needsInput() {
192 return getRemaining() <= 0;
196 * Returns true if a preset dictionary is needed for decompression.
197 * @return true if a preset dictionary is needed for decompression
198 * @see Inflater#setDictionary
200 public boolean needsDictionary() {
201 return impl.needDict();
205 * Returns true if the end of the compressed data stream has been
207 * @return true if the end of the compressed data stream has been
210 public boolean finished() {
211 return impl.finished();
215 * Uncompresses bytes into specified buffer. Returns actual number
216 * of bytes uncompressed. A return value of 0 indicates that
217 * needsInput() or needsDictionary() should be called in order to
218 * determine if more input data or a preset dictionary is required.
219 * In the latter case, getAdler() can be used to get the Adler-32
220 * value of the dictionary required.
221 * @param b the buffer for the uncompressed data
222 * @param off the start offset of the data
223 * @param len the maximum number of uncompressed bytes
224 * @return the actual number of uncompressed bytes
225 * @exception DataFormatException if the compressed data format is invalid
226 * @see Inflater#needsInput
227 * @see Inflater#needsDictionary
229 public int inflate(byte[] b, int off, int len)
230 throws DataFormatException
233 throw new NullPointerException();
235 if (off < 0 || len < 0 || off > b.length - len) {
236 throw new ArrayIndexOutOfBoundsException();
238 impl.setOutput(b, off, len);
239 int err = impl.inflate(JzLibInflater.Z_NO_FLUSH);
240 return impl.next_out_index - off;
244 * Uncompresses bytes into specified buffer. Returns actual number
245 * of bytes uncompressed. A return value of 0 indicates that
246 * needsInput() or needsDictionary() should be called in order to
247 * determine if more input data or a preset dictionary is required.
248 * In the latter case, getAdler() can be used to get the Adler-32
249 * value of the dictionary required.
250 * @param b the buffer for the uncompressed data
251 * @return the actual number of uncompressed bytes
252 * @exception DataFormatException if the compressed data format is invalid
253 * @see Inflater#needsInput
254 * @see Inflater#needsDictionary
256 public int inflate(byte[] b) throws DataFormatException {
257 return inflate(b, 0, b.length);
261 * Returns the ADLER-32 value of the uncompressed data.
262 * @return the ADLER-32 value of the uncompressed data
264 public int getAdler() {
265 return (int) impl.getAdler();
269 * Returns the total number of compressed bytes input so far.
271 * <p>Since the number of bytes may be greater than
272 * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
273 * the preferred means of obtaining this information.</p>
275 * @return the total number of compressed bytes input so far
277 public int getTotalIn() {
278 return (int) getBytesRead();
282 * Returns the total number of compressed bytes input so far.</p>
284 * @return the total (non-negative) number of compressed bytes input so far
287 public long getBytesRead() {
288 return impl.total_in;
292 * Returns the total number of uncompressed bytes output so far.
294 * <p>Since the number of bytes may be greater than
295 * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
296 * the preferred means of obtaining this information.</p>
298 * @return the total number of uncompressed bytes output so far
300 public int getTotalOut() {
301 return (int) getBytesWritten();
305 * Returns the total number of uncompressed bytes output so far.</p>
307 * @return the total (non-negative) number of uncompressed bytes output so far
310 public long getBytesWritten() {
311 return impl.total_out;
315 * Resets inflater so that a new set of input data can be processed.
317 public void reset() {
318 impl = new JzLibInflater(15, nowrap);
322 * Closes the decompressor and discards any unprocessed input.
323 * This method should be called when the decompressor is no longer
324 * being used, but will also be called automatically by the finalize()
325 * method. Once this method is called, the behavior of the Inflater
326 * object is undefined.
333 * Closes the decompressor when garbage is collected.
335 protected void finalize() {