1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.utils;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.nio.ByteBuffer;
24
25
26
27
28
29
30
31 public abstract class BoundedArchiveInputStream extends InputStream {
32
33 private final long end;
34 private ByteBuffer singleByteBuffer;
35 private long loc;
36
37
38
39
40
41
42
43 public BoundedArchiveInputStream(final long start, final long remaining) {
44 this.end = start + remaining;
45 if (this.end < start) {
46
47 throw new IllegalArgumentException("Invalid length of stream at offset=" + start + ", length=" + remaining);
48 }
49 loc = start;
50 }
51
52 @Override
53 public synchronized int read() throws IOException {
54 if (loc >= end) {
55 return -1;
56 }
57 if (singleByteBuffer == null) {
58 singleByteBuffer = ByteBuffer.allocate(1);
59 } else {
60 singleByteBuffer.rewind();
61 }
62 final int read = read(loc, singleByteBuffer);
63 if (read < 1) {
64 return -1;
65 }
66 loc++;
67 return singleByteBuffer.get() & 0xff;
68 }
69
70 @Override
71 public synchronized int read(final byte[] b, final int off, final int len) throws IOException {
72 if (loc >= end) {
73 return -1;
74 }
75 final long maxLen = Math.min(len, end - loc);
76 if (maxLen <= 0) {
77 return 0;
78 }
79 if (off < 0 || off > b.length || maxLen > b.length - off) {
80 throw new IndexOutOfBoundsException("offset or len are out of bounds");
81 }
82
83 final ByteBuffer buf = ByteBuffer.wrap(b, off, (int) maxLen);
84 final int ret = read(loc, buf);
85 if (ret > 0) {
86 loc += ret;
87 }
88 return ret;
89 }
90
91
92
93
94
95
96
97
98
99 protected abstract int read(long pos, ByteBuffer buf) throws IOException;
100 }