emul/mini/src/main/java/java/util/zip/Inflater.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 694 0d277415ed02
parent 687 a9e506a27b55
permissions -rw-r--r--
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.
     1 /*
     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.
     4  *
     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.
    10  *
    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).
    16  *
    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.
    20  *
    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
    23  * questions.
    24  */
    25 
    26 package java.util.zip;
    27 
    28 /**
    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>.
    35  *
    36  * <p>The following code fragment demonstrates a trivial compression
    37  * and decompression of a string using <tt>Deflater</tt> and
    38  * <tt>Inflater</tt>.
    39  *
    40  * <blockquote><pre>
    41  * try {
    42  *     // Encode a String into bytes
    43  *     String inputString = "blahblahblah\u20AC\u20AC";
    44  *     byte[] input = inputString.getBytes("UTF-8");
    45  *
    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);
    52  *
    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);
    58  *     decompresser.end();
    59  *
    60  *     // Decode the bytes into a String
    61  *     String outputString = new String(result, 0, resultLength, "UTF-8");
    62  * } catch(java.io.UnsupportedEncodingException ex) {
    63  *     // handle
    64  * } catch (java.util.zip.DataFormatException ex) {
    65  *     // handle
    66  * }
    67  * </pre></blockquote>
    68  *
    69  * @see         Deflater
    70  * @author      David Connelly
    71  *
    72  */
    73 public
    74 class Inflater {
    75     private final org.apidesign.bck2brwsr.emul.zip.Inflater impl;
    76     
    77     /**
    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.
    81      * <p>
    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.
    85      *
    86      * @param nowrap if true then support GZIP compatible compression
    87      */
    88     public Inflater(boolean nowrap) {
    89         if (getClass() == org.apidesign.bck2brwsr.emul.zip.Inflater.class) {
    90             impl = null;
    91         } else {
    92             impl = new org.apidesign.bck2brwsr.emul.zip.Inflater(nowrap);
    93         }
    94     }
    95 
    96     /**
    97      * Creates a new decompressor.
    98      */
    99     public Inflater() {
   100         this(false);
   101     }
   102 
   103     /**
   104      * Sets input data for decompression. Should be called whenever
   105      * needsInput() returns true indicating that more input data is
   106      * required.
   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
   111      */
   112     public void setInput(byte[] b, int off, int len) {
   113         impl.setInput(b, off, len);
   114     }
   115 
   116     /**
   117      * Sets input data for decompression. Should be called whenever
   118      * needsInput() returns true indicating that more input data is
   119      * required.
   120      * @param b the input data bytes
   121      * @see Inflater#needsInput
   122      */
   123     public void setInput(byte[] b) {
   124         impl.setInput(b);
   125     }
   126 
   127     /**
   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
   137      */
   138     public void setDictionary(byte[] b, int off, int len) {
   139         impl.setDictionary(b, off, len);
   140     }
   141 
   142     /**
   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
   150      */
   151     public void setDictionary(byte[] b) {
   152         impl.setDictionary(b);
   153     }
   154 
   155     /**
   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
   160      */
   161     public int getRemaining() {
   162         return impl.getRemaining();
   163     }
   164 
   165     /**
   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
   170      */
   171     public boolean needsInput() {
   172         return impl.needsInput();
   173     }
   174 
   175     /**
   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
   179      */
   180     public boolean needsDictionary() {
   181         return impl.needsDictionary();
   182     }
   183 
   184     /**
   185      * Returns true if the end of the compressed data stream has been
   186      * reached.
   187      * @return true if the end of the compressed data stream has been
   188      * reached
   189      */
   190     public boolean finished() {
   191         return impl.finished();
   192     }
   193 
   194     /**
   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
   208      */
   209     public int inflate(byte[] b, int off, int len)
   210         throws DataFormatException
   211     {
   212         return impl.inflate(b, off, len);
   213     }
   214 
   215     /**
   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
   227      */
   228     public int inflate(byte[] b) throws DataFormatException {
   229         return impl.inflate(b);
   230     }
   231 
   232     /**
   233      * Returns the ADLER-32 value of the uncompressed data.
   234      * @return the ADLER-32 value of the uncompressed data
   235      */
   236     public int getAdler() {
   237         return impl.getAdler();
   238     }
   239 
   240     /**
   241      * Returns the total number of compressed bytes input so far.
   242      *
   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>
   246      *
   247      * @return the total number of compressed bytes input so far
   248      */
   249     public int getTotalIn() {
   250         return impl.getTotalIn();
   251     }
   252 
   253     /**
   254      * Returns the total number of compressed bytes input so far.</p>
   255      *
   256      * @return the total (non-negative) number of compressed bytes input so far
   257      * @since 1.5
   258      */
   259     public long getBytesRead() {
   260         return impl.getBytesRead();
   261     }
   262 
   263     /**
   264      * Returns the total number of uncompressed bytes output so far.
   265      *
   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>
   269      *
   270      * @return the total number of uncompressed bytes output so far
   271      */
   272     public int getTotalOut() {
   273         return impl.getTotalOut();
   274     }
   275 
   276     /**
   277      * Returns the total number of uncompressed bytes output so far.</p>
   278      *
   279      * @return the total (non-negative) number of uncompressed bytes output so far
   280      * @since 1.5
   281      */
   282     public long getBytesWritten() {
   283         return impl.getBytesWritten();
   284     }
   285 
   286     /**
   287      * Resets inflater so that a new set of input data can be processed.
   288      */
   289     public void reset() {
   290         impl.reset();
   291     }
   292 
   293     /**
   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.
   299      */
   300     public void end() {
   301         impl.end();
   302     }
   303 
   304     /**
   305      * Closes the decompressor when garbage is collected.
   306      */
   307     protected void finalize() {
   308         end();
   309     }
   310 }