1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io.input;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.util.Objects;
23
24 import org.apache.commons.io.build.AbstractOrigin;
25 import org.apache.commons.io.build.AbstractStreamBuilder;
26
27
28
29
30
31
32
33
34
35
36
37
38
39 public class UnsynchronizedByteArrayInputStream extends InputStream {
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 public static class Builder extends AbstractStreamBuilder<UnsynchronizedByteArrayInputStream, Builder> {
83
84 private int offset;
85 private int length;
86
87
88
89
90 public Builder() {
91
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 @Override
116 public UnsynchronizedByteArrayInputStream get() throws IOException {
117 return new UnsynchronizedByteArrayInputStream(checkOrigin().getByteArray(), offset, length);
118 }
119
120 @Override
121 public Builder setByteArray(final byte[] origin) {
122 length = Objects.requireNonNull(origin, "origin").length;
123 return super.setByteArray(origin);
124 }
125
126
127
128
129
130
131
132 public Builder setLength(final int length) {
133 if (length < 0) {
134 throw new IllegalArgumentException("length cannot be negative");
135 }
136 this.length = length;
137 return this;
138 }
139
140
141
142
143
144
145
146 public Builder setOffset(final int offset) {
147 if (offset < 0) {
148 throw new IllegalArgumentException("offset cannot be negative");
149 }
150 this.offset = offset;
151 return this;
152 }
153
154 }
155
156
157
158
159 public static final int END_OF_STREAM = -1;
160
161
162
163
164
165
166 public static Builder builder() {
167 return new Builder();
168 }
169
170 private static int minPosLen(final byte[] data, final int defaultValue) {
171 requireNonNegative(defaultValue, "defaultValue");
172 return Math.min(defaultValue, data.length > 0 ? data.length : defaultValue);
173 }
174
175 private static int requireNonNegative(final int value, final String name) {
176 if (value < 0) {
177 throw new IllegalArgumentException(name + " cannot be negative");
178 }
179 return value;
180 }
181
182
183
184
185 private final byte[] data;
186
187
188
189
190
191
192 private final int eod;
193
194
195
196
197 private int offset;
198
199
200
201
202 private int markedOffset;
203
204
205
206
207
208
209
210 @Deprecated
211 public UnsynchronizedByteArrayInputStream(final byte[] data) {
212 this(data, data.length, 0, 0);
213 }
214
215
216
217
218
219
220
221
222
223 @Deprecated
224 public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset) {
225 this(data, data.length, Math.min(requireNonNegative(offset, "offset"), minPosLen(data, offset)), minPosLen(data, offset));
226 }
227
228
229
230
231
232
233
234
235
236
237 @Deprecated
238 public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset, final int length) {
239 requireNonNegative(offset, "offset");
240 requireNonNegative(length, "length");
241 this.data = Objects.requireNonNull(data, "data");
242 this.eod = Math.min(minPosLen(data, offset) + length, data.length);
243 this.offset = minPosLen(data, offset);
244 this.markedOffset = minPosLen(data, offset);
245 }
246
247 private UnsynchronizedByteArrayInputStream(final byte[] data, final int eod, final int offset, final int markedOffset) {
248 this.data = Objects.requireNonNull(data, "data");
249 this.eod = eod;
250 this.offset = offset;
251 this.markedOffset = markedOffset;
252 }
253
254 @Override
255 public int available() {
256 return offset < eod ? eod - offset : 0;
257 }
258
259 @SuppressWarnings("sync-override")
260 @Override
261 public void mark(final int readLimit) {
262 this.markedOffset = this.offset;
263 }
264
265 @Override
266 public boolean markSupported() {
267 return true;
268 }
269
270 @Override
271 public int read() {
272 return offset < eod ? data[offset++] & 0xff : END_OF_STREAM;
273 }
274
275 @Override
276 public int read(final byte[] dest) {
277 Objects.requireNonNull(dest, "dest");
278 return read(dest, 0, dest.length);
279 }
280
281 @Override
282 public int read(final byte[] dest, final int off, final int len) {
283 Objects.requireNonNull(dest, "dest");
284 if (off < 0 || len < 0 || off + len > dest.length) {
285 throw new IndexOutOfBoundsException();
286 }
287
288 if (offset >= eod) {
289 return END_OF_STREAM;
290 }
291
292 int actualLen = eod - offset;
293 if (len < actualLen) {
294 actualLen = len;
295 }
296 if (actualLen <= 0) {
297 return 0;
298 }
299 System.arraycopy(data, offset, dest, off, actualLen);
300 offset += actualLen;
301 return actualLen;
302 }
303
304 @SuppressWarnings("sync-override")
305 @Override
306 public void reset() {
307 this.offset = this.markedOffset;
308 }
309
310 @Override
311 public long skip(final long n) {
312 if (n < 0) {
313 throw new IllegalArgumentException("Skipping backward is not supported");
314 }
315
316 long actualSkip = eod - offset;
317 if (n < actualSkip) {
318 actualSkip = n;
319 }
320
321 offset = Math.addExact(offset, Math.toIntExact(n));
322 return actualSkip;
323 }
324 }