OSDN Git Service

PR libgcj/14446:
[pf3gnuchains/gcc-fork.git] / libjava / java / util / zip / InflaterInputStream.java
1 /* InflaterInputStream.java - Input stream filter for decompressing
2    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
3    Free Software Foundation, Inc.
4
5 This file is part of GNU Classpath.
6
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11  
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA.
21
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38
39 package java.util.zip;
40
41 import java.io.FilterInputStream;
42 import java.io.InputStream;
43 import java.io.IOException;
44
45 /**
46  * This filter stream is used to decompress data compressed in the "deflate"
47  * format. The "deflate" format is described in RFC 1951.
48  *
49  * This stream may form the basis for other decompression filters, such
50  * as the <code>GZIPInputStream</code>.
51  *
52  * @author John Leuner
53  * @author Tom Tromey
54  * @since 1.1
55  */
56 public class InflaterInputStream extends FilterInputStream
57 {
58   /**
59    * Decompressor for this filter 
60    */
61   protected Inflater inf;
62
63   /**
64    * Byte array used as a buffer 
65    */
66   protected byte[] buf;
67
68   /**
69    * Size of buffer   
70    */
71   protected int len;
72
73   // We just use this if we are decoding one byte at a time with the
74   // read() call.
75   private byte[] onebytebuffer = new byte[1];
76
77   /**
78    * Create an InflaterInputStream with the default decompresseor
79    * and a default buffer size.
80    *
81    * @param in the InputStream to read bytes from
82    */
83   public InflaterInputStream(InputStream in) 
84   {
85     this(in, new Inflater(), 4096);
86   }
87
88   /**
89    * Create an InflaterInputStream with the specified decompresseor
90    * and a default buffer size.
91    *
92    * @param in the InputStream to read bytes from
93    * @param inf the decompressor used to decompress data read from in
94    */
95   public InflaterInputStream(InputStream in, Inflater inf) 
96   {
97     this(in, inf, 4096);
98   }
99
100   /**
101    * Create an InflaterInputStream with the specified decompresseor
102    * and a specified buffer size.
103    *
104    * @param in the InputStream to read bytes from
105    * @param inf the decompressor used to decompress data read from in
106    * @param size size of the buffer to use
107    */
108   public InflaterInputStream(InputStream in, Inflater inf, int size) 
109   {
110     super(in);
111
112     if (in == null)
113       throw new NullPointerException("in may not be null");
114     if (inf == null)
115       throw new NullPointerException("inf may not be null");
116     if (size < 0)
117       throw new IllegalArgumentException("size may not be negative");
118     
119     this.inf = inf;
120     this.buf = new byte [size];
121   }
122
123   /**
124    * Returns 0 once the end of the stream (EOF) has been reached.
125    * Otherwise returns 1.
126    */
127   public int available() throws IOException
128   {
129     // According to the JDK 1.2 docs, this should only ever return 0
130     // or 1 and should not be relied upon by Java programs.
131     if (inf == null)
132       throw new IOException("stream closed");
133     return inf.finished() ? 0 : 1;
134   }
135
136   /**
137    * Closes the input stream
138    */
139   public synchronized void close() throws IOException
140   {
141     inf = null;
142     super.close();
143   }
144
145   /**
146    * Fills the buffer with more data to decompress.
147    */
148   protected void fill() throws IOException
149   {
150     if (in == null)
151       throw new ZipException ("InflaterInputStream is closed");
152     
153     len = in.read(buf, 0, buf.length);
154
155     if (len < 0)
156       throw new ZipException("Deflated stream ends early.");
157     
158     inf.setInput(buf, 0, len);
159   }
160
161   /**
162    * Reads one byte of decompressed data.
163    *
164    * The byte is in the lower 8 bits of the int.
165    */
166   public int read() throws IOException
167   { 
168     int nread = read(onebytebuffer, 0, 1);
169     if (nread > 0)
170       return onebytebuffer[0] & 0xff;
171     return -1;
172   }
173
174   /**
175    * Decompresses data into the byte array
176    *
177    * @param b the array to read and decompress data into
178    * @param off the offset indicating where the data should be placed
179    * @param len the number of bytes to decompress
180    */
181   public int read(byte[] b, int off, int len) throws IOException
182   {
183     if (inf == null)
184       throw new IOException("stream closed");
185     if (len == 0)
186       return 0;
187     if (inf.finished())
188       return -1;
189
190     int count = 0;
191     for (;;)
192       {
193         if (inf.needsInput())
194           fill();
195         
196         try
197           {
198             count = inf.inflate(b, off, len);
199             if (count == 0)
200               {
201                 if (this.len == -1)
202                   {
203                     // Couldn't get any more data to feed to the Inflater
204                     return -1;
205                   }
206                 if (inf.needsDictionary())
207                   throw new ZipException("Inflater needs Dictionary");
208               }
209           } 
210         catch (DataFormatException dfe) 
211           {
212             throw new ZipException(dfe.getMessage());
213           }
214
215         if (count > 0)
216           return count;
217       }
218   }
219
220   /**
221    * Skip specified number of bytes of uncompressed data
222    *
223    * @param n number of bytes to skip
224    */
225   public long skip(long n) throws IOException
226   {
227     if (inf == null)
228       throw new IOException("stream closed");
229     if (n < 0)
230       throw new IllegalArgumentException();
231
232     if (n == 0)
233       return 0;
234
235     int buflen = (int) Math.min(n, 2048);
236     byte[] tmpbuf = new byte[buflen];
237
238     long skipped = 0L;
239     while (n > 0L)
240       {
241         int numread = read(tmpbuf, 0, buflen);
242         if (numread <= 0)
243           break;
244         n -= numread;
245         skipped += numread;
246         buflen = (int) Math.min(n, 2048);
247       }
248
249     return skipped;
250  }
251 }