151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.util.zip;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.FilterInputStream;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InputStream;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Implements an input stream filter for compressing data in the "deflate"
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * compression format.
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since       1.6
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author      David R Tribble (david@tribble.com)
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see DeflaterOutputStream
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see InflaterOutputStream
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see InflaterInputStream
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class DeflaterInputStream extends FilterInputStream {
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Compressor for this stream. */
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected final Deflater def;
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Input buffer for reading compressed data. */
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected final byte[] buf;
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Temporary read buffer. */
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private byte[] rbuf = new byte[1];
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Default compressor is used. */
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean usesDefaultDeflater = false;
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** End of the underlying input stream has been reached. */
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean reachEOF = false;
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Check to make sure that this stream has not been closed.
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void ensureOpen() throws IOException {
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (in == null) {
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Stream closed");
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a new input stream with a default compressor and buffer
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * size.
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param in input stream to read the uncompressed data to
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if {@code in} is null
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DeflaterInputStream(InputStream in) {
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(in, new Deflater());
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        usesDefaultDeflater = true;
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a new input stream with the specified compressor and a
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * default buffer size.
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param in input stream to read the uncompressed data to
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param defl compressor ("deflater") for this stream
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if {@code in} or {@code defl} is null
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DeflaterInputStream(InputStream in, Deflater defl) {
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(in, defl, 512);
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a new input stream with the specified compressor and buffer
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * size.
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param in input stream to read the uncompressed data to
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param defl compressor ("deflater") for this stream
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param bufLen compression buffer size
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IllegalArgumentException if {@code bufLen} is <= 0
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws NullPointerException if {@code in} or {@code defl} is null
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DeflaterInputStream(InputStream in, Deflater defl, int bufLen) {
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        super(in);
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Sanity checks
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (in == null)
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("Null input");
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (defl == null)
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("Null deflater");
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bufLen < 1)
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("Buffer size < 1");
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Initialize
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        def = defl;
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        buf = new byte[bufLen];
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Closes this input stream and its underlying input stream, discarding
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * any pending uncompressed data.
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IOException if an I/O error occurs
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void close() throws IOException {
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (in != null) {
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Clean up
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (usesDefaultDeflater) {
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    def.end();
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in.close();
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } finally {
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in = null;
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads a single byte of compressed data from the input stream.
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method will block until some input can be read and compressed.
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a single byte of compressed data, or -1 if the end of the
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * uncompressed input stream is reached
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IOException if an I/O error occurs or if this stream is
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * already closed
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int read() throws IOException {
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Read a single byte of compressed data
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int len = read(rbuf, 0, 1);
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (len <= 0)
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return -1;
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (rbuf[0] & 0xFF);
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads compressed data into a byte array.
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method will block until some input can be read and compressed.
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param b buffer into which the data is read
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param off starting offset of the data within {@code b}
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param len maximum number of compressed bytes to read into {@code b}
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the actual number of bytes read, or -1 if the end of the
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * uncompressed input stream is reached
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IndexOutOfBoundsException  if {@code len} > {@code b.length -
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * off}
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IOException if an I/O error occurs or if this input stream is
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * already closed
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int read(byte[] b, int off, int len) throws IOException {
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Sanity checks
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ensureOpen();
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (b == null) {
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException("Null buffer for read");
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (off < 0 || len < 0 || len > b.length - off) {
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IndexOutOfBoundsException();
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (len == 0) {
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0;
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Read and compress (deflate) input data bytes
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int cnt = 0;
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (len > 0 && !def.finished()) {
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n;
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Read data from the input stream
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (def.needsInput()) {
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                n = in.read(buf, 0, buf.length);
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (n < 0) {
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // End of the input stream reached
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    def.finish();
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (n > 0) {
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    def.setInput(buf, 0, n);
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Compress the input data, filling the read buffer
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n = def.deflate(b, off, len);
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cnt += n;
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            off += n;
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            len -= n;
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
205457d3b26a6cbd62d203d3b56f69bcc441ea8d66fNarayan Kamath
206457d3b26a6cbd62d203d3b56f69bcc441ea8d66fNarayan Kamath        // Android changed : set reachEOF eagerly (not just when the number of bytes is zero).
207457d3b26a6cbd62d203d3b56f69bcc441ea8d66fNarayan Kamath        // so that available is more accurate.
208457d3b26a6cbd62d203d3b56f69bcc441ea8d66fNarayan Kamath        if (def.finished()) {
209457d3b26a6cbd62d203d3b56f69bcc441ea8d66fNarayan Kamath            reachEOF =true;
210457d3b26a6cbd62d203d3b56f69bcc441ea8d66fNarayan Kamath            if (cnt == 0) {
211457d3b26a6cbd62d203d3b56f69bcc441ea8d66fNarayan Kamath                cnt = -1;
212457d3b26a6cbd62d203d3b56f69bcc441ea8d66fNarayan Kamath            }
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return cnt;
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Skips over and discards data from the input stream.
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method may block until the specified number of bytes are read and
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * skipped. <em>Note:</em> While {@code n} is given as a {@code long},
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the maximum number of bytes which can be skipped is
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@code Integer.MAX_VALUE}.
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param n number of bytes to be skipped
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the actual number of bytes skipped
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IOException if an I/O error occurs or if this stream is
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * already closed
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public long skip(long n) throws IOException {
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (n < 0) {
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("negative skip length");
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ensureOpen();
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Skip bytes by repeatedly decompressing small blocks
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (rbuf.length < 512)
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            rbuf = new byte[512];
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int total = (int)Math.min(n, Integer.MAX_VALUE);
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long cnt = 0;
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (total > 0) {
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Read a small block of uncompressed bytes
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int len = read(rbuf, 0, (total <= rbuf.length ? total : rbuf.length));
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (len < 0) {
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cnt += len;
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            total -= len;
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return cnt;
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns 0 after EOF has been reached, otherwise always return 1.
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Programs should not count on this method to return the actual number
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * of bytes that could be read without blocking
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return zero after the end of the underlying input stream has been
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * reached, otherwise always returns 1
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IOException if an I/O error occurs or if this stream is
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * already closed
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int available() throws IOException {
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ensureOpen();
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (reachEOF) {
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0;
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return 1;
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Always returns {@code false} because this input stream does not support
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the {@link #mark mark()} and {@link #reset reset()} methods.
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return false, always
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean markSupported() {
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <i>This operation is not supported</i>.
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param limit maximum bytes that can be read before invalidating the position marker
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void mark(int limit) {
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Operation not supported
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <i>This operation is not supported</i>.
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IOException always thrown
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void reset() throws IOException {
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throw new IOException("mark/reset not supported");
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
301