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