2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package java.util.zip;
20 import java.io.FileDescriptor;
23 * This class uncompresses data that was compressed using the <i>DEFLATE</i>
24 * algorithm (see <a href="http://www.gzip.org/algorithm.txt">specification</a>).
26 * Basically this class is part of the API to the stream based ZLIB compression
27 * library and is used as such by {@code InflaterInputStream} and its
30 * The typical usage of a {@code Inflater} outside this package consists of a
31 * specific call to one of its constructors before being passed to an instance
32 * of {@code InflaterInputStream}.
34 * @see InflaterInputStream
37 public class Inflater {
38 private boolean finished; // Set by the inflateImpl native
44 private boolean needsDictionary; // Set by the inflateImpl native
46 private long streamHandle = -1;
49 * This constructor creates an inflater that expects a header from the input
50 * stream. Use {@code Inflater(boolean)} if the input comes without a ZLIB
58 * This constructor allows to create an inflater that expects no header from
62 * {@code true} indicates that no ZLIB header comes with the
65 public Inflater(boolean noHeader) {
66 streamHandle = createStream(noHeader);
69 private native long createStream(boolean noHeader1);
72 * Release any resources associated with this {@code Inflater}. Any unused
73 * input/output is discarded. This is also called by the finalize method.
75 public synchronized void end() {
76 if (streamHandle != -1) {
77 endImpl(streamHandle);
84 private native synchronized void endImpl(long handle);
86 @Override protected void finalize() {
92 } catch (Throwable t) {
93 throw new AssertionError(t);
99 * Indicates if the {@code Inflater} has inflated the entire deflated
100 * stream. If deflated bytes remain and {@code needsInput()} returns {@code
101 * true} this method will return {@code false}. This method should be
102 * called after all deflated input is supplied to the {@code Inflater}.
104 * @return {@code true} if all input has been inflated, {@code false}
107 public synchronized boolean finished() {
112 * Returns the <i>Adler32</i> checksum of either all bytes inflated, or the
113 * checksum of the preset dictionary if one has been supplied.
115 * @return The <i>Adler32</i> checksum associated with this
118 public synchronized int getAdler() {
119 if (streamHandle == -1) {
120 throw new IllegalStateException();
122 return getAdlerImpl(streamHandle);
125 private native synchronized int getAdlerImpl(long handle);
128 * Returns the total number of bytes read by the {@code Inflater}. This
129 * method performs the same as {@code getTotalIn()} except that it returns a
130 * {@code long} value instead of an integer.
132 * @return the total number of bytes read.
134 public synchronized long getBytesRead() {
136 if (streamHandle == -1) {
137 throw new NullPointerException();
139 return getTotalInImpl(streamHandle);
143 * Returns a the total number of bytes read by the {@code Inflater}. This
144 * method performs the same as {@code getTotalOut} except it returns a
145 * {@code long} value instead of an integer.
147 * @return the total bytes written to the output buffer.
149 public synchronized long getBytesWritten() {
151 if (streamHandle == -1) {
152 throw new NullPointerException();
154 return getTotalOutImpl(streamHandle);
158 * Returns the number of bytes of current input remaining to be read by the
161 * @return the number of bytes of unread input.
163 public synchronized int getRemaining() {
164 return inLength - inRead;
168 * Returns total number of bytes of input read by the {@code Inflater}. The
169 * result value is limited by {@code Integer.MAX_VALUE}.
171 * @return the total number of bytes read.
173 public synchronized int getTotalIn() {
174 if (streamHandle == -1) {
175 throw new IllegalStateException();
177 long totalIn = getTotalInImpl(streamHandle);
178 return (totalIn <= Integer.MAX_VALUE ? (int) totalIn
179 : Integer.MAX_VALUE);
182 private synchronized native long getTotalInImpl(long handle);
185 * Returns total number of bytes written to the output buffer by the {@code
186 * Inflater}. The result value is limited by {@code Integer.MAX_VALUE}.
188 * @return the total bytes of output data written.
190 public synchronized int getTotalOut() {
191 if (streamHandle == -1) {
192 throw new IllegalStateException();
194 long totalOut = getTotalOutImpl(streamHandle);
195 return (totalOut <= Integer.MAX_VALUE ? (int) totalOut
196 : Integer.MAX_VALUE);
199 private native synchronized long getTotalOutImpl(long handle);
202 * Inflates bytes from current input and stores them in {@code buf}.
205 * the buffer where decompressed data bytes are written.
206 * @return the number of bytes inflated.
207 * @throws DataFormatException
208 * if the underlying stream is corrupted or was not compressed
209 * using a {@code Deflater}.
211 public int inflate(byte[] buf) throws DataFormatException {
212 return inflate(buf, 0, buf.length);
216 * Inflates up to n bytes from the current input and stores them in {@code
217 * buf} starting at {@code off}.
220 * the buffer to write inflated bytes to.
222 * the offset in buffer where to start writing decompressed data.
224 * the number of inflated bytes to write to {@code buf}.
225 * @throws DataFormatException
226 * if the underlying stream is corrupted or was not compressed
227 * using a {@code Deflater}.
228 * @return the number of bytes inflated.
230 public synchronized int inflate(byte[] buf, int off, int nbytes)
231 throws DataFormatException {
232 // avoid int overflow, check null buf
233 if (off > buf.length || nbytes < 0 || off < 0
234 || buf.length - off < nbytes) {
235 throw new ArrayIndexOutOfBoundsException();
242 if (streamHandle == -1) {
243 throw new IllegalStateException();
250 boolean neededDict = needsDictionary;
251 needsDictionary = false;
252 int result = inflateImpl(buf, off, nbytes, streamHandle);
253 if (needsDictionary && neededDict) {
254 throw new DataFormatException("Needs dictionary");
260 private native synchronized int inflateImpl(byte[] buf, int off,
261 int nbytes, long handle);
264 * Indicates whether the input bytes were compressed with a preset
265 * dictionary. This method should be called prior to {@code inflate()} to
266 * determine whether a dictionary is required. If so {@code setDictionary()}
267 * should be called with the appropriate dictionary prior to calling {@code
270 * @return {@code true} if a preset dictionary is required for inflation.
271 * @see #setDictionary(byte[])
272 * @see #setDictionary(byte[], int, int)
274 public synchronized boolean needsDictionary() {
275 return needsDictionary;
279 * Indicates that input has to be passed to the inflater.
281 * @return {@code true} if {@code setInput} has to be called before
282 * inflation can proceed.
283 * @see #setInput(byte[])
285 public synchronized boolean needsInput() {
286 return inRead == inLength;
290 * Resets the {@code Inflater}. Should be called prior to inflating a new
293 public synchronized void reset() {
294 if (streamHandle == -1) {
295 throw new NullPointerException();
298 needsDictionary = false;
299 inLength = inRead = 0;
300 resetImpl(streamHandle);
303 private native synchronized void resetImpl(long handle);
306 * Sets the preset dictionary to be used for inflation to {@code buf}.
307 * {@code needsDictionary()} can be called to determine whether the current
308 * input was deflated using a preset dictionary.
311 * The buffer containing the dictionary bytes.
312 * @see #needsDictionary
314 public synchronized void setDictionary(byte[] buf) {
315 setDictionary(buf, 0, buf.length);
319 * Like {@code setDictionary(byte[])}, allowing to define a specific region
320 * inside {@code buf} to be used as a dictionary.
322 * The dictionary should be set if the {@link #inflate(byte[])} returned
323 * zero bytes inflated and {@link #needsDictionary()} returns
327 * the buffer containing the dictionary data bytes.
329 * the offset of the data.
331 * the length of the data.
332 * @see #needsDictionary
334 public synchronized void setDictionary(byte[] buf, int off, int nbytes) {
335 if (streamHandle == -1) {
336 throw new IllegalStateException();
338 // avoid int overflow, check null buf
339 if (off <= buf.length && nbytes >= 0 && off >= 0
340 && buf.length - off >= nbytes) {
341 setDictionaryImpl(buf, off, nbytes, streamHandle);
343 throw new ArrayIndexOutOfBoundsException();
347 private native synchronized void setDictionaryImpl(byte[] buf, int off,
348 int nbytes, long handle);
351 * Sets the current input to to be decrompressed. This method should only be
352 * called if {@code needsInput()} returns {@code true}.
358 public synchronized void setInput(byte[] buf) {
359 setInput(buf, 0, buf.length);
363 * Sets the current input to the region of the input buffer starting at
364 * {@code off} and ending at {@code nbytes - 1} where data is written after
365 * decompression. This method should only be called if {@code needsInput()}
366 * returns {@code true}.
371 * the offset to read from the input buffer.
373 * the number of bytes to read.
376 public synchronized void setInput(byte[] buf, int off, int nbytes) {
377 if (streamHandle == -1) {
378 throw new IllegalStateException();
380 // avoid int overflow, check null buf
381 if (off <= buf.length && nbytes >= 0 && off >= 0
382 && buf.length - off >= nbytes) {
385 setInputImpl(buf, off, nbytes, streamHandle);
387 throw new ArrayIndexOutOfBoundsException();
391 // BEGIN android-only
393 * Sets the current input to the region within a file starting at {@code
394 * off} and ending at {@code nbytes - 1}. This method should only be called
395 * if {@code needsInput()} returns {@code true}.
400 * the offset to read from in buffer.
402 * the number of bytes to read.
405 synchronized int setFileInput(FileDescriptor fd, long off, int nbytes) {
406 if (streamHandle == -1) {
407 throw new IllegalStateException();
410 inLength = setFileInputImpl(fd, off, nbytes, streamHandle);
415 private native synchronized void setInputImpl(byte[] buf, int off,
416 int nbytes, long handle);
418 // BEGIN android-only
419 private native synchronized int setFileInputImpl(FileDescriptor fd, long off,
420 int nbytes, long handle);