1
2
3
4
5
6
7
8
9
10
11
12
13
14 package eu.fbk.rdfpro.util;
15
16 import java.util.Arrays;
17
18 abstract class Buffer {
19
20 public static Buffer newFixedBuffer(final byte[] bytes) {
21 return new FixedBuffer(bytes);
22 }
23
24 public static Buffer newResizableBuffer() {
25 return new ResizableBuffer();
26 }
27
28 public abstract byte read(long offset);
29
30 public abstract short readShort(final long offset);
31
32 public abstract int readInt(long offset);
33
34 public abstract long readNumber(final long offset, final int length);
35
36 public abstract String readString(final long offset, final int length);
37
38 public abstract void write(final long offset, final byte b);
39
40 public abstract void writeShort(final long offset, final short n);
41
42 public abstract void writeInt(final long offset, final int n);
43
44 public abstract void writeLong(final long offset, final long n);
45
46 public abstract void writeNumber(final long offset, final int length, final long n);
47
48 public abstract void writeBytes(long offset, final byte[] bytes, int index, int length);
49
50 public abstract void writeBuffer(long offset, final Buffer buffer, long bufferOffset,
51 long length);
52
53 public abstract int writeString(long offset, String s);
54
55 public abstract boolean equalString(final long offset, final int length, final String s);
56
57 private static final class FixedBuffer extends Buffer {
58
59 private final byte[] buffer;
60
61 FixedBuffer(final byte[] buffer) {
62 this.buffer = buffer;
63 }
64
65 @Override
66 public byte read(final long offset) {
67 return this.buffer[(int) offset];
68 }
69
70 @Override
71 public short readShort(final long offset) {
72 final int index = (int) offset;
73 return (short) (this.buffer[index] << 8 | this.buffer[index + 1] & 0xFF);
74 }
75
76 @Override
77 public int readInt(final long offset) {
78 final int index = (int) offset;
79 return this.buffer[index] << 24 | (this.buffer[index + 1] & 0xFF) << 16
80 | (this.buffer[index + 2] & 0xFF) << 8 | this.buffer[index + 3] & 0xFF;
81 }
82
83 @Override
84 public long readNumber(final long offset, final int length) {
85 int index = (int) offset;
86 long result = 0;
87 for (int i = 0; i < length; ++i) {
88 result = result << 8 | this.buffer[index++] & 0xFFL;
89 }
90 return result;
91 }
92
93 @Override
94 public String readString(final long offset, final int length) {
95 final StringBuilder builder = new StringBuilder();
96 int index = (int) offset;
97 int temp = 0;
98 for (int i = 0; i < length; ++i) {
99 final int b = this.buffer[index++] & 0xFF;
100 if (temp != 0) {
101 if (temp < 0) {
102 temp = b;
103 } else {
104 builder.append((char) (temp << 8 | b));
105 temp = 0;
106 }
107 } else if (b == 0) {
108 temp = -1;
109 } else {
110 builder.append((char) b);
111 }
112 }
113 return builder.toString();
114 }
115
116 @Override
117 public void write(final long offset, final byte b) {
118 this.buffer[(int) offset] = b;
119 }
120
121 @Override
122 public void writeShort(final long offset, final short n) {
123 final int index = (int) offset;
124 this.buffer[index] = (byte) (n >>> 8);
125 this.buffer[index + 1] = (byte) n;
126 }
127
128 @Override
129 public void writeInt(final long offset, final int n) {
130 final int index = (int) offset;
131 this.buffer[index] = (byte) (n >>> 24);
132 this.buffer[index + 1] = (byte) (n >>> 16);
133 this.buffer[index + 2] = (byte) (n >>> 8);
134 this.buffer[index + 3] = (byte) n;
135 }
136
137 @Override
138 public void writeLong(final long offset, final long n) {
139 final int index = (int) offset;
140 this.buffer[index] = (byte) (n >>> 56);
141 this.buffer[index + 1] = (byte) (n >>> 48);
142 this.buffer[index + 2] = (byte) (n >>> 40);
143 this.buffer[index + 3] = (byte) (n >>> 32);
144 this.buffer[index + 4] = (byte) (n >>> 24);
145 this.buffer[index + 5] = (byte) (n >>> 16);
146 this.buffer[index + 6] = (byte) (n >>> 8);
147 this.buffer[index + 7] = (byte) n;
148 }
149
150 @Override
151 public void writeNumber(final long offset, final int length, final long n) {
152 int index = (int) offset;
153 for (int i = 1; i <= length; ++i) {
154 this.buffer[index++] = (byte) (n >>> (length - i << 3));
155 }
156 }
157
158 @Override
159 public void writeBytes(final long offset, final byte[] bytes, final int index,
160 final int length) {
161 System.arraycopy(bytes, index, this.buffer, (int) offset, length);
162 }
163
164 @Override
165 public void writeBuffer(final long thisOffset, final Buffer buffer,
166 final long bufferOffset, long length) {
167
168 if (buffer instanceof FixedBuffer) {
169 writeBytes(thisOffset, ((FixedBuffer) buffer).buffer, (int) bufferOffset,
170 (int) length);
171 }
172
173 final ResizableBuffer rbuffer = (ResizableBuffer) buffer;
174 int thisIndex = (int) thisOffset;
175 int bufferIndex = (int) (bufferOffset >>> 16);
176 int byteIndex = (int) bufferOffset & 0xFFFF;
177 while (true) {
178 final int len = (int) Math.min(length, 0x10000 - byteIndex);
179 final byte[] bytes = rbuffer.buffer(bufferIndex);
180 System.arraycopy(bytes, byteIndex, this.buffer, thisIndex, len);
181 length -= len;
182 if (length == 0) {
183 break;
184 }
185 thisIndex += len;
186 byteIndex = 0;
187 ++bufferIndex;
188 }
189 }
190
191 @Override
192 public int writeString(final long offset, final String s) {
193 int index = (int) offset;
194 final int length = s.length();
195 int byteLength = length;
196 for (int i = 0; i < length; ++i) {
197 final char ch = s.charAt(i);
198 if (ch > 0 && ch <= 127) {
199 this.buffer[index++] = (byte) ch;
200 } else {
201 byteLength += 2;
202 this.buffer[index++] = 0;
203 this.buffer[index++] = (byte) (ch >>> 8);
204 this.buffer[index++] = (byte) ch;
205 }
206 }
207 return byteLength;
208 }
209
210 @Override
211 public boolean equalString(final long offset, final int length, final String s) {
212
213 final int strLength = s.length();
214 if (strLength == 0) {
215 return length == 0;
216 } else if (strLength > length) {
217 return false;
218 }
219
220 int index = (int) offset;
221 int temp = -1;
222 int strIndex = 0;
223 for (int i = 0; i < length; ++i) {
224 final byte b = this.buffer[index++];
225 if (temp >= 0) {
226 if (temp == Integer.MAX_VALUE) {
227 temp = b & 0xFF;
228 } else {
229 final char ch = (char) (temp << 8 | b & 0xFF);
230 if (strIndex == strLength || s.charAt(strIndex++) != ch) {
231 return false;
232 }
233 temp = -1;
234 }
235 } else if (b == 0) {
236 temp = Integer.MAX_VALUE;
237 } else {
238 final char ch = (char) b;
239 if (strIndex == strLength || s.charAt(strIndex++) != ch) {
240 return false;
241 }
242 }
243 }
244
245 return strIndex == strLength;
246 }
247
248 }
249
250 private static final class ResizableBuffer extends Buffer {
251
252 private byte[][] buffers;
253
254 ResizableBuffer() {
255 this.buffers = new byte[4][];
256 }
257
258 @Override
259 public byte read(final long offset) {
260 final int bufferIndex = (int) (offset >>> 16);
261 final int byteIndex = (int) offset & 0xFFFF;
262 return buffer(bufferIndex)[byteIndex];
263 }
264
265 @Override
266 public short readShort(final long offset) {
267 final int bufferIndex = (int) (offset >>> 16);
268 final int byteIndex = (int) offset & 0xFFFF;
269 if (byteIndex < 0x10000 - 1) {
270 final byte[] buffer = buffer(bufferIndex);
271 return (short) (buffer[byteIndex] << 8 | buffer[byteIndex + 1] & 0xFF);
272 } else {
273 return (short) readNumber(offset, 2);
274 }
275 }
276
277 @Override
278 public int readInt(final long offset) {
279 final int bufferIndex = (int) (offset >>> 16);
280 final int byteIndex = (int) offset & 0xFFFF;
281 if (byteIndex < 0x10000 - 3) {
282 final byte[] buffer = buffer(bufferIndex);
283 return buffer[byteIndex] << 24 | (buffer[byteIndex + 1] & 0xFF) << 16
284 | (buffer[byteIndex + 2] & 0xFF) << 8 | buffer[byteIndex + 3] & 0xFF;
285 } else {
286 return (int) readNumber(offset, 4);
287 }
288 }
289
290 @Override
291 public long readNumber(final long offset, final int length) {
292 int bufferIndex = (int) (offset >>> 16);
293 int byteIndex = (int) offset & 0xFFFF;
294 byte[] buffer = buffer(bufferIndex);
295 long result = 0;
296 for (int i = 0; i < length; ++i) {
297 result = result << 8 | buffer[byteIndex++] & 0xFFL;
298 if (byteIndex == 0x10000) {
299 buffer = buffer(++bufferIndex);
300 byteIndex = 0;
301 }
302 }
303 return result;
304 }
305
306 @Override
307 public String readString(final long offset, final int length) {
308
309 assert offset >= 0;
310 assert length >= 0;
311
312 final StringBuilder builder = new StringBuilder();
313 int bufferIndex = (int) (offset >>> 16);
314 int byteIndex = (int) offset & 0xFFFF;
315 byte[] buffer = buffer(bufferIndex);
316 int temp = 0;
317 for (int i = 0; i < length; ++i) {
318 final int b = buffer[byteIndex++] & 0xFF;
319 if (byteIndex == 0x10000) {
320 buffer = buffer(++bufferIndex);
321 byteIndex = 0;
322 }
323 if (temp != 0) {
324 if (temp < 0) {
325 temp = b;
326 } else {
327 builder.append((char) (temp << 8 | b));
328 temp = 0;
329 }
330 } else if (b == 0) {
331 temp = -1;
332 } else {
333 builder.append((char) b);
334 }
335 }
336
337 return builder.toString();
338 }
339
340 @Override
341 public void write(final long offset, final byte b) {
342 final int bufferIndex = (int) (offset >>> 16);
343 final int byteIndex = (int) offset & 0xFFFF;
344 final byte[] buffer = buffer(bufferIndex);
345 buffer[byteIndex] = b;
346 }
347
348 @Override
349 public void writeShort(final long offset, final short n) {
350 final int bufferIndex = (int) (offset >>> 16);
351 final int byteIndex = (int) offset & 0xFFFF;
352 if (byteIndex < 0x10000 - 1) {
353 final byte[] buffer = buffer(bufferIndex);
354 buffer[byteIndex] = (byte) (n >>> 8);
355 buffer[byteIndex + 1] = (byte) n;
356 } else {
357 writeNumber(offset, 2, n);
358 }
359 }
360
361 @Override
362 public void writeInt(final long offset, final int n) {
363 final int bufferIndex = (int) (offset >>> 16);
364 final int byteIndex = (int) offset & 0xFFFF;
365 if (byteIndex < 0x10000 - 3) {
366 final byte[] buffer = buffer(bufferIndex);
367 buffer[byteIndex] = (byte) (n >>> 24);
368 buffer[byteIndex + 1] = (byte) (n >>> 16);
369 buffer[byteIndex + 2] = (byte) (n >>> 8);
370 buffer[byteIndex + 3] = (byte) n;
371 } else {
372 writeNumber(offset, 4, n);
373 }
374 }
375
376 @Override
377 public void writeLong(final long offset, final long n) {
378 final int bufferIndex = (int) (offset >>> 16);
379 final int byteIndex = (int) offset & 0xFFFF;
380 if (byteIndex < 0x10000 - 7) {
381 final byte[] buffer = buffer(bufferIndex);
382 buffer[byteIndex] = (byte) (n >>> 56);
383 buffer[byteIndex + 1] = (byte) (n >>> 48);
384 buffer[byteIndex + 2] = (byte) (n >>> 40);
385 buffer[byteIndex + 3] = (byte) (n >>> 32);
386 buffer[byteIndex + 4] = (byte) (n >>> 24);
387 buffer[byteIndex + 5] = (byte) (n >>> 16);
388 buffer[byteIndex + 6] = (byte) (n >>> 8);
389 buffer[byteIndex + 7] = (byte) n;
390 } else {
391 writeNumber(offset, 8, n);
392 }
393 }
394
395 @Override
396 public void writeNumber(final long offset, final int length, final long n) {
397 int bufferIndex = (int) (offset >>> 16);
398 int byteIndex = (int) offset & 0xFFFF;
399 byte[] buffer = buffer(bufferIndex);
400 for (int i = 1; i <= length; ++i) {
401 buffer[byteIndex++] = (byte) (n >>> (length - i << 3));
402 if (byteIndex == 0x10000) {
403 buffer = buffer(++bufferIndex);
404 byteIndex = 0;
405 }
406 }
407 }
408
409 @Override
410 public void writeBytes(final long offset, final byte[] bytes, int index, int length) {
411 int bufferIndex = (int) (offset >>> 16);
412 int byteIndex = (int) offset & 0xFFFF;
413 while (true) {
414 final int len = Math.min(length, 0x10000 - byteIndex);
415 final byte[] buffer = buffer(bufferIndex);
416 System.arraycopy(bytes, index, buffer, byteIndex, len);
417 length -= len;
418 if (length == 0) {
419 break;
420 }
421 index += len;
422 byteIndex = 0;
423 ++bufferIndex;
424 }
425 }
426
427 @Override
428 public void writeBuffer(final long thisOffset, final Buffer buffer,
429 final long bufferOffset, long length) {
430
431 if (buffer instanceof FixedBuffer) {
432 writeBytes(thisOffset, ((FixedBuffer) buffer).buffer, (int) bufferOffset,
433 (int) length);
434
435 } else {
436 int thisBufferIndex = (int) (thisOffset >>> 16);
437 int thisByteIndex = (int) thisOffset & 0xFFFF;
438 int otherBufferIndex = (int) (bufferOffset >>> 16);
439 int otherByteIndex = (int) bufferOffset & 0xFFFF;
440
441 while (true) {
442 final int len = (int) Math.min(length,
443 Math.min(0x10000 - otherByteIndex, 0x10000 - thisByteIndex));
444 final byte[] thisBuffer = buffer(thisBufferIndex);
445 final byte[] otherBuffer = ((ResizableBuffer) buffer).buffer(otherBufferIndex);
446 System.arraycopy(otherBuffer, otherByteIndex, thisBuffer, thisByteIndex, len);
447 length -= len;
448 if (length == 0) {
449 break;
450 }
451 thisByteIndex += len;
452 if (thisByteIndex == 0x10000) {
453 ++thisBufferIndex;
454 thisByteIndex = 0;
455 }
456 otherByteIndex += len;
457 if (otherByteIndex == 0x10000) {
458 ++otherBufferIndex;
459 otherByteIndex = 0;
460 }
461 }
462 }
463 }
464
465 @Override
466 public int writeString(final long offset, final String s) {
467
468 assert offset >= 0L;
469 assert s != null;
470
471 int bufferIndex = (int) (offset >>> 16);
472 int byteIndex = (int) offset & 0xFFFF;
473 byte[] buffer = buffer(bufferIndex);
474 final int length = s.length();
475 int byteLength = length;
476 for (int i = 0; i < length; ++i) {
477 final char ch = s.charAt(i);
478 if (ch > 0 && ch <= 127) {
479 buffer[byteIndex++] = (byte) ch;
480 if (byteIndex == 0x10000) {
481 buffer = buffer(++bufferIndex);
482 byteIndex = 0;
483 }
484 } else {
485 byteLength += 2;
486 for (final byte b : new byte[] { 0, (byte) (ch >>> 8), (byte) ch }) {
487 buffer[byteIndex++] = b;
488 if (byteIndex == 0x10000) {
489 buffer = buffer(++bufferIndex);
490 byteIndex = 0;
491 }
492 }
493 }
494 }
495
496 return byteLength;
497 }
498
499 @Override
500 public boolean equalString(final long offset, final int length, final String s) {
501
502 assert offset >= 0;
503 assert length >= 0;
504 assert s != null;
505
506 final int strLength = s.length();
507 if (strLength == 0) {
508 return length == 0;
509 } else if (strLength > length) {
510 return false;
511 }
512
513 int bufferIndex = (int) (offset >>> 16);
514 int byteIndex = (int) offset & 0xFFFF;
515 byte[] buffer = buffer(bufferIndex);
516 int temp = -1;
517 int strIndex = 0;
518 for (int i = 0; i < length; ++i) {
519 final byte b = buffer[byteIndex++];
520 if (byteIndex == 0x10000) {
521 buffer = buffer(++bufferIndex);
522 byteIndex = 0;
523 }
524 if (temp >= 0) {
525 if (temp == Integer.MAX_VALUE) {
526 temp = b & 0xFF;
527 } else {
528 final char ch = (char) (temp << 8 | b & 0xFF);
529 if (strIndex == strLength || s.charAt(strIndex++) != ch) {
530 return false;
531 }
532 temp = -1;
533 }
534 } else if (b == 0) {
535 temp = Integer.MAX_VALUE;
536 } else {
537 final char ch = (char) b;
538 if (strIndex == strLength || s.charAt(strIndex++) != ch) {
539 return false;
540 }
541 }
542 }
543
544 return strIndex == strLength;
545 }
546
547 private byte[] buffer(final int index) {
548 assert index >= 0;
549 final byte[][] buffers = this.buffers;
550 if (index < buffers.length) {
551 final byte[] buffer = buffers[index];
552 if (buffer != null) {
553 return buffer;
554 }
555 }
556 return bufferHelper(index);
557 }
558
559 private synchronized byte[] bufferHelper(final int index) {
560 if (index >= this.buffers.length) {
561 this.buffers = Arrays.copyOf(this.buffers, this.buffers.length << 1);
562 }
563 byte[] buffer = this.buffers[index];
564 if (buffer == null) {
565 buffer = new byte[64 * 1024];
566 this.buffers[index] = buffer;
567 }
568 return buffer;
569 }
570
571 }
572
573 }