1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.provider.ram;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.DataInputStream;
21 import java.io.DataOutputStream;
22 import java.io.EOFException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.nio.charset.Charset;
26 import java.util.Objects;
27
28 import org.apache.commons.vfs2.RandomAccessContent;
29 import org.apache.commons.vfs2.util.RandomAccessMode;
30
31
32
33
34 public class RamFileRandomAccessContent implements RandomAccessContent {
35
36 private static final int BYTE_VALUE_MASK = 0xFF;
37
38
39
40
41
42
43
44
45 public static byte[] toBytes(long n, final byte[] b) {
46 b[7] = (byte) n;
47 n >>>= 8;
48 b[6] = (byte) n;
49 n >>>= 8;
50 b[5] = (byte) n;
51 n >>>= 8;
52 b[4] = (byte) n;
53 n >>>= 8;
54 b[3] = (byte) n;
55 n >>>= 8;
56 b[2] = (byte) n;
57 n >>>= 8;
58 b[1] = (byte) n;
59 n >>>= 8;
60 b[0] = (byte) n;
61 return b;
62 }
63
64
65
66
67
68
69
70 public static long toLong(final byte[] b) {
71 return ((long) b[7] & BYTE_VALUE_MASK) + (((long) b[6] & BYTE_VALUE_MASK) << 8) + (((long) b[5] & BYTE_VALUE_MASK) << 16)
72 + (((long) b[4] & BYTE_VALUE_MASK) << 24) + (((long) b[3] & BYTE_VALUE_MASK) << 32) + (((long) b[2] & BYTE_VALUE_MASK) << 40)
73 + (((long) b[1] & BYTE_VALUE_MASK) << 48) + (((long) b[0] & BYTE_VALUE_MASK) << 56);
74 }
75
76
77
78
79
80
81
82 public static short toShort(final byte[] b) {
83 return (short) toUnsignedShort(b);
84 }
85
86
87
88
89
90
91
92 public static int toUnsignedShort(final byte[] b) {
93 return (b[1] & BYTE_VALUE_MASK) + ((b[0] & BYTE_VALUE_MASK) << 8);
94 }
95
96
97
98
99 protected int filePointer;
100
101
102
103
104 private byte[] buf;
105
106
107
108
109 private final byte[] buffer8 = new byte[8];
110
111
112
113
114 private final byte[] buffer4 = new byte[4];
115
116
117
118
119 private final byte[] buffer2 = new byte[2];
120
121
122
123
124 private final byte[] buffer1 = new byte[1];
125
126
127
128
129 private final RamFileObject file;
130
131 private final InputStream rafis;
132
133
134
135
136
137
138
139 public RamFileRandomAccessContent(final RamFileObject file, final RandomAccessMode mode) {
140 Objects.requireNonNull(file, "file");
141 Objects.requireNonNull(mode, "mode");
142 buf = file.getData().getContent();
143 this.file = file;
144
145 rafis = new InputStream() {
146 @Override
147 public int available() throws IOException {
148 return getLeftBytes();
149 }
150
151 @Override
152 public void close() throws IOException {
153 }
154
155 @Override
156 public int read() throws IOException {
157 try {
158 return readByte() & BYTE_VALUE_MASK;
159 } catch (final EOFException e) {
160 return -1;
161 }
162 }
163
164 @Override
165 public int read(final byte[] b) throws IOException {
166 return read(b, 0, b.length);
167 }
168
169 @Override
170 public int read(final byte[] b, final int off, final int len) throws IOException {
171 int retLen = -1;
172 final int left = getLeftBytes();
173 if (left > 0) {
174 retLen = Math.min(len, left);
175 RamFileRandomAccessContent.this.readFully(b, off, retLen);
176 }
177 return retLen;
178 }
179
180 @Override
181 public long skip(final long n) throws IOException {
182 seek(getFilePointer() + n);
183 return n;
184 }
185 };
186 }
187
188
189
190
191
192
193 @Override
194 public void close() throws IOException {
195
196 }
197
198
199
200
201
202
203 @Override
204 public long getFilePointer() throws IOException {
205 return filePointer;
206 }
207
208 @Override
209 public InputStream getInputStream() throws IOException {
210 return rafis;
211 }
212
213 private int getLeftBytes() {
214 return buf.length - filePointer;
215 }
216
217
218
219
220
221
222 @Override
223 public long length() throws IOException {
224 return buf.length;
225 }
226
227
228
229
230
231
232 @Override
233 public boolean readBoolean() throws IOException {
234 return readUnsignedByte() != 0;
235 }
236
237
238
239
240
241
242 @Override
243 public byte readByte() throws IOException {
244 return (byte) readUnsignedByte();
245 }
246
247
248
249
250
251
252 @Override
253 public char readChar() throws IOException {
254 final int ch1 = readUnsignedByte();
255 final int ch2 = readUnsignedByte();
256 return (char) ((ch1 << 8) + (ch2 << 0));
257 }
258
259
260
261
262
263
264 @Override
265 public double readDouble() throws IOException {
266 return Double.longBitsToDouble(readLong());
267 }
268
269
270
271
272
273
274 @Override
275 public float readFloat() throws IOException {
276 return Float.intBitsToFloat(readInt());
277 }
278
279
280
281
282
283
284 @Override
285 public void readFully(final byte[] b) throws IOException {
286 this.readFully(b, 0, b.length);
287 }
288
289
290
291
292
293
294 @Override
295 public void readFully(final byte[] b, final int off, final int len) throws IOException {
296 if (len < 0) {
297 throw new IndexOutOfBoundsException("Length is lower than 0");
298 }
299
300 if (len > getLeftBytes()) {
301 throw new IndexOutOfBoundsException(
302 "Read length (" + len + ") is higher than buffer left bytes (" + getLeftBytes() + ") ");
303 }
304
305 System.arraycopy(buf, filePointer, b, off, len);
306
307 filePointer += len;
308 }
309
310
311
312
313
314
315 @Override
316 public int readInt() throws IOException {
317 return readUnsignedByte() << 24 | readUnsignedByte() << 16 | readUnsignedByte() << 8 | readUnsignedByte();
318 }
319
320
321
322
323
324
325 @Override
326 public String readLine() throws IOException {
327 throw new UnsupportedOperationException("deprecated");
328 }
329
330
331
332
333
334
335 @Override
336 public long readLong() throws IOException {
337 this.readFully(buffer8);
338 return toLong(buffer8);
339 }
340
341
342
343
344
345
346 @Override
347 public short readShort() throws IOException {
348 this.readFully(buffer2);
349 return toShort(buffer2);
350 }
351
352
353
354
355
356
357 @Override
358 public int readUnsignedByte() throws IOException {
359 if (filePointer < buf.length) {
360 return buf[filePointer++] & BYTE_VALUE_MASK;
361 }
362 throw new EOFException();
363 }
364
365
366
367
368
369
370 @Override
371 public int readUnsignedShort() throws IOException {
372 this.readFully(buffer2);
373 return toUnsignedShort(buffer2);
374 }
375
376
377
378
379
380
381 @Override
382 public String readUTF() throws IOException {
383 return DataInputStream.readUTF(this);
384 }
385
386
387
388
389
390
391 @Override
392 public void seek(final long pos) throws IOException {
393 if (pos < 0) {
394 throw new IOException("Attempt to position before the start of the file");
395 }
396 filePointer = (int) pos;
397 }
398
399 @Override
400 public void setLength(final long newLength) throws IOException {
401 file.resize(newLength);
402 buf = file.getData().getContent();
403 }
404
405
406
407
408
409
410 @Override
411 public int skipBytes(final int n) throws IOException {
412 if (n < 0) {
413 throw new IndexOutOfBoundsException("The skip number can't be negative");
414 }
415
416 final long newPos = filePointer + n;
417
418 if (newPos > buf.length) {
419 throw new IndexOutOfBoundsException("Tyring to skip too much bytes");
420 }
421
422 seek(newPos);
423
424 return n;
425 }
426
427
428
429
430
431
432 @Override
433 public void write(final byte[] b) throws IOException {
434 this.write(b, 0, b.length);
435 }
436
437
438
439
440
441
442 @Override
443 public void write(final byte[] b, final int off, final int len) throws IOException {
444 if (getLeftBytes() < len) {
445 final int newSize = buf.length + len - getLeftBytes();
446 file.resize(newSize);
447 buf = file.getData().getContent();
448 }
449 System.arraycopy(b, off, buf, filePointer, len);
450 filePointer += len;
451 }
452
453
454
455
456
457
458 @Override
459 public void write(final int b) throws IOException {
460 buffer1[0] = (byte) b;
461 this.write(buffer1);
462 }
463
464
465
466
467
468
469 @Override
470 public void writeBoolean(final boolean v) throws IOException {
471 this.write(v ? 1 : 0);
472 }
473
474
475
476
477
478
479 @Override
480 public void writeByte(final int i) throws IOException {
481 this.write(i);
482 }
483
484
485
486
487
488
489 @Override
490 public void writeBytes(final String s) throws IOException {
491 write(s.getBytes(Charset.defaultCharset()));
492 }
493
494
495
496
497
498
499 @Override
500 public void writeChar(final int v) throws IOException {
501 buffer2[0] = (byte) (v >>> 8 & BYTE_VALUE_MASK);
502 buffer2[1] = (byte) (v >>> 0 & BYTE_VALUE_MASK);
503 write(buffer2);
504 }
505
506
507
508
509
510
511 @Override
512 public void writeChars(final String s) throws IOException {
513 final int len = s.length();
514 for (int i = 0; i < len; i++) {
515 writeChar(s.charAt(i));
516 }
517 }
518
519
520
521
522
523
524 @Override
525 public void writeDouble(final double v) throws IOException {
526 writeLong(Double.doubleToLongBits(v));
527 }
528
529
530
531
532
533
534 @Override
535 public void writeFloat(final float v) throws IOException {
536 writeInt(Float.floatToIntBits(v));
537 }
538
539
540
541
542
543
544 @Override
545 public void writeInt(final int v) throws IOException {
546 buffer4[0] = (byte) (v >>> 24 & BYTE_VALUE_MASK);
547 buffer4[1] = (byte) (v >>> 16 & BYTE_VALUE_MASK);
548 buffer4[2] = (byte) (v >>> 8 & BYTE_VALUE_MASK);
549 buffer4[3] = (byte) (v & BYTE_VALUE_MASK);
550 write(buffer4);
551 }
552
553
554
555
556
557
558 @Override
559 public void writeLong(final long v) throws IOException {
560 write(toBytes(v, buffer8));
561 }
562
563
564
565
566
567
568 @Override
569 public void writeShort(final int v) throws IOException {
570 buffer2[0] = (byte) (v >>> 8 & BYTE_VALUE_MASK);
571 buffer2[1] = (byte) (v & BYTE_VALUE_MASK);
572 write(buffer2);
573 }
574
575
576
577
578
579
580 @Override
581 public void writeUTF(final String str) throws IOException {
582 final ByteArrayOutputStream out = new ByteArrayOutputStream(str.length());
583 final DataOutputStream dataOut = new DataOutputStream(out);
584 dataOut.writeUTF(str);
585 dataOut.flush();
586 dataOut.close();
587 final byte[] b = out.toByteArray();
588 write(b);
589 }
590 }