InflaterInputStream.java revision 60eb73fc9f0636c3d0bda5baba641a5f88f8476f
1f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License.  You may obtain a copy of the License at
8f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util.zip;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.EOFException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FilterInputStream;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.archive.internal.nls.Messages;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class provides an implementation of {@code FilterInputStream} that
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * uncompresses data that was compressed using the <i>DEFLATE</i> algorithm
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (see <a href="http://www.gzip.org/algorithm.txt">specification</a>).
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Basically it wraps the {@code Inflater} class and takes care of the
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffering.
3357995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson *
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see Inflater
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see DeflaterOutputStream
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class InflaterInputStream extends FilterInputStream {
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The inflater used for this stream.
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected Inflater inf;
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The input buffer used for decompression.
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected byte[] buf;
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The length of the buffer.
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected int len;
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    boolean closed;
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
560146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson    /**
570146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * True if this stream's last byte has been returned to the user. This
580146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * could be because the underlying stream has been exhausted, or if errors
590146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * were encountered while inflating that stream.
600146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     */
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    boolean eof;
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static final int BUF_SIZE = 512;
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
65f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson    int nativeEndBufSize = 0; // android-only
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This is the most basic constructor. You only need to pass the {@code
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * InputStream} from which the compressed data is to be read from. Default
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * settings for the {@code Inflater} and internal buffer are be used. In
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * particular the Inflater expects a ZLIB header from the input stream.
7257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param is
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code InputStream} to read data from.
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InflaterInputStream(InputStream is) {
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(is, new Inflater(), BUF_SIZE);
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This constructor lets you pass a specifically initialized Inflater,
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for example one that expects no ZLIB header.
8357995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param is
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code InputStream} to read data from.
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inf
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the specific {@code Inflater} for uncompressing data.
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InflaterInputStream(InputStream is, Inflater inf) {
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(is, inf, BUF_SIZE);
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This constructor lets you specify both the {@code Inflater} as well as
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the internal buffer size to be used.
9657995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param is
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code InputStream} to read data from.
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param inf
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the specific {@code Inflater} for uncompressing data.
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param bsize
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the size to be used for the internal buffer.
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InflaterInputStream(InputStream is, Inflater inf, int bsize) {
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(is);
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (is == null || inf == null) {
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new NullPointerException();
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (bsize <= 0) {
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.inf = inf;
113f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson        // BEGIN android-only
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (is instanceof ZipFile.RAFStream) {
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nativeEndBufSize = bsize;
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            buf = new byte[bsize];
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
119f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson        // END android-only
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads a single byte of decompressed data.
12457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the byte read.
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs reading the byte.
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read() throws IOException {
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] b = new byte[1];
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (read(b, 0, 1) == -1) {
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return -1;
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return b[0] & 0xff;
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads up to {@code nbytes} of decompressed data and stores it in
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code buffer} starting at {@code off}.
14157995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param buffer
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the buffer to write data to.
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param off
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            offset in buffer to start writing.
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param nbytes
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            number of bytes to read.
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return Number of uncompressed bytes read
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an IOException occurs.
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read(byte[] buffer, int off, int nbytes) throws IOException {
15460eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        checkClosed();
15560eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        if (buffer == null) {
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new NullPointerException();
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (off < 0 || nbytes < 0 || off + nbytes > buffer.length) {
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IndexOutOfBoundsException();
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (nbytes == 0) {
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1670146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson        if (eof) {
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return -1;
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // avoid int overflow, check null buffer
1720146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson        if (off > buffer.length || nbytes < 0 || off < 0
1730146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                || buffer.length - off < nbytes) {
1740146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            throw new ArrayIndexOutOfBoundsException();
1750146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson        }
1760146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson
1770146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson        do {
1780146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            if (inf.needsInput()) {
1790146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                fill();
1800146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            }
1810146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            // Invariant: if reading returns -1 or throws, eof must be true.
1820146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            // It may also be true if the next read() should return -1.
1830146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            try {
1840146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                int result = inf.inflate(buffer, off, nbytes);
1850146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                eof = inf.finished();
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (result > 0) {
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return result;
1880146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                } else if (eof) {
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return -1;
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (inf.needsDictionary()) {
1910146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                    eof = true;
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return -1;
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (len == -1) {
1940146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                    eof = true;
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new EOFException();
19657995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson                    // If result == 0, fill() and try again
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1980146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            } catch (DataFormatException e) {
1990146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                eof = true;
2000146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                if (len == -1) {
2010146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                    throw new EOFException();
2020146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                }
2030146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                throw (IOException) (new IOException().initCause(e));
2040146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            }
2050146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson        } while (true);
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Fills the input buffer with data to be decompressed.
21057995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an {@code IOException} occurs.
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void fill() throws IOException {
21560eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        checkClosed();
216f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson        // BEGIN android-only
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (nativeEndBufSize > 0) {
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ZipFile.RAFStream is = (ZipFile.RAFStream)in;
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized (is.mSharedRaf) {
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                long len = is.mLength - is.mOffset;
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (len > nativeEndBufSize) len = nativeEndBufSize;
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int cnt = inf.setFileInput(is.mSharedRaf.getFD(), is.mOffset, (int)nativeEndBufSize);
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                is.skip(cnt);
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ((len = in.read(buf)) > 0) {
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                inf.setInput(buf, 0, len);
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
230f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson        // END android-only
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Skips up to n bytes of uncompressed data.
23557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param nbytes
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the number of bytes to skip.
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of uncompressed bytes skipped.
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs skipping.
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public long skip(long nbytes) throws IOException {
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (nbytes >= 0) {
24557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson            if (buf == null) {
246f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson                buf = new byte[(int)Math.min(nbytes, BUF_SIZE)];
24757995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson            }
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long count = 0, rem = 0;
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (count < nbytes) {
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int x = read(buf, 0,
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        (rem = nbytes - count) > buf.length ? buf.length
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                : (int) rem);
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (x == -1) {
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return count;
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                count += x;
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return count;
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new IllegalArgumentException();
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
2640146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * Returns 0 when when this stream has exhausted its input; and 1 otherwise.
2650146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * A result of 1 does not guarantee that further bytes can be returned,
2660146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * with or without blocking.
2670146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     *
2680146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * <p>Although consistent with the RI, this behavior is inconsistent with
2690146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * {@link InputStream#available()}, and violates the <a
2700146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * href="http://en.wikipedia.org/wiki/Liskov_substitution_principle">Liskov
2710146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * Substitution Principle</a>. This method should not be used.
27257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
2730146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * @return 0 if no further bytes are available. Otherwise returns 1,
2740146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     *         which suggests (but does not guarantee) that additional bytes are
2750146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     *         available.
276582d926fbf5f5fd4800def67f86ecfedee44681eElliott Hughes     * @throws IOException if this stream is closed or an error occurs
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int available() throws IOException {
28060eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        checkClosed();
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (eof) {
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return 1;
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the input stream.
28957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             If an error occurs closing the input stream.
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!closed) {
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            inf.end();
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            closed = true;
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            eof = true;
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            super.close();
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
30257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
30457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     * Marks the current position in the stream. This implementation overrides
30557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     * the super type implementation to do nothing at all.
30657995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param readlimit
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            of no use.
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void mark(int readlimit) {
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // do nothing
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reset the position of the stream to the last marked position. This
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * implementation overrides the supertype implementation and always throws
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * an {@link IOException IOException} when called.
31957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the method is called
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
32457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson    public void reset() throws IOException {
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new IOException();
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
32757995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether the receiver implements {@code mark} semantics. This type
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * does not support {@code mark()}, so always responds {@code false}.
33157995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return false, always
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean markSupported() {
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
33960eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes    private void checkClosed() throws IOException {
34060eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        if (closed) {
34160eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes            throw new IOException("Stream is closed");
34260eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        }
34360eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes    }
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
345