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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 @Override
107 public UnsynchronizedByteArrayInputStream get() throws IOException {
108 return new UnsynchronizedByteArrayInputStream(checkOrigin().getByteArray(), offset, length);
109 }
110
111 @Override
112 public Builder setByteArray(final byte[] origin) {
113 length = Objects.requireNonNull(origin, "origin").length;
114 return super.setByteArray(origin);
115 }
116
117
118
119
120
121
122
123 public Builder setLength(final int length) {
124 if (length < 0) {
125 throw new IllegalArgumentException("length cannot be negative");
126 }
127 this.length = length;
128 return this;
129 }
130
131
132
133
134
135
136
137 public Builder setOffset(final int offset) {
138 if (offset < 0) {
139 throw new IllegalArgumentException("offset cannot be negative");
140 }
141 this.offset = offset;
142 return this;
143 }
144
145 }
146
147
148
149
150 public static final int END_OF_STREAM = -1;
151
152
153
154
155
156
157 public static Builder builder() {
158 return new Builder();
159 }
160
161 private static int minPosLen(final byte[] data, final int defaultValue) {
162 requireNonNegative(defaultValue, "defaultValue");
163 return Math.min(defaultValue, data.length > 0 ? data.length : defaultValue);
164 }
165
166 private static int requireNonNegative(final int value, final String name) {
167 if (value < 0) {
168 throw new IllegalArgumentException(name + " cannot be negative");
169 }
170 return value;
171 }
172
173
174
175
176 private final byte[] data;
177
178
179
180
181
182
183 private final int eod;
184
185
186
187
188 private int offset;
189
190
191
192
193 private int markedOffset;
194
195
196
197
198
199
200
201 @Deprecated
202 public UnsynchronizedByteArrayInputStream(final byte[] data) {
203 this(data, data.length, 0, 0);
204 }
205
206
207
208
209
210
211
212
213
214
215 @Deprecated
216 public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset) {
217 this(data, data.length, Math.min(requireNonNegative(offset, "offset"), minPosLen(data, offset)), minPosLen(data, offset));
218 }
219
220
221
222
223
224
225
226
227
228
229
230 @Deprecated
231 public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset, final int length) {
232 requireNonNegative(offset, "offset");
233 requireNonNegative(length, "length");
234 this.data = Objects.requireNonNull(data, "data");
235 this.eod = Math.min(minPosLen(data, offset) + length, data.length);
236 this.offset = minPosLen(data, offset);
237 this.markedOffset = minPosLen(data, offset);
238 }
239
240 private UnsynchronizedByteArrayInputStream(final byte[] data, final int eod, final int offset, final int markedOffset) {
241 this.data = Objects.requireNonNull(data, "data");
242 this.eod = eod;
243 this.offset = offset;
244 this.markedOffset = markedOffset;
245 }
246
247 @Override
248 public int available() {
249 return offset < eod ? eod - offset : 0;
250 }
251
252 @SuppressWarnings("sync-override")
253 @Override
254 public void mark(final int readLimit) {
255 this.markedOffset = this.offset;
256 }
257
258 @Override
259 public boolean markSupported() {
260 return true;
261 }
262
263 @Override
264 public int read() {
265 return offset < eod ? data[offset++] & 0xff : END_OF_STREAM;
266 }
267
268 @Override
269 public int read(final byte[] dest) {
270 Objects.requireNonNull(dest, "dest");
271 return read(dest, 0, dest.length);
272 }
273
274 @Override
275 public int read(final byte[] dest, final int off, final int len) {
276 Objects.requireNonNull(dest, "dest");
277 if (off < 0 || len < 0 || off + len > dest.length) {
278 throw new IndexOutOfBoundsException();
279 }
280
281 if (offset >= eod) {
282 return END_OF_STREAM;
283 }
284
285 int actualLen = eod - offset;
286 if (len < actualLen) {
287 actualLen = len;
288 }
289 if (actualLen <= 0) {
290 return 0;
291 }
292 System.arraycopy(data, offset, dest, off, actualLen);
293 offset += actualLen;
294 return actualLen;
295 }
296
297 @SuppressWarnings("sync-override")
298 @Override
299 public void reset() {
300 this.offset = this.markedOffset;
301 }
302
303 @Override
304 public long skip(final long n) {
305 if (n < 0) {
306 throw new IllegalArgumentException("Skipping backward is not supported");
307 }
308
309 long actualSkip = eod - offset;
310 if (n < actualSkip) {
311 actualSkip = n;
312 }
313
314 offset = Math.addExact(offset, Math.toIntExact(n));
315 return actualSkip;
316 }
317 }