blob: 19b681e4373a6f68bfa14f96ce5772e05f22e5d3 [file] [log] [blame]
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07001package android.content.pm;
2
Pete Gillin60f55a252018-05-10 15:40:32 +01003import libcore.util.ArrayUtils;
4
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005import java.io.FilterInputStream;
6import java.io.IOException;
7import java.io.InputStream;
8
9/**
10 * A class that limits the amount of data that is read from an InputStream. When
11 * the specified length is reached, the stream returns an EOF even if the
12 * underlying stream still has more data.
13 *
14 * @hide
15 */
16public class LimitedLengthInputStream extends FilterInputStream {
17 /**
18 * The end of the stream where we don't want to allow more data to be read.
19 */
Kenny Root103d5302012-05-10 10:21:06 -070020 private final long mEnd;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070021
22 /**
23 * Current offset in the stream.
24 */
Kenny Root103d5302012-05-10 10:21:06 -070025 private long mOffset;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070026
27 /**
28 * @param in underlying stream to wrap
29 * @param offset offset into stream where data starts
30 * @param length length of data at offset
Kenny Root103d5302012-05-10 10:21:06 -070031 * @throws IOException if an error occurred with the underlying stream
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070032 */
Kenny Root103d5302012-05-10 10:21:06 -070033 public LimitedLengthInputStream(InputStream in, long offset, long length) throws IOException {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070034 super(in);
35
36 if (in == null) {
37 throw new IOException("in == null");
38 }
39
40 if (offset < 0) {
Kenny Root103d5302012-05-10 10:21:06 -070041 throw new IOException("offset < 0");
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070042 }
43
44 if (length < 0) {
Kenny Root103d5302012-05-10 10:21:06 -070045 throw new IOException("length < 0");
46 }
47
48 if (length > Long.MAX_VALUE - offset) {
49 throw new IOException("offset + length > Long.MAX_VALUE");
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070050 }
51
52 mEnd = offset + length;
53
54 skip(offset);
55 mOffset = offset;
56 }
57
58 @Override
59 public synchronized int read() throws IOException {
60 if (mOffset >= mEnd) {
61 return -1;
62 }
63
64 mOffset++;
65 return super.read();
66 }
67
68 @Override
69 public int read(byte[] buffer, int offset, int byteCount) throws IOException {
70 if (mOffset >= mEnd) {
71 return -1;
72 }
73
Kenny Root103d5302012-05-10 10:21:06 -070074 final int arrayLength = buffer.length;
Pete Gillin60f55a252018-05-10 15:40:32 +010075 ArrayUtils.throwsIfOutOfBounds(arrayLength, offset, byteCount);
Kenny Root103d5302012-05-10 10:21:06 -070076
77 if (mOffset > Long.MAX_VALUE - byteCount) {
78 throw new IOException("offset out of bounds: " + mOffset + " + " + byteCount);
79 }
80
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070081 if (mOffset + byteCount > mEnd) {
Kenny Root103d5302012-05-10 10:21:06 -070082 byteCount = (int) (mEnd - mOffset);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070083 }
84
85 final int numRead = super.read(buffer, offset, byteCount);
86 mOffset += numRead;
87
88 return numRead;
89 }
90
91 @Override
92 public int read(byte[] buffer) throws IOException {
93 return read(buffer, 0, buffer.length);
94 }
95}