OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / java / util / zip / Inflater.java
1 /*
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 package java.util.zip;
19
20 import java.io.FileDescriptor;
21
22 /**
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>).
25  * <p>
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
28  * descendants.
29  * <p>
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}.
33  *
34  * @see InflaterInputStream
35  * @see Deflater
36  */
37 public class Inflater {
38     private boolean finished; // Set by the inflateImpl native
39
40     int inLength;
41
42     int inRead;
43
44     private boolean needsDictionary; // Set by the inflateImpl native
45
46     private long streamHandle = -1;
47
48     /**
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
51      * header.
52      */
53     public Inflater() {
54         this(false);
55     }
56
57     /**
58      * This constructor allows to create an inflater that expects no header from
59      * the input stream.
60      *
61      * @param noHeader
62      *            {@code true} indicates that no ZLIB header comes with the
63      *            input.
64      */
65     public Inflater(boolean noHeader) {
66         streamHandle = createStream(noHeader);
67     }
68
69     private native long createStream(boolean noHeader1);
70
71     /**
72      * Release any resources associated with this {@code Inflater}. Any unused
73      * input/output is discarded. This is also called by the finalize method.
74      */
75     public synchronized void end() {
76         if (streamHandle != -1) {
77             endImpl(streamHandle);
78             inRead = 0;
79             inLength = 0;
80             streamHandle = -1;
81         }
82     }
83
84     private native synchronized void endImpl(long handle);
85
86     @Override protected void finalize() {
87         try {
88             end();
89         } finally {
90             try {
91                 super.finalize();
92             } catch (Throwable t) {
93                 throw new AssertionError(t);
94             }
95         }
96     }
97
98     /**
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}.
103      *
104      * @return {@code true} if all input has been inflated, {@code false}
105      *         otherwise.
106      */
107     public synchronized boolean finished() {
108         return finished;
109     }
110
111     /**
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.
114      *
115      * @return The <i>Adler32</i> checksum associated with this
116      *         {@code Inflater}.
117      */
118     public synchronized int getAdler() {
119         if (streamHandle == -1) {
120             throw new IllegalStateException();
121         }
122         return getAdlerImpl(streamHandle);
123     }
124
125     private native synchronized int getAdlerImpl(long handle);
126
127     /**
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.
131      *
132      * @return the total number of bytes read.
133      */
134     public synchronized long getBytesRead() {
135         // Throw NPE here
136         if (streamHandle == -1) {
137             throw new NullPointerException();
138         }
139         return getTotalInImpl(streamHandle);
140     }
141
142     /**
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.
146      *
147      * @return the total bytes written to the output buffer.
148      */
149     public synchronized long getBytesWritten() {
150         // Throw NPE here
151         if (streamHandle == -1) {
152             throw new NullPointerException();
153         }
154         return getTotalOutImpl(streamHandle);
155     }
156
157     /**
158      * Returns the number of bytes of current input remaining to be read by the
159      * inflater.
160      *
161      * @return the number of bytes of unread input.
162      */
163     public synchronized int getRemaining() {
164         return inLength - inRead;
165     }
166
167     /**
168      * Returns total number of bytes of input read by the {@code Inflater}. The
169      * result value is limited by {@code Integer.MAX_VALUE}.
170      *
171      * @return the total number of bytes read.
172      */
173     public synchronized int getTotalIn() {
174         if (streamHandle == -1) {
175             throw new IllegalStateException();
176         }
177         long totalIn = getTotalInImpl(streamHandle);
178         return (totalIn <= Integer.MAX_VALUE ? (int) totalIn
179                 : Integer.MAX_VALUE);
180     }
181
182     private synchronized native long getTotalInImpl(long handle);
183
184     /**
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}.
187      *
188      * @return the total bytes of output data written.
189      */
190     public synchronized int getTotalOut() {
191         if (streamHandle == -1) {
192             throw new IllegalStateException();
193         }
194         long totalOut = getTotalOutImpl(streamHandle);
195         return (totalOut <= Integer.MAX_VALUE ? (int) totalOut
196                 : Integer.MAX_VALUE);
197     }
198
199     private native synchronized long getTotalOutImpl(long handle);
200
201     /**
202      * Inflates bytes from current input and stores them in {@code buf}.
203      *
204      * @param 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}.
210      */
211     public int inflate(byte[] buf) throws DataFormatException {
212         return inflate(buf, 0, buf.length);
213     }
214
215     /**
216      * Inflates up to n bytes from the current input and stores them in {@code
217      * buf} starting at {@code off}.
218      *
219      * @param buf
220      *            the buffer to write inflated bytes to.
221      * @param off
222      *            the offset in buffer where to start writing decompressed data.
223      * @param nbytes
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.
229      */
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();
236         }
237
238         if (nbytes == 0) {
239             return 0;
240         }
241
242         if (streamHandle == -1) {
243             throw new IllegalStateException();
244         }
245
246         if (needsInput()) {
247             return 0;
248         }
249
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");
255         }
256
257         return result;
258     }
259
260     private native synchronized int inflateImpl(byte[] buf, int off,
261             int nbytes, long handle);
262
263     /**
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
268      * inflate()}.
269      *
270      * @return {@code true} if a preset dictionary is required for inflation.
271      * @see #setDictionary(byte[])
272      * @see #setDictionary(byte[], int, int)
273      */
274     public synchronized boolean needsDictionary() {
275         return needsDictionary;
276     }
277
278     /**
279      * Indicates that input has to be passed to the inflater.
280      *
281      * @return {@code true} if {@code setInput} has to be called before
282      *         inflation can proceed.
283      * @see #setInput(byte[])
284      */
285     public synchronized boolean needsInput() {
286         return inRead == inLength;
287     }
288
289     /**
290      * Resets the {@code Inflater}. Should be called prior to inflating a new
291      * set of data.
292      */
293     public synchronized void reset() {
294         if (streamHandle == -1) {
295             throw new NullPointerException();
296         }
297         finished = false;
298         needsDictionary = false;
299         inLength = inRead = 0;
300         resetImpl(streamHandle);
301     }
302
303     private native synchronized void resetImpl(long handle);
304
305     /**
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.
309      *
310      * @param buf
311      *            The buffer containing the dictionary bytes.
312      * @see #needsDictionary
313      */
314     public synchronized void setDictionary(byte[] buf) {
315         setDictionary(buf, 0, buf.length);
316     }
317
318     /**
319      * Like {@code setDictionary(byte[])}, allowing to define a specific region
320      * inside {@code buf} to be used as a dictionary.
321      * <p>
322      * The dictionary should be set if the {@link #inflate(byte[])} returned
323      * zero bytes inflated and {@link #needsDictionary()} returns
324      * <code>true</code>.
325      *
326      * @param buf
327      *            the buffer containing the dictionary data bytes.
328      * @param off
329      *            the offset of the data.
330      * @param nbytes
331      *            the length of the data.
332      * @see #needsDictionary
333      */
334     public synchronized void setDictionary(byte[] buf, int off, int nbytes) {
335         if (streamHandle == -1) {
336             throw new IllegalStateException();
337         }
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);
342         } else {
343             throw new ArrayIndexOutOfBoundsException();
344         }
345     }
346
347     private native synchronized void setDictionaryImpl(byte[] buf, int off,
348             int nbytes, long handle);
349
350     /**
351      * Sets the current input to to be decrompressed. This method should only be
352      * called if {@code needsInput()} returns {@code true}.
353      *
354      * @param buf
355      *            the input buffer.
356      * @see #needsInput
357      */
358     public synchronized void setInput(byte[] buf) {
359         setInput(buf, 0, buf.length);
360     }
361
362     /**
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}.
367      *
368      * @param buf
369      *            the input buffer.
370      * @param off
371      *            the offset to read from the input buffer.
372      * @param nbytes
373      *            the number of bytes to read.
374      * @see #needsInput
375      */
376     public synchronized void setInput(byte[] buf, int off, int nbytes) {
377         if (streamHandle == -1) {
378             throw new IllegalStateException();
379         }
380         // avoid int overflow, check null buf
381         if (off <= buf.length && nbytes >= 0 && off >= 0
382                 && buf.length - off >= nbytes) {
383             inRead = 0;
384             inLength = nbytes;
385             setInputImpl(buf, off, nbytes, streamHandle);
386         } else {
387             throw new ArrayIndexOutOfBoundsException();
388         }
389     }
390
391     // BEGIN android-only
392     /**
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}.
396      *
397      * @param fd
398      *            the input file.
399      * @param off
400      *            the offset to read from in buffer.
401      * @param nbytes
402      *            the number of bytes to read.
403      * @see #needsInput
404      */
405     synchronized int setFileInput(FileDescriptor fd, long off, int nbytes) {
406         if (streamHandle == -1) {
407             throw new IllegalStateException();
408         }
409         inRead = 0;
410         inLength = setFileInputImpl(fd, off, nbytes, streamHandle);
411         return inLength;
412     }
413     // END android-only
414
415     private native synchronized void setInputImpl(byte[] buf, int off,
416             int nbytes, long handle);
417
418     // BEGIN android-only
419     private native synchronized int setFileInputImpl(FileDescriptor fd, long off,
420             int nbytes, long handle);
421     // END android-only
422 }