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 java.util.zip;
29 * This class provides support for general purpose decompression using the
30 * popular ZLIB compression library. The ZLIB compression library was
31 * initially developed as part of the PNG graphics standard and is not
32 * protected by patents. It is fully described in the specifications at
33 * the <a href="package-summary.html#package_description">java.util.zip
34 * package description</a>.
36 * <p>The following code fragment demonstrates a trivial compression
37 * and decompression of a string using <tt>Deflater</tt> and
42 * // Encode a String into bytes
43 * String inputString = "blahblahblah\u20AC\u20AC";
44 * byte[] input = inputString.getBytes("UTF-8");
46 * // Compress the bytes
47 * byte[] output = new byte[100];
48 * Deflater compresser = new Deflater();
49 * compresser.setInput(input);
50 * compresser.finish();
51 * int compressedDataLength = compresser.deflate(output);
53 * // Decompress the bytes
54 * Inflater decompresser = new Inflater();
55 * decompresser.setInput(output, 0, compressedDataLength);
56 * byte[] result = new byte[100];
57 * int resultLength = decompresser.inflate(result);
60 * // Decode the bytes into a String
61 * String outputString = new String(result, 0, resultLength, "UTF-8");
62 * } catch(java.io.UnsupportedEncodingException ex) {
64 * } catch (java.util.zip.DataFormatException ex) {
70 * @author David Connelly
75 private final org.apidesign.bck2brwsr.emul.zip.Inflater impl;
78 * Creates a new decompressor. If the parameter 'nowrap' is true then
79 * the ZLIB header and checksum fields will not be used. This provides
80 * compatibility with the compression format used by both GZIP and PKZIP.
82 * Note: When using the 'nowrap' option it is also necessary to provide
83 * an extra "dummy" byte as input. This is required by the ZLIB native
84 * library in order to support certain optimizations.
86 * @param nowrap if true then support GZIP compatible compression
88 public Inflater(boolean nowrap) {
89 if (getClass() == org.apidesign.bck2brwsr.emul.zip.Inflater.class) {
92 impl = new org.apidesign.bck2brwsr.emul.zip.Inflater(nowrap);
97 * Creates a new decompressor.
104 * Sets input data for decompression. Should be called whenever
105 * needsInput() returns true indicating that more input data is
107 * @param b the input data bytes
108 * @param off the start offset of the input data
109 * @param len the length of the input data
110 * @see Inflater#needsInput
112 public void setInput(byte[] b, int off, int len) {
113 impl.setInput(b, off, len);
117 * Sets input data for decompression. Should be called whenever
118 * needsInput() returns true indicating that more input data is
120 * @param b the input data bytes
121 * @see Inflater#needsInput
123 public void setInput(byte[] b) {
128 * Sets the preset dictionary to the given array of bytes. Should be
129 * called when inflate() returns 0 and needsDictionary() returns true
130 * indicating that a preset dictionary is required. The method getAdler()
131 * can be used to get the Adler-32 value of the dictionary needed.
132 * @param b the dictionary data bytes
133 * @param off the start offset of the data
134 * @param len the length of the data
135 * @see Inflater#needsDictionary
136 * @see Inflater#getAdler
138 public void setDictionary(byte[] b, int off, int len) {
139 impl.setDictionary(b, off, len);
143 * Sets the preset dictionary to the given array of bytes. Should be
144 * called when inflate() returns 0 and needsDictionary() returns true
145 * indicating that a preset dictionary is required. The method getAdler()
146 * can be used to get the Adler-32 value of the dictionary needed.
147 * @param b the dictionary data bytes
148 * @see Inflater#needsDictionary
149 * @see Inflater#getAdler
151 public void setDictionary(byte[] b) {
152 impl.setDictionary(b);
156 * Returns the total number of bytes remaining in the input buffer.
157 * This can be used to find out what bytes still remain in the input
158 * buffer after decompression has finished.
159 * @return the total number of bytes remaining in the input buffer
161 public int getRemaining() {
162 return impl.getRemaining();
166 * Returns true if no data remains in the input buffer. This can
167 * be used to determine if #setInput should be called in order
168 * to provide more input.
169 * @return true if no data remains in the input buffer
171 public boolean needsInput() {
172 return impl.needsInput();
176 * Returns true if a preset dictionary is needed for decompression.
177 * @return true if a preset dictionary is needed for decompression
178 * @see Inflater#setDictionary
180 public boolean needsDictionary() {
181 return impl.needsDictionary();
185 * Returns true if the end of the compressed data stream has been
187 * @return true if the end of the compressed data stream has been
190 public boolean finished() {
191 return impl.finished();
195 * Uncompresses bytes into specified buffer. Returns actual number
196 * of bytes uncompressed. A return value of 0 indicates that
197 * needsInput() or needsDictionary() should be called in order to
198 * determine if more input data or a preset dictionary is required.
199 * In the latter case, getAdler() can be used to get the Adler-32
200 * value of the dictionary required.
201 * @param b the buffer for the uncompressed data
202 * @param off the start offset of the data
203 * @param len the maximum number of uncompressed bytes
204 * @return the actual number of uncompressed bytes
205 * @exception DataFormatException if the compressed data format is invalid
206 * @see Inflater#needsInput
207 * @see Inflater#needsDictionary
209 public int inflate(byte[] b, int off, int len)
210 throws DataFormatException
212 return impl.inflate(b, off, len);
216 * Uncompresses bytes into specified buffer. Returns actual number
217 * of bytes uncompressed. A return value of 0 indicates that
218 * needsInput() or needsDictionary() should be called in order to
219 * determine if more input data or a preset dictionary is required.
220 * In the latter case, getAdler() can be used to get the Adler-32
221 * value of the dictionary required.
222 * @param b the buffer for the uncompressed data
223 * @return the actual number of uncompressed bytes
224 * @exception DataFormatException if the compressed data format is invalid
225 * @see Inflater#needsInput
226 * @see Inflater#needsDictionary
228 public int inflate(byte[] b) throws DataFormatException {
229 return impl.inflate(b);
233 * Returns the ADLER-32 value of the uncompressed data.
234 * @return the ADLER-32 value of the uncompressed data
236 public int getAdler() {
237 return impl.getAdler();
241 * Returns the total number of compressed bytes input so far.
243 * <p>Since the number of bytes may be greater than
244 * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
245 * the preferred means of obtaining this information.</p>
247 * @return the total number of compressed bytes input so far
249 public int getTotalIn() {
250 return impl.getTotalIn();
254 * Returns the total number of compressed bytes input so far.</p>
256 * @return the total (non-negative) number of compressed bytes input so far
259 public long getBytesRead() {
260 return impl.getBytesRead();
264 * Returns the total number of uncompressed bytes output so far.
266 * <p>Since the number of bytes may be greater than
267 * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
268 * the preferred means of obtaining this information.</p>
270 * @return the total number of uncompressed bytes output so far
272 public int getTotalOut() {
273 return impl.getTotalOut();
277 * Returns the total number of uncompressed bytes output so far.</p>
279 * @return the total (non-negative) number of uncompressed bytes output so far
282 public long getBytesWritten() {
283 return impl.getBytesWritten();
287 * Resets inflater so that a new set of input data can be processed.
289 public void reset() {
294 * Closes the decompressor and discards any unprocessed input.
295 * This method should be called when the decompressor is no longer
296 * being used, but will also be called automatically by the finalize()
297 * method. Once this method is called, the behavior of the Inflater
298 * object is undefined.
305 * Closes the decompressor when garbage is collected.
307 protected void finalize() {