OSDN Git Service

27c29ff41dfd4dac0a70330ebf76a1ce0c68811c
[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
74   /**
75    * Create an InflaterInputStream with the default decompresseor
76    * and a default buffer size.
77    *
78    * @param in the InputStream to read bytes from
79    */
80   public InflaterInputStream(InputStream in) 
81   {
82     this(in, new Inflater(), 4096);
83   }
84
85   /**
86    * Create an InflaterInputStream with the specified decompresseor
87    * and a default buffer size.
88    *
89    * @param in the InputStream to read bytes from
90    * @param inf the decompressor used to decompress data read from in
91    */
92   public InflaterInputStream(InputStream in, Inflater inf) 
93   {
94     this(in, inf, 4096);
95   }
96
97   /**
98    * Create an InflaterInputStream with the specified decompresseor
99    * and a specified buffer size.
100    *
101    * @param in the InputStream to read bytes from
102    * @param inf the decompressor used to decompress data read from in
103    * @param size size of the buffer to use
104    */
105   public InflaterInputStream(InputStream in, Inflater inf, int size) 
106   {
107     super(in);
108
109     if (in == null)
110       throw new NullPointerException("in may not be null");
111     if (inf == null)
112       throw new NullPointerException("inf may not be null");
113     if (size < 0)
114       throw new IllegalArgumentException("size may not be negative");
115     
116     this.inf = inf;
117     this.buf = new byte [size];
118   }
119
120   /**
121    * Returns 0 once the end of the stream (EOF) has been reached.
122    * Otherwise returns 1.
123    */
124   public int available() throws IOException
125   {
126     // According to the JDK 1.2 docs, this should only ever return 0
127     // or 1 and should not be relied upon by Java programs.
128     if (inf == null)
129       throw new IOException("stream closed");
130     return inf.finished() ? 0 : 1;
131   }
132
133   /**
134    * Closes the input stream
135    */
136   public synchronized void close() throws IOException
137   {
138     inf = null;
139     super.close();
140   }
141
142   /**
143    * Fills the buffer with more data to decompress.
144    */
145   protected void fill() throws IOException
146   {
147     if (in == null)
148       throw new ZipException ("InflaterInputStream is closed");
149     
150     len = in.read(buf, 0, buf.length);
151
152     if (len < 0)
153       throw new ZipException("Deflated stream ends early.");
154     
155     inf.setInput(buf, 0, len);
156   }
157
158   /**
159    * Decompresses data into the byte array
160    *
161    * @param b the array to read and decompress data into
162    * @param off the offset indicating where the data should be placed
163    * @param len the number of bytes to decompress
164    */
165   public int read(byte[] b, int off, int len) throws IOException
166   {
167     if (inf == null)
168       throw new IOException("stream closed");
169     if (len == 0)
170       return 0;
171     if (inf.finished())
172       return -1;
173
174     int count = 0;
175     for (;;)
176       {
177         if (inf.needsInput())
178           fill();
179         
180         try
181           {
182             count = inf.inflate(b, off, len);
183             if (count == 0)
184               {
185                 if (this.len == -1)
186                   {
187                     // Couldn't get any more data to feed to the Inflater
188                     return -1;
189                   }
190                 if (inf.needsDictionary())
191                   throw new ZipException("Inflater needs Dictionary");
192               }
193           } 
194         catch (DataFormatException dfe) 
195           {
196             throw new ZipException(dfe.getMessage());
197           }
198
199         if (count > 0)
200           return count;
201       }
202   }
203
204   /**
205    * Skip specified number of bytes of uncompressed data
206    *
207    * @param n number of bytes to skip
208    */
209   public long skip(long n) throws IOException
210   {
211     if (inf == null)
212       throw new IOException("stream closed");
213     if (n < 0)
214       throw new IllegalArgumentException();
215
216     if (n == 0)
217       return 0;
218
219     int buflen = (int) Math.min(n, 2048);
220     byte[] tmpbuf = new byte[buflen];
221
222     long skipped = 0L;
223     while (n > 0L)
224       {
225         int numread = read(tmpbuf, 0, buflen);
226         if (numread <= 0)
227           break;
228         n -= numread;
229         skipped += numread;
230         buflen = (int) Math.min(n, 2048);
231       }
232
233     return skipped;
234  }
235 }