1ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey/*
2ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * Copyright (C) 2014 The Android Open Source Project
3ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey *
4ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * you may not use this file except in compliance with the License.
6ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * You may obtain a copy of the License at
7ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey *
8ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey *
10ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * See the License for the specific language governing permissions and
14ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * limitations under the License.
15ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey */
16ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
17ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeypackage com.android.internal.util;
18ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
19ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport libcore.io.Streams;
20ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
21ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.IOException;
22ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeyimport java.io.InputStream;
23ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
24ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey/**
25ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * Reads exact number of bytes from wrapped stream, returning EOF once those
26ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey * bytes have been read.
27ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey */
28ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkeypublic class SizedInputStream extends InputStream {
29ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    private final InputStream mWrapped;
30ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    private long mLength;
31ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
32ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    public SizedInputStream(InputStream wrapped, long length) {
33ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        mWrapped = wrapped;
34ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        mLength = length;
35ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    }
36ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
37ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    @Override
38ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    public void close() throws IOException {
39ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        super.close();
40ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        mWrapped.close();
41ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    }
42ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
43ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    @Override
44ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    public int read() throws IOException {
45ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        return Streams.readSingleByte(this);
46ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    }
47ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
48ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    @Override
49ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
50ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        if (mLength <= 0) {
51ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey            return -1;
52ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        } else if (byteCount > mLength) {
53ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey            byteCount = (int) mLength;
54ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        }
55ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey
56ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        final int n = mWrapped.read(buffer, byteOffset, byteCount);
57ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        if (n == -1) {
58ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey            if (mLength > 0) {
59ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey                throw new IOException("Unexpected EOF; expected " + mLength + " more bytes");
60ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey            }
61ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        } else {
62ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey            mLength -= n;
63ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        }
64ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey        return n;
65ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey    }
66ec55ef0934b8e0d1bb705434947de817f7be57f1Jeff Sharkey}
67