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.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream;
226186821cb13f4ac7ff50950c813394367e021eaeJesse Wilsonimport libcore.io.Streams;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The {@code CheckedInputStream} class is used to maintain a checksum at the
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * same time as the data, on which the checksum is computed, is read from a
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * stream. The purpose of this checksum is to establish data integrity,
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * comparing the computed checksum against a published checksum value.
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class CheckedInputStream extends java.io.FilterInputStream {
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final Checksum check;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code CheckedInputStream} on {@code InputStream}
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code is}. The checksum will be calculated using the algorithm
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * implemented by {@code csum}.
38f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson     *
39858dd42310622fd1b77bfa0fbd85ec851b3925c1Jesse Wilson     * <p><strong>Warning:</strong> passing a null source creates an invalid
40858dd42310622fd1b77bfa0fbd85ec851b3925c1Jesse Wilson     * {@code CheckedInputStream}. All operations on such a stream will fail.
41858dd42310622fd1b77bfa0fbd85ec851b3925c1Jesse Wilson     *
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param is
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the input stream to calculate checksum from.
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param csum
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            an entity implementing the checksum algorithm.
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public CheckedInputStream(InputStream is, Checksum csum) {
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(is);
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        check = csum;
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads one byte of data from the underlying input stream and updates the
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * checksum with the byte data.
55f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson     *
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code -1} at the end of the stream, a single byte value
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an {@code IOException} occurs.
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int read() throws IOException {
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int x = in.read();
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (x != -1) {
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            check.update(x);
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return x;
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
71325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes     * Reads up to {@code byteCount} bytes of data from the underlying input stream, storing it
72325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes     * into {@code buffer}, starting at offset {@code byteOffset}. The checksum is
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * updated with the bytes read.
74325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes     * Returns the number of bytes actually read or {@code -1} if arrived at the
75325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes     * end of the filtered stream while reading the data.
76f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson     *
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this stream is closed or some I/O error occurs.
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
81325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
82325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes        int bytesRead = in.read(buffer, byteOffset, byteCount);
83325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes        if (bytesRead != -1) {
84325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes            check.update(buffer, byteOffset, bytesRead);
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
86325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes        return bytesRead;
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the checksum calculated on the stream read so far.
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Checksum getChecksum() {
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return check;
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
9780b486724ca19b3c1c3c36334d06856330362f83Jesse Wilson     * Skip up to {@code byteCount} bytes of data on the underlying input
9880b486724ca19b3c1c3c36334d06856330362f83Jesse Wilson     * stream. Any skipped bytes are added to the running checksum value.
99f7c6911047d63bc76292f55ce538da32818dd931Jesse Wilson     *
10080b486724ca19b3c1c3c36334d06856330362f83Jesse Wilson     * @param byteCount the number of bytes to skip.
10180b486724ca19b3c1c3c36334d06856330362f83Jesse Wilson     * @throws IOException if this stream is closed or another I/O error occurs.
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes skipped.
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
10580b486724ca19b3c1c3c36334d06856330362f83Jesse Wilson    public long skip(long byteCount) throws IOException {
10680b486724ca19b3c1c3c36334d06856330362f83Jesse Wilson        return Streams.skipByReading(this, byteCount);
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
109