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