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;
24b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughesimport java.util.Arrays;
256186821cb13f4ac7ff50950c813394367e021eaeJesse Wilsonimport libcore.io.Streams;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class provides an implementation of {@code FilterInputStream} that
298cfafd33742282beb20c6971aafc1feb35e3fa5eJesse Wilson * decompresses 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
65fb0ec0e650bf8be35acb0d47da0311a7c446aa33Elliott Hughes    int nativeEndBufSize = 0;
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.
86018b67accb28954d35f3cd697be3428e9b45b7d8Jesse Wilson     * @param inflater
878cfafd33742282beb20c6971aafc1feb35e3fa5eJesse Wilson     *            the specific {@code Inflater} for decompressing data.
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
89018b67accb28954d35f3cd697be3428e9b45b7d8Jesse Wilson    public InflaterInputStream(InputStream is, Inflater inflater) {
90018b67accb28954d35f3cd697be3428e9b45b7d8Jesse Wilson        this(is, inflater, 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.
99018b67accb28954d35f3cd697be3428e9b45b7d8Jesse Wilson     * @param inflater
1008cfafd33742282beb20c6971aafc1feb35e3fa5eJesse Wilson     *            the specific {@code Inflater} for decompressing data.
101cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes     * @param bufferSize
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the size to be used for the internal buffer.
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
104cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes    public InflaterInputStream(InputStream is, Inflater inflater, int bufferSize) {
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(is);
10686acc043d3334651ee26c65467d78d6cefedd397Kenny Root        if (is == null) {
10786acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("is == null");
10886acc043d3334651ee26c65467d78d6cefedd397Kenny Root        } else if (inflater == null) {
10986acc043d3334651ee26c65467d78d6cefedd397Kenny Root            throw new NullPointerException("inflater == null");
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
111cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes        if (bufferSize <= 0) {
112cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes            throw new IllegalArgumentException("bufferSize <= 0: " + bufferSize);
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
114018b67accb28954d35f3cd697be3428e9b45b7d8Jesse Wilson        this.inf = inflater;
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (is instanceof ZipFile.RAFStream) {
116cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes            nativeEndBufSize = bufferSize;
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
118cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes            buf = new byte[bufferSize];
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
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     */
129ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes    @Override public int read() throws IOException {
130ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes        return Streams.readSingleByte(this);
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
134b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughes     * Reads up to {@code byteCount} bytes of decompressed data and stores it in
135325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes     * {@code buffer} starting at {@code byteOffset}. Returns the number of uncompressed bytes read,
136325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes     * or -1.
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
139325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
14060eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        checkClosed();
141325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
143b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughes        if (byteCount == 0) {
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1470146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson        if (eof) {
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return -1;
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1510146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson        do {
1520146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            if (inf.needsInput()) {
1530146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                fill();
1540146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            }
1550146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            // Invariant: if reading returns -1 or throws, eof must be true.
1560146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            // It may also be true if the next read() should return -1.
1570146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            try {
158325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes                int result = inf.inflate(buffer, byteOffset, byteCount);
1590146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                eof = inf.finished();
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (result > 0) {
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return result;
1620146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                } else if (eof) {
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return -1;
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (inf.needsDictionary()) {
1650146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                    eof = true;
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return -1;
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (len == -1) {
1680146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                    eof = true;
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new EOFException();
17057995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson                    // If result == 0, fill() and try again
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1720146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            } catch (DataFormatException e) {
1730146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                eof = true;
1740146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                if (len == -1) {
1750146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                    throw new EOFException();
1760146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                }
1770146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson                throw (IOException) (new IOException().initCause(e));
1780146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson            }
1790146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson        } while (true);
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Fills the input buffer with data to be decompressed.
18457995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an {@code IOException} occurs.
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void fill() throws IOException {
18960eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        checkClosed();
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (nativeEndBufSize > 0) {
19113f30b9167639ad63da1707102db6320e8f76474Elliott Hughes            ZipFile.RAFStream is = (ZipFile.RAFStream) in;
19213f30b9167639ad63da1707102db6320e8f76474Elliott Hughes            len = is.fill(inf, nativeEndBufSize);
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ((len = in.read(buf)) > 0) {
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                inf.setInput(buf, 0, len);
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
2013541c79d5058b86e742867b4ee5811a1de01de1fJesse Wilson     * Skips up to {@code byteCount} bytes of uncompressed data.
20257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
2033541c79d5058b86e742867b4ee5811a1de01de1fJesse Wilson     * @param byteCount the number of bytes to skip.
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of uncompressed bytes skipped.
205f9480f317cddcec859025833b748f096247a40aaElliott Hughes     * @throws IllegalArgumentException if {@code byteCount < 0}.
2063541c79d5058b86e742867b4ee5811a1de01de1fJesse Wilson     * @throws IOException if an error occurs skipping.
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
2093541c79d5058b86e742867b4ee5811a1de01de1fJesse Wilson    public long skip(long byteCount) throws IOException {
210f9480f317cddcec859025833b748f096247a40aaElliott Hughes        if (byteCount < 0) {
211f9480f317cddcec859025833b748f096247a40aaElliott Hughes            throw new IllegalArgumentException("byteCount < 0");
212f9480f317cddcec859025833b748f096247a40aaElliott Hughes        }
2133541c79d5058b86e742867b4ee5811a1de01de1fJesse Wilson        return Streams.skipByReading(this, byteCount);
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
2170146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * Returns 0 when when this stream has exhausted its input; and 1 otherwise.
2180146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * A result of 1 does not guarantee that further bytes can be returned,
2190146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * with or without blocking.
2200146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     *
2210146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * <p>Although consistent with the RI, this behavior is inconsistent with
2220146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * {@link InputStream#available()}, and violates the <a
2230146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * href="http://en.wikipedia.org/wiki/Liskov_substitution_principle">Liskov
2240146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * Substitution Principle</a>. This method should not be used.
22557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
2260146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     * @return 0 if no further bytes are available. Otherwise returns 1,
2270146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     *         which suggests (but does not guarantee) that additional bytes are
2280146d778677790cf6aee98fbb8a5e7d24eb023a4Jesse Wilson     *         available.
229582d926fbf5f5fd4800def67f86ecfedee44681eElliott Hughes     * @throws IOException if this stream is closed or an error occurs
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int available() throws IOException {
23360eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        checkClosed();
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (eof) {
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return 0;
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return 1;
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the input stream.
24257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             If an error occurs closing the input stream.
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!closed) {
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            inf.end();
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            closed = true;
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            eof = true;
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            super.close();
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
25557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
25757995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     * Marks the current position in the stream. This implementation overrides
25857995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     * the super type implementation to do nothing at all.
25957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param readlimit
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            of no use.
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void mark(int readlimit) {
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // do nothing
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
269a98ba29c98e7941698ce79232b328ceaba07cbc1Elliott Hughes     * This operation is not supported and throws {@code IOException}.
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
27257995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson    public void reset() throws IOException {
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new IOException();
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
27557995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether the receiver implements {@code mark} semantics. This type
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * does not support {@code mark()}, so always responds {@code false}.
27957995e8186b54515d5a03bf2ab104c3dc247f1b6Jesse Wilson     *
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return false, always
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean markSupported() {
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
28760eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes    private void checkClosed() throws IOException {
28860eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        if (closed) {
28960eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes            throw new IOException("Stream is closed");
29060eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes        }
29160eb73fc9f0636c3d0bda5baba641a5f88f8476fElliott Hughes    }
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
293