1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.buffer.api.unsafe;
17
18 import io.netty5.buffer.api.AllocatorControl;
19 import io.netty5.buffer.api.Buffer;
20 import io.netty5.buffer.api.BufferAllocator;
21 import io.netty5.buffer.api.BufferClosedException;
22 import io.netty5.buffer.api.BufferReadOnlyException;
23 import io.netty5.buffer.api.ByteCursor;
24 import io.netty5.buffer.api.ComponentIterator;
25 import io.netty5.buffer.api.ComponentIterator.Next;
26 import io.netty5.buffer.api.Drop;
27 import io.netty5.buffer.api.Owned;
28 import io.netty5.buffer.api.ReadableComponent;
29 import io.netty5.buffer.api.ReadableComponentProcessor;
30 import io.netty5.buffer.api.WritableComponent;
31 import io.netty5.buffer.api.WritableComponentProcessor;
32 import io.netty5.buffer.api.internal.AdaptableBuffer;
33 import io.netty5.buffer.api.internal.NotReadOnlyReadableComponent;
34 import io.netty5.buffer.api.internal.SingleComponentIterator;
35 import io.netty5.buffer.api.internal.Statics;
36 import io.netty5.buffer.api.internal.Statics.UncheckedLoadByte;
37 import io.netty5.util.internal.PlatformDependent;
38 import io.netty5.util.internal.UnsafeAccess;
39 import sun.misc.Unsafe;
40
41 import java.io.IOException;
42 import java.lang.ref.Reference;
43 import java.nio.ByteBuffer;
44 import java.nio.ByteOrder;
45 import java.nio.ReadOnlyBufferException;
46 import java.nio.channels.FileChannel;
47 import java.nio.channels.ReadableByteChannel;
48 import java.nio.channels.WritableByteChannel;
49
50 import static io.netty5.buffer.api.internal.Statics.MAX_BUFFER_SIZE;
51 import static io.netty5.buffer.api.internal.Statics.bbslice;
52 import static io.netty5.buffer.api.internal.Statics.bufferIsReadOnly;
53 import static io.netty5.buffer.api.internal.Statics.checkImplicitCapacity;
54 import static io.netty5.buffer.api.internal.Statics.checkLength;
55 import static io.netty5.buffer.api.internal.Statics.nativeAddressWithOffset;
56 import static io.netty5.util.internal.ObjectUtil.checkPositiveOrZero;
57 import static io.netty5.util.internal.PlatformDependent.roundToPowerOfTwo;
58
59 @UnsafeAccess
60 final class UnsafeBuffer extends AdaptableBuffer<UnsafeBuffer>
61 implements ReadableComponent, WritableComponent, NotReadOnlyReadableComponent, ComponentIterator.Next {
62 private static final int CLOSED_SIZE = -1;
63 private static final boolean ACCESS_UNALIGNED = PlatformDependent.isUnaligned();
64 private static final boolean FLIP_BYTES = ByteOrder.BIG_ENDIAN != ByteOrder.nativeOrder();
65 private static final Unsafe UNSAFE = (Unsafe) PlatformDependent.unwrapUnsafeOrNull();
66 private UnsafeMemory memory;
67 private Object base;
68 private long baseOffset;
69 private long address;
70 private int rsize;
71 private int wsize;
72 private boolean readOnly;
73 private int roff;
74 private int woff;
75 private int implicitCapacityLimit;
76
77 UnsafeBuffer(UnsafeMemory memory, long offset, int size, AllocatorControl control,
78 Drop<UnsafeBuffer> drop) {
79 super(drop, control);
80 this.memory = memory;
81 base = memory.base;
82 baseOffset = offset;
83 address = memory.address + offset;
84 rsize = size;
85 wsize = size;
86 implicitCapacityLimit = MAX_BUFFER_SIZE;
87 }
88
89
90
91
92 private UnsafeBuffer(UnsafeBuffer parent, Drop<UnsafeBuffer> drop) {
93 super(drop, parent.control);
94 implicitCapacityLimit = parent.implicitCapacityLimit;
95 memory = parent.memory;
96 base = parent.base;
97 baseOffset = parent.baseOffset;
98 address = parent.address;
99 rsize = parent.rsize;
100 wsize = parent.wsize;
101 readOnly = parent.readOnly;
102 roff = parent.roff;
103 woff = parent.woff;
104 }
105
106 @Override
107 public String toString() {
108 return "Buffer[roff:" + roff + ", woff:" + woff + ", cap:" + rsize + ']';
109 }
110
111 @Override
112 protected RuntimeException createResourceClosedException() {
113 return Statics.bufferIsClosed(this);
114 }
115
116 @Override
117 public int capacity() {
118 return Math.max(0, rsize);
119 }
120
121 @Override
122 public int readerOffset() {
123 return roff;
124 }
125
126 @Override
127 public Buffer readerOffset(int offset) {
128 checkRead(offset, 0);
129 roff = offset;
130 return this;
131 }
132
133 @Override
134 public int writerOffset() {
135 return woff;
136 }
137
138 @Override
139 public Buffer writerOffset(int offset) {
140 checkWrite(offset, 0, false);
141 woff = offset;
142 return this;
143 }
144
145 @Override
146 public int readableBytes() {
147 return super.readableBytes();
148 }
149
150 @Override
151 public int writableBytes() {
152 return super.writableBytes();
153 }
154
155 @Override
156 public UnsafeBuffer skipReadableBytes(int delta) {
157 return (UnsafeBuffer) super.skipReadableBytes(delta);
158 }
159
160 @Override
161 public UnsafeBuffer skipWritableBytes(int delta) {
162 return (UnsafeBuffer) super.skipWritableBytes(delta);
163 }
164
165 @Override
166 public Buffer fill(byte value) {
167 checkSet(0, capacity());
168 if (rsize == CLOSED_SIZE) {
169 throw bufferIsClosed();
170 }
171 try {
172 PlatformDependent.setMemory(base, address, rsize, value);
173 } finally {
174 Reference.reachabilityFence(memory);
175 }
176 return this;
177 }
178
179 private long nativeAddress() {
180 return base == null? address : 0;
181 }
182
183 @Override
184 public Buffer makeReadOnly() {
185 readOnly = true;
186 wsize = CLOSED_SIZE;
187 return this;
188 }
189
190 @Override
191 public boolean readOnly() {
192 return readOnly;
193 }
194
195 @Override
196 public boolean isDirect() {
197 return base == null;
198 }
199
200 @Override
201 public Buffer implicitCapacityLimit(int limit) {
202 checkImplicitCapacity(limit, capacity());
203 implicitCapacityLimit = limit;
204 return this;
205 }
206
207 @Override
208 public int implicitCapacityLimit() {
209 return implicitCapacityLimit;
210 }
211
212 @Override
213 public Buffer copy(int offset, int length, boolean readOnly) {
214 checkLength(length);
215 checkGet(offset, length);
216 if (readOnly && readOnly()) {
217
218 UnsafeBuffer copy = newConstChild();
219 copy.baseOffset += offset;
220 copy.address += offset;
221 copy.rsize = length;
222 copy.roff = 0;
223 copy.woff = length;
224 return copy;
225 }
226 Buffer copy = control.getAllocator().allocate(length);
227 try {
228 copyInto(offset, copy, 0, length);
229 copy.writerOffset(length);
230 if (readOnly) {
231 copy.makeReadOnly();
232 }
233 return copy;
234 } catch (Throwable e) {
235 copy.close();
236 throw e;
237 }
238 }
239
240 @Override
241 public void copyInto(int srcPos, byte[] dest, int destPos, int length) {
242 checkCopyIntoArgs(srcPos, length, destPos, dest.length);
243 copyIntoArray(srcPos, dest, destPos, length);
244 }
245
246 private void copyIntoArray(int srcPos, byte[] dest, int destPos, int length) {
247 long destOffset = PlatformDependent.byteArrayBaseOffset();
248 try {
249 PlatformDependent.copyMemory(base, address + srcPos, dest, destOffset + destPos, length);
250 } finally {
251 Reference.reachabilityFence(memory);
252 Reference.reachabilityFence(dest);
253 }
254 }
255
256 @Override
257 public void copyInto(int srcPos, ByteBuffer dest, int destPos, int length) {
258 checkCopyIntoArgs(srcPos, length, destPos, dest.capacity());
259 if (dest.isReadOnly()) {
260 throw new ReadOnlyBufferException();
261 }
262 if (dest.hasArray()) {
263 copyIntoArray(srcPos, dest.array(), dest.arrayOffset() + destPos, length);
264 } else {
265 assert dest.isDirect();
266 long destAddr = PlatformDependent.directBufferAddress(dest);
267 try {
268 PlatformDependent.copyMemory(base, address + srcPos, null, destAddr + destPos, length);
269 } finally {
270 Reference.reachabilityFence(memory);
271 Reference.reachabilityFence(dest);
272 }
273 }
274 }
275
276 private void checkCopyIntoArgs(int srcPos, int length, int destPos, int destLength) {
277 if (rsize == CLOSED_SIZE) {
278 throw bufferIsClosed();
279 }
280 if (srcPos < 0) {
281 throw new IndexOutOfBoundsException("The srcPos cannot be negative: " + srcPos + '.');
282 }
283 checkLength(length);
284 if (rsize < srcPos + length) {
285 throw new IndexOutOfBoundsException("The srcPos + length is beyond the end of the buffer: " +
286 "srcPos = " + srcPos + ", length = " + length + '.');
287 }
288 if (destPos < 0) {
289 throw new IndexOutOfBoundsException("The destPos cannot be negative: " + destPos + '.');
290 }
291 if (destLength < destPos + length) {
292 throw new IndexOutOfBoundsException("The destPos + length is beyond the end of the destination: " +
293 "destPos = " + destPos + ", length = " + length + '.');
294 }
295 }
296
297 @Override
298 public void copyInto(int srcPos, Buffer dest, int destPos, int length) {
299 if (!dest.isAccessible()) {
300 throw Statics.bufferIsClosed(dest);
301 }
302 checkCopyIntoArgs(srcPos, length, destPos, dest.capacity());
303 if (dest.readOnly()) {
304 throw bufferIsReadOnly(this);
305 }
306 try {
307 if (dest instanceof UnsafeBuffer) {
308 UnsafeBuffer destUnsafe = (UnsafeBuffer) dest;
309 long nativeAddress = destUnsafe.nativeAddress();
310 if (nativeAddress != 0) {
311 PlatformDependent.copyMemory(base, address + srcPos, null, nativeAddress + destPos, length);
312 } else {
313 PlatformDependent.copyMemory(
314 base, address + srcPos, destUnsafe.base, destUnsafe.address + destPos, length);
315 }
316 } else {
317 Statics.copyToViaReverseLoop(this, srcPos, dest, destPos, length);
318 }
319 } finally {
320 Reference.reachabilityFence(memory);
321 Reference.reachabilityFence(dest);
322 }
323 }
324
325 @Override
326 public int transferTo(WritableByteChannel channel, int length) throws IOException {
327 if (!isAccessible()) {
328 throw bufferIsClosed();
329 }
330 length = Math.min(readableBytes(), length);
331 if (length == 0) {
332 return 0;
333 }
334 checkGet(readerOffset(), length);
335 int bytesWritten = channel.write(readableBuffer().limit(length));
336 skipReadableBytes(bytesWritten);
337 return bytesWritten;
338 }
339
340 @Override
341 public int transferFrom(FileChannel channel, long position, int length) throws IOException {
342 checkPositiveOrZero(position, "position");
343 checkPositiveOrZero(length, "length");
344 if (!isAccessible()) {
345 throw bufferIsClosed();
346 }
347 if (readOnly()) {
348 throw bufferIsReadOnly(this);
349 }
350 length = Math.min(writableBytes(), length);
351 if (length == 0) {
352 return 0;
353 }
354 checkSet(writerOffset(), length);
355 int bytesRead = channel.read(writableBuffer().limit(length), position);
356 if (bytesRead > 0) {
357 skipWritableBytes(bytesRead);
358 }
359 return bytesRead;
360 }
361
362 @Override
363 public int transferFrom(ReadableByteChannel channel, int length) throws IOException {
364 if (!isAccessible()) {
365 throw bufferIsClosed();
366 }
367 if (readOnly()) {
368 throw bufferIsReadOnly(this);
369 }
370 length = Math.min(writableBytes(), length);
371 if (length == 0) {
372 return 0;
373 }
374 checkSet(writerOffset(), length);
375 int bytesRead = channel.read(writableBuffer().limit(length));
376 if (bytesRead != -1) {
377 skipWritableBytes(bytesRead);
378 }
379 return bytesRead;
380 }
381
382
383
384
385
386 private static final boolean BYTES_BEFORE_USE_LITTLE_ENDIAN =
387 PlatformDependent.isUnaligned() && ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN;
388
389 @Override
390 public int bytesBefore(byte needle) {
391
392
393 if (!isAccessible()) {
394 throw bufferIsClosed();
395 }
396 try {
397 int offset = roff;
398 final int length = woff - roff;
399 final int end = woff;
400 final long addr = address;
401
402 if (length > 7) {
403 final long pattern = (needle & 0xFFL) * 0x101010101010101L;
404 for (final int longEnd = offset + (length >>> 3) * Long.BYTES;
405 offset < longEnd;
406 offset += Long.BYTES) {
407 final long word = BYTES_BEFORE_USE_LITTLE_ENDIAN?
408 PlatformDependent.getLong(base, addr + offset) :
409 loadLong(addr + offset);
410
411 final long input = word ^ pattern;
412 final long tmp =
413 ~((input & 0x7F7F7F7F7F7F7F7FL) + 0x7F7F7F7F7F7F7F7FL | input | 0x7F7F7F7F7F7F7F7FL);
414 final int binaryPosition = BYTES_BEFORE_USE_LITTLE_ENDIAN?
415 Long.numberOfTrailingZeros(tmp) :
416 Long.numberOfLeadingZeros(tmp);
417
418 if (binaryPosition < Long.SIZE) {
419 return offset + (binaryPosition >>> 3) - roff;
420 }
421 }
422 }
423 for (; offset < end; offset++) {
424 if (loadByte(addr + offset) == needle) {
425 return offset - roff;
426 }
427 }
428
429 return -1;
430 } finally {
431 Reference.reachabilityFence(memory);
432 }
433 }
434
435 @Override
436 public int bytesBefore(Buffer needle) {
437 try {
438 UncheckedLoadByte uncheckedLoadByte = UnsafeBuffer::uncheckedLoadByte;
439 return Statics.bytesBefore(this, uncheckedLoadByte,
440 needle, needle instanceof UnsafeBuffer ? uncheckedLoadByte : null);
441 } finally {
442 Reference.reachabilityFence(memory);
443 }
444 }
445
446
447
448
449 private static byte uncheckedLoadByte(Buffer buffer, int offset) {
450 UnsafeBuffer unsafeBuffer = (UnsafeBuffer) buffer;
451 return UNSAFE.getByte(unsafeBuffer.base, unsafeBuffer.address + offset);
452 }
453
454 @Override
455 public ByteCursor openCursor() {
456 return openCursor(readerOffset(), readableBytes());
457 }
458
459 @Override
460 public ByteCursor openCursor(int fromOffset, int length) {
461 if (rsize == CLOSED_SIZE) {
462 throw bufferIsClosed();
463 }
464 if (fromOffset < 0) {
465 throw new IndexOutOfBoundsException("The fromOffset cannot be negative: " + fromOffset + '.');
466 }
467 checkLength(length);
468 if (capacity() < fromOffset + length) {
469 throw new IndexOutOfBoundsException("The fromOffset + length is beyond the end of the buffer: " +
470 "fromOffset = " + fromOffset + ", length = " + length + '.');
471 }
472 return new ForwardUnsafeByteCursor(memory, base, address, fromOffset, length);
473 }
474
475 @Override
476 public ByteCursor openReverseCursor(int fromOffset, int length) {
477 if (rsize == CLOSED_SIZE) {
478 throw bufferIsClosed();
479 }
480 if (fromOffset < 0) {
481 throw new IndexOutOfBoundsException("The fromOffset cannot be negative: " + fromOffset + '.');
482 }
483 checkLength(length);
484 if (capacity() <= fromOffset) {
485 throw new IndexOutOfBoundsException("The fromOffset is beyond the end of the buffer: " + fromOffset + '.');
486 }
487 if (fromOffset - length < -1) {
488 throw new IndexOutOfBoundsException("The fromOffset - length would underflow the buffer: " +
489 "fromOffset = " + fromOffset + ", length = " + length + '.');
490 }
491 return new ReverseUnsafeByteCursor(memory, base, address, fromOffset, length);
492 }
493
494 @Override
495 public Buffer ensureWritable(int size, int minimumGrowth, boolean allowCompaction) {
496 if (!isAccessible()) {
497 throw bufferIsClosed();
498 }
499 if (!isOwned()) {
500 throw attachTrace(new IllegalStateException(
501 "Buffer is not owned. Only owned buffers can call ensureWritable."));
502 }
503 if (size < 0) {
504 throw new IllegalArgumentException("Cannot ensure writable for a negative size: " + size + '.');
505 }
506 if (minimumGrowth < 0) {
507 throw new IllegalArgumentException("The minimum growth cannot be negative: " + minimumGrowth + '.');
508 }
509 if (rsize != wsize) {
510 throw bufferIsReadOnly(this);
511 }
512 if (writableBytes() >= size) {
513
514 return this;
515 }
516
517 if (allowCompaction && writableBytes() + readerOffset() >= size) {
518
519 return compact();
520 }
521
522
523 long newSize = capacity() + (long) Math.max(size - writableBytes(), minimumGrowth);
524 Statics.assertValidBufferSize(newSize);
525 UnsafeBuffer buffer = (UnsafeBuffer) control.getAllocator().allocate((int) newSize);
526
527
528 try {
529 copyInto(0, buffer, 0, capacity());
530 } finally {
531 Reference.reachabilityFence(memory);
532 Reference.reachabilityFence(buffer.memory);
533 }
534
535
536 Drop<UnsafeBuffer> drop = buffer.unsafeGetDrop();
537 disconnectDrop(drop);
538 attachNewMemory(buffer.memory, drop);
539 return this;
540 }
541
542 private Drop<UnsafeBuffer> disconnectDrop(Drop<UnsafeBuffer> newDrop) {
543 var drop = (Drop<UnsafeBuffer>) unsafeGetDrop();
544 int roff = this.roff;
545 int woff = this.woff;
546 drop.drop(this);
547 unsafeSetDrop(newDrop);
548 this.roff = roff;
549 this.woff = woff;
550 return drop;
551 }
552
553 private void attachNewMemory(UnsafeMemory memory, Drop<UnsafeBuffer> drop) {
554 this.memory = memory;
555 base = memory.base;
556 baseOffset = 0;
557 address = memory.address;
558 rsize = memory.size;
559 wsize = memory.size;
560 drop.attach(this);
561 }
562
563 @Override
564 public Buffer split(int splitOffset) {
565 if (splitOffset < 0) {
566 throw new IllegalArgumentException("The split offset cannot be negative: " + splitOffset + '.');
567 }
568 if (capacity() < splitOffset) {
569 throw new IllegalArgumentException("The split offset cannot be greater than the buffer capacity, " +
570 "but the split offset was " + splitOffset + ", and capacity is " + capacity() + '.');
571 }
572 if (!isAccessible()) {
573 throw bufferIsClosed();
574 }
575 if (!isOwned()) {
576 throw attachTrace(new IllegalStateException("Cannot split a buffer that is not owned."));
577 }
578 var drop = unsafeGetDrop().fork();
579 var splitBuffer = new UnsafeBuffer(memory, baseOffset, splitOffset, control, drop);
580 drop.attach(splitBuffer);
581 splitBuffer.woff = Math.min(woff, splitOffset);
582 splitBuffer.roff = Math.min(roff, splitOffset);
583 boolean readOnly = readOnly();
584 if (readOnly) {
585 splitBuffer.makeReadOnly();
586 }
587
588 rsize -= splitOffset;
589 baseOffset += splitOffset;
590 address += splitOffset;
591 if (!readOnly) {
592 wsize = rsize;
593 }
594 woff = Math.max(woff, splitOffset) - splitOffset;
595 roff = Math.max(roff, splitOffset) - splitOffset;
596 return splitBuffer;
597 }
598
599 @Override
600 public Buffer compact() {
601 if (!isAccessible()) {
602 throw bufferIsClosed();
603 }
604 if (!isOwned()) {
605 throw attachTrace(new IllegalStateException("Buffer must be owned in order to compact."));
606 }
607 if (readOnly()) {
608 throw new BufferReadOnlyException("Buffer must be writable in order to compact, but was read-only.");
609 }
610 if (roff == 0) {
611 return this;
612 }
613 try {
614 PlatformDependent.copyMemory(base, address + roff, base, address, woff - roff);
615 } finally {
616 Reference.reachabilityFence(memory);
617 }
618 woff -= roff;
619 roff = 0;
620 return this;
621 }
622
623 @Override
624 public int countComponents() {
625 return 1;
626 }
627
628 @Override
629 public int countReadableComponents() {
630 return readableBytes() > 0? 1 : 0;
631 }
632
633 @Override
634 public int countWritableComponents() {
635 return writableBytes() > 0? 1 : 0;
636 }
637
638
639 @Override
640 public boolean hasReadableArray() {
641 return base instanceof byte[];
642 }
643
644 @Override
645 public byte[] readableArray() {
646 checkHasReadableArray();
647 return (byte[]) base;
648 }
649
650 @Override
651 public int readableArrayOffset() {
652 checkHasReadableArray();
653 return Math.toIntExact(address + roff - PlatformDependent.byteArrayBaseOffset());
654 }
655
656 private void checkHasReadableArray() {
657 if (!hasReadableArray()) {
658 throw new UnsupportedOperationException("No readable array available.");
659 }
660 }
661
662 @Override
663 public int readableArrayLength() {
664 return woff - roff;
665 }
666
667 @Override
668 public long readableNativeAddress() {
669 return nativeAddressWithOffset(nativeAddress(), roff);
670 }
671
672 @Override
673 public ByteBuffer readableBuffer() {
674 return mutableReadableBuffer().asReadOnlyBuffer();
675 }
676
677 @Override
678 public ByteBuffer mutableReadableBuffer() {
679 final ByteBuffer buf;
680 if (hasReadableArray()) {
681 buf = bbslice(ByteBuffer.wrap(readableArray()), readableArrayOffset(), readableArrayLength());
682 } else {
683 buf = PlatformDependent.directBuffer(address + roff, readableBytes(), memory);
684 }
685 return buf;
686 }
687
688 @Override
689 public boolean hasWritableArray() {
690 return hasReadableArray();
691 }
692
693 @Override
694 public byte[] writableArray() {
695 checkHasWritableArray();
696 return (byte[]) base;
697 }
698
699 @Override
700 public int writableArrayOffset() {
701 checkHasWritableArray();
702 return Math.toIntExact(address + woff - PlatformDependent.byteArrayBaseOffset());
703 }
704
705 private void checkHasWritableArray() {
706 if (!hasReadableArray()) {
707 throw new UnsupportedOperationException("No writable array available.");
708 }
709 }
710
711 @Override
712 public int writableArrayLength() {
713 return capacity() - woff;
714 }
715
716 @Override
717 public long writableNativeAddress() {
718 return nativeAddressWithOffset(nativeAddress(), woff);
719 }
720
721 @Override
722 public ByteBuffer writableBuffer() {
723 final ByteBuffer buf;
724 if (hasWritableArray()) {
725 buf = bbslice(ByteBuffer.wrap(writableArray()), writableArrayOffset(), writableArrayLength());
726 } else {
727 buf = PlatformDependent.directBuffer(address + woff, writableBytes(), memory);
728 }
729 return buf;
730 }
731
732 @Override
733 public <N extends Next> N next() {
734 return null;
735 }
736
737
738 @Override
739 public <E extends Exception> int forEachReadable(int initialIndex, ReadableComponentProcessor<E> processor)
740 throws E {
741 if (!isAccessible()) {
742 throw bufferIsClosed();
743 }
744 int readableBytes = readableBytes();
745 if (readableBytes == 0) {
746 return 0;
747 }
748 checkRead(readerOffset(), readableBytes);
749 try {
750 return processor.process(initialIndex, this)? 1 : -1;
751 } finally {
752 Reference.reachabilityFence(this);
753 }
754 }
755
756 @Override
757 public <T extends ReadableComponent & Next> ComponentIterator<T> forEachReadable() {
758 return new SingleComponentIterator<>(acquire(), readableBytes() > 0 ? this : null);
759 }
760
761 @Override
762 public <E extends Exception> int forEachWritable(int initialIndex, WritableComponentProcessor<E> processor)
763 throws E {
764 if (!isAccessible()) {
765 throw bufferIsClosed();
766 }
767 int writableBytes = writableBytes();
768 if (writableBytes == 0) {
769 return 0;
770 }
771 checkWrite(writerOffset(), writableBytes, false);
772 try {
773 return processor.process(initialIndex, this)? 1 : -1;
774 } finally {
775 Reference.reachabilityFence(this);
776 }
777 }
778
779 @Override
780 public <T extends WritableComponent & Next> ComponentIterator<T> forEachWritable() {
781 checkWrite(writerOffset(), writableBytes(), false);
782 return new SingleComponentIterator<>(acquire(), writableBytes() > 0 ? this : null);
783 }
784
785
786 @Override
787 public byte readByte() {
788 checkRead(roff, Byte.BYTES);
789 try {
790 var value = loadByte(address + roff);
791 roff += Byte.BYTES;
792 return value;
793 } finally {
794 Reference.reachabilityFence(memory);
795 }
796 }
797
798 @Override
799 public byte getByte(int roff) {
800 checkGet(roff, Byte.BYTES);
801 try {
802 return loadByte(address + roff);
803 } finally {
804 Reference.reachabilityFence(memory);
805 }
806 }
807
808 @Override
809 public int readUnsignedByte() {
810 return readByte() & 0xFF;
811 }
812
813 @Override
814 public int getUnsignedByte(int roff) {
815 return getByte(roff) & 0xFF;
816 }
817
818 @Override
819 public Buffer writeByte(byte value) {
820 checkWrite(woff, Byte.BYTES, true);
821 long offset = address + woff;
822 woff += Byte.BYTES;
823 try {
824 storeByte(offset, value);
825 } finally {
826 Reference.reachabilityFence(memory);
827 }
828 return this;
829 }
830
831 @Override
832 public Buffer setByte(int woff, byte value) {
833 checkSet(woff, Byte.BYTES);
834 long offset = address + woff;
835 try {
836 storeByte(offset, value);
837 } finally {
838 Reference.reachabilityFence(memory);
839 }
840 return this;
841 }
842
843 @Override
844 public Buffer writeUnsignedByte(int value) {
845 checkWrite(woff, Byte.BYTES, true);
846 long offset = address + woff;
847 woff += Byte.BYTES;
848 try {
849 storeByte(offset, (byte) (value & 0xFF));
850 } finally {
851 Reference.reachabilityFence(memory);
852 }
853 return this;
854 }
855
856 @Override
857 public Buffer setUnsignedByte(int woff, int value) {
858 checkSet(woff, Byte.BYTES);
859 long offset = address + woff;
860 try {
861 storeByte(offset, (byte) (value & 0xFF));
862 } finally {
863 Reference.reachabilityFence(memory);
864 }
865 return this;
866 }
867
868 @Override
869 public char readChar() {
870 checkRead(roff, Character.BYTES);
871 try {
872 long offset = address + roff;
873 roff += Character.BYTES;
874 return loadChar(offset);
875 } finally {
876 Reference.reachabilityFence(memory);
877 }
878 }
879
880 @Override
881 public char getChar(int roff) {
882 checkGet(roff, Character.BYTES);
883 try {
884 long offset = address + roff;
885 return loadChar(offset);
886 } finally {
887 Reference.reachabilityFence(memory);
888 }
889 }
890
891 @Override
892 public Buffer writeChar(char value) {
893 checkWrite(woff, Character.BYTES, true);
894 long offset = address + woff;
895 woff += Character.BYTES;
896 try {
897 storeChar(offset, value);
898 } finally {
899 Reference.reachabilityFence(memory);
900 }
901 return this;
902 }
903
904 @Override
905 public Buffer setChar(int woff, char value) {
906 checkSet(woff, Character.BYTES);
907 long offset = address + woff;
908 try {
909 storeChar(offset, value);
910 } finally {
911 Reference.reachabilityFence(memory);
912 }
913 return this;
914 }
915
916 @Override
917 public short readShort() {
918 checkRead(roff, Short.BYTES);
919 try {
920 long offset = address + roff;
921 roff += Short.BYTES;
922 return loadShort(offset);
923 } finally {
924 Reference.reachabilityFence(memory);
925 }
926 }
927
928 @Override
929 public short getShort(int roff) {
930 checkGet(roff, Short.BYTES);
931 try {
932 long offset = address + roff;
933 return loadShort(offset);
934 } finally {
935 Reference.reachabilityFence(memory);
936 }
937 }
938
939 @Override
940 public int readUnsignedShort() {
941 return readShort() & 0xFFFF;
942 }
943
944 @Override
945 public int getUnsignedShort(int roff) {
946 return getShort(roff) & 0xFFFF;
947 }
948
949 @Override
950 public Buffer writeShort(short value) {
951 checkWrite(woff, Short.BYTES, true);
952 long offset = address + woff;
953 woff += Short.BYTES;
954 try {
955 storeShort(offset, value);
956 } finally {
957 Reference.reachabilityFence(memory);
958 }
959 return this;
960 }
961
962 @Override
963 public Buffer setShort(int woff, short value) {
964 checkSet(woff, Short.BYTES);
965 long offset = address + woff;
966 try {
967 storeShort(offset, value);
968 } finally {
969 Reference.reachabilityFence(memory);
970 }
971 return this;
972 }
973
974 @Override
975 public Buffer writeUnsignedShort(int value) {
976 checkWrite(woff, Short.BYTES, true);
977 long offset = address + woff;
978 woff += Short.BYTES;
979 try {
980 storeShort(offset, (short) (value & 0xFFFF));
981 } finally {
982 Reference.reachabilityFence(memory);
983 }
984 return this;
985 }
986
987 @Override
988 public Buffer setUnsignedShort(int woff, int value) {
989 checkSet(woff, Short.BYTES);
990 long offset = address + woff;
991 try {
992 storeShort(offset, (short) (value & 0xFFFF));
993 } finally {
994 Reference.reachabilityFence(memory);
995 }
996 return this;
997 }
998
999 @Override
1000 public int readMedium() {
1001 checkRead(roff, 3);
1002 long offset = address + roff;
1003 int value = loadByte(offset) << 16 | (loadByte(offset + 1) & 0xFF) << 8 | loadByte(offset + 2) & 0xFF;
1004 roff += 3;
1005 return value;
1006 }
1007
1008 @Override
1009 public int getMedium(int roff) {
1010 checkGet(roff, 3);
1011 long offset = address + roff;
1012 return loadByte(offset) << 16 | (loadByte(offset + 1) & 0xFF) << 8 | loadByte(offset + 2) & 0xFF;
1013 }
1014
1015 @Override
1016 public int readUnsignedMedium() {
1017 checkRead(roff, 3);
1018 long offset = address + roff;
1019 int value =
1020 (loadByte(offset) << 16 | (loadByte(offset + 1) & 0xFF) << 8 | loadByte(offset + 2) & 0xFF) & 0xFFFFFF;
1021 roff += 3;
1022 return value;
1023 }
1024
1025 @Override
1026 public int getUnsignedMedium(int roff) {
1027 checkGet(roff, 3);
1028 long offset = address + roff;
1029 return (loadByte(offset) << 16 | (loadByte(offset + 1) & 0xFF) << 8 | loadByte(offset + 2) & 0xFF) & 0xFFFFFF;
1030 }
1031
1032 @Override
1033 public Buffer writeMedium(int value) {
1034 checkWrite(woff, 3, true);
1035 long offset = address + woff;
1036 storeByte(offset, (byte) (value >> 16));
1037 storeByte(offset + 1, (byte) (value >> 8 & 0xFF));
1038 storeByte(offset + 2, (byte) (value & 0xFF));
1039 woff += 3;
1040 return this;
1041 }
1042
1043 @Override
1044 public Buffer setMedium(int woff, int value) {
1045 checkSet(woff, 3);
1046 long offset = address + woff;
1047 storeByte(offset, (byte) (value >> 16));
1048 storeByte(offset + 1, (byte) (value >> 8 & 0xFF));
1049 storeByte(offset + 2, (byte) (value & 0xFF));
1050 return this;
1051 }
1052
1053 @Override
1054 public Buffer writeUnsignedMedium(int value) {
1055 checkWrite(woff, 3, true);
1056 long offset = address + woff;
1057 storeByte(offset, (byte) (value >> 16));
1058 storeByte(offset + 1, (byte) (value >> 8 & 0xFF));
1059 storeByte(offset + 2, (byte) (value & 0xFF));
1060 woff += 3;
1061 return this;
1062 }
1063
1064 @Override
1065 public Buffer setUnsignedMedium(int woff, int value) {
1066 checkSet(woff, 3);
1067 long offset = address + woff;
1068 storeByte(offset, (byte) (value >> 16));
1069 storeByte(offset + 1, (byte) (value >> 8 & 0xFF));
1070 storeByte(offset + 2, (byte) (value & 0xFF));
1071 return this;
1072 }
1073
1074 @Override
1075 public int readInt() {
1076 checkRead(roff, Integer.BYTES);
1077 try {
1078 long offset = address + roff;
1079 roff += Integer.BYTES;
1080 return loadInt(offset);
1081 } finally {
1082 Reference.reachabilityFence(memory);
1083 }
1084 }
1085
1086 @Override
1087 public int getInt(int roff) {
1088 checkGet(roff, Integer.BYTES);
1089 try {
1090 long offset = address + roff;
1091 return loadInt(offset);
1092 } finally {
1093 Reference.reachabilityFence(memory);
1094 }
1095 }
1096
1097 @Override
1098 public long readUnsignedInt() {
1099 return readInt() & 0x0000_0000_FFFF_FFFFL;
1100 }
1101
1102 @Override
1103 public long getUnsignedInt(int roff) {
1104 return getInt(roff) & 0x0000_0000_FFFF_FFFFL;
1105 }
1106
1107 @Override
1108 public Buffer writeInt(int value) {
1109 checkWrite(woff, Integer.BYTES, true);
1110 long offset = address + woff;
1111 woff += Integer.BYTES;
1112 try {
1113 storeInt(offset, value);
1114 } finally {
1115 Reference.reachabilityFence(memory);
1116 }
1117 return this;
1118 }
1119
1120 @Override
1121 public Buffer setInt(int woff, int value) {
1122 checkSet(woff, Integer.BYTES);
1123 long offset = address + woff;
1124 try {
1125 storeInt(offset, value);
1126 } finally {
1127 Reference.reachabilityFence(memory);
1128 }
1129 return this;
1130 }
1131
1132 @Override
1133 public Buffer writeUnsignedInt(long value) {
1134 checkWrite(woff, Integer.BYTES, true);
1135 long offset = address + woff;
1136 woff += Integer.BYTES;
1137 try {
1138 storeInt(offset, (int) (value & 0xFFFF_FFFFL));
1139 } finally {
1140 Reference.reachabilityFence(memory);
1141 }
1142 return this;
1143 }
1144
1145 @Override
1146 public Buffer setUnsignedInt(int woff, long value) {
1147 checkSet(woff, Integer.BYTES);
1148 long offset = address + woff;
1149 try {
1150 storeInt(offset, (int) (value & 0xFFFF_FFFFL));
1151 } finally {
1152 Reference.reachabilityFence(memory);
1153 }
1154 return this;
1155 }
1156
1157 @Override
1158 public float readFloat() {
1159 checkRead(roff, Float.BYTES);
1160 try {
1161 long offset = address + roff;
1162 roff += Float.BYTES;
1163 return loadFloat(offset);
1164 } finally {
1165 Reference.reachabilityFence(memory);
1166 }
1167 }
1168
1169 @Override
1170 public float getFloat(int roff) {
1171 checkGet(roff, Float.BYTES);
1172 try {
1173 long offset = address + roff;
1174 return loadFloat(offset);
1175 } finally {
1176 Reference.reachabilityFence(memory);
1177 }
1178 }
1179
1180 @Override
1181 public Buffer writeFloat(float value) {
1182 checkWrite(woff, Float.BYTES, true);
1183 long offset = address + woff;
1184 woff += Float.BYTES;
1185 try {
1186 storeFloat(offset, value);
1187 } finally {
1188 Reference.reachabilityFence(memory);
1189 }
1190 return this;
1191 }
1192
1193 @Override
1194 public Buffer setFloat(int woff, float value) {
1195 checkSet(woff, Float.BYTES);
1196 long offset = address + woff;
1197 try {
1198 storeFloat(offset, value);
1199 } finally {
1200 Reference.reachabilityFence(memory);
1201 }
1202 return this;
1203 }
1204
1205 @Override
1206 public long readLong() {
1207 checkRead(roff, Long.BYTES);
1208 try {
1209 long offset = address + roff;
1210 roff += Long.BYTES;
1211 return loadLong(offset);
1212 } finally {
1213 Reference.reachabilityFence(memory);
1214 }
1215 }
1216
1217 @Override
1218 public long getLong(int roff) {
1219 checkGet(roff, Long.BYTES);
1220 try {
1221 long offset = address + roff;
1222 return loadLong(offset);
1223 } finally {
1224 Reference.reachabilityFence(memory);
1225 }
1226 }
1227
1228 @Override
1229 public Buffer writeLong(long value) {
1230 checkWrite(woff, Long.BYTES, true);
1231 long offset = address + woff;
1232 woff += Long.BYTES;
1233 try {
1234 storeLong(offset, value);
1235 } finally {
1236 Reference.reachabilityFence(memory);
1237 }
1238 return this;
1239 }
1240
1241 @Override
1242 public Buffer setLong(int woff, long value) {
1243 checkSet(woff, Long.BYTES);
1244 long offset = address + woff;
1245 try {
1246 storeLong(offset, value);
1247 } finally {
1248 Reference.reachabilityFence(memory);
1249 }
1250 return this;
1251 }
1252
1253 @Override
1254 public double readDouble() {
1255 checkRead(roff, Double.BYTES);
1256 try {
1257 long offset = address + roff;
1258 roff += Double.BYTES;
1259 return loadDouble(offset);
1260 } finally {
1261 Reference.reachabilityFence(memory);
1262 }
1263 }
1264
1265 @Override
1266 public double getDouble(int roff) {
1267 checkGet(roff, Double.BYTES);
1268 try {
1269 long offset = address + roff;
1270 return loadDouble(offset);
1271 } finally {
1272 Reference.reachabilityFence(memory);
1273 }
1274 }
1275
1276 @Override
1277 public Buffer writeDouble(double value) {
1278 checkWrite(woff, Double.BYTES, true);
1279 long offset = address + woff;
1280 woff += Double.BYTES;
1281 try {
1282 storeDouble(offset, value);
1283 } finally {
1284 Reference.reachabilityFence(memory);
1285 }
1286 return this;
1287 }
1288
1289 @Override
1290 public Buffer setDouble(int woff, double value) {
1291 checkSet(woff, Double.BYTES);
1292 long offset = address + woff;
1293 try {
1294 storeDouble(offset, value);
1295 } finally {
1296 Reference.reachabilityFence(memory);
1297 }
1298 return this;
1299 }
1300
1301
1302 @Override
1303 protected Owned<UnsafeBuffer> prepareSend() {
1304 int roff = this.roff;
1305 int woff = this.woff;
1306 boolean readOnly = readOnly();
1307 int implicitCapacityLimit = this.implicitCapacityLimit;
1308 UnsafeMemory memory = this.memory;
1309 AllocatorControl control = this.control;
1310 long baseOffset = this.baseOffset;
1311 int rsize = this.rsize;
1312 return drop -> {
1313 UnsafeBuffer copy = new UnsafeBuffer(memory, baseOffset, rsize, control, drop);
1314 copy.roff = roff;
1315 copy.woff = woff;
1316 copy.implicitCapacityLimit = implicitCapacityLimit;
1317 if (readOnly) {
1318 copy.makeReadOnly();
1319 }
1320 return copy;
1321 };
1322 }
1323
1324 @Override
1325 protected void makeInaccessible() {
1326 roff = 0;
1327 woff = 0;
1328 rsize = CLOSED_SIZE;
1329 wsize = CLOSED_SIZE;
1330 readOnly = false;
1331 }
1332
1333 private void checkRead(int index, int size) {
1334 if (index < 0 | woff < index + size) {
1335 throw readAccessCheckException(index, size);
1336 }
1337 }
1338
1339 private void checkGet(int index, int size) {
1340 if (index < 0 | rsize < index + size) {
1341 throw readAccessCheckException(index, size);
1342 }
1343 }
1344
1345 private void checkWrite(int index, int size, boolean mayExpand) {
1346 if (index < roff | wsize < index + size) {
1347 handleWriteAccessBoundsFailure(index, size, mayExpand);
1348 }
1349 }
1350
1351 private void checkSet(int index, int size) {
1352 if (index < 0 | wsize < index + size) {
1353 handleWriteAccessBoundsFailure(index, size, false);
1354 }
1355 }
1356
1357 private RuntimeException readAccessCheckException(int index, int size) {
1358 if (rsize == CLOSED_SIZE) {
1359 throw bufferIsClosed();
1360 }
1361 return outOfBounds(index, size);
1362 }
1363
1364 private void handleWriteAccessBoundsFailure(int index, int size, boolean mayExpand) {
1365 if (rsize == CLOSED_SIZE) {
1366 throw bufferIsClosed();
1367 }
1368 if (wsize != rsize) {
1369 throw bufferIsReadOnly(this);
1370 }
1371 int capacity = capacity();
1372 if (mayExpand && index >= 0 && index <= capacity && woff + size <= implicitCapacityLimit && isOwned()) {
1373
1374 int minimumGrowth = Math.min(
1375 Math.max(roundToPowerOfTwo(capacity * 2), size),
1376 implicitCapacityLimit) - capacity;
1377 ensureWritable(size, minimumGrowth, false);
1378 checkSet(index, size);
1379 return;
1380 }
1381 throw outOfBounds(index, size);
1382 }
1383
1384 private BufferClosedException bufferIsClosed() {
1385 return attachTrace(Statics.bufferIsClosed(this));
1386 }
1387
1388 private IndexOutOfBoundsException outOfBounds(int index, int size) {
1389 return new IndexOutOfBoundsException(
1390 "Access at index " + index + " of size " + size + " is out of bounds: " +
1391 "[read 0 to " + woff + ", write 0 to " + rsize + "].");
1392 }
1393
1394 private byte loadByte(long off) {
1395 return PlatformDependent.getByte(base, off);
1396 }
1397
1398 private char loadChar(long offset) {
1399 if (ACCESS_UNALIGNED) {
1400 var value = PlatformDependent.getChar(base, offset);
1401 return FLIP_BYTES? Character.reverseBytes(value) : value;
1402 }
1403 return loadCharUnaligned(offset);
1404 }
1405
1406 private char loadCharUnaligned(long offset) {
1407 final char value;
1408 Object b = base;
1409 if ((offset & 1) == 0) {
1410 value = PlatformDependent.getChar(b, offset);
1411 } else {
1412 value = (char) (PlatformDependent.getByte(b, offset) << 8 |
1413 PlatformDependent.getByte(b, offset + 1));
1414 }
1415 return FLIP_BYTES? Character.reverseBytes(value) : value;
1416 }
1417
1418 private short loadShort(long offset) {
1419 if (ACCESS_UNALIGNED) {
1420 var value = PlatformDependent.getShort(base, offset);
1421 return FLIP_BYTES? Short.reverseBytes(value) : value;
1422 }
1423 return loadShortUnaligned(offset);
1424 }
1425
1426 private short loadShortUnaligned(long offset) {
1427 final short value;
1428 Object b = base;
1429 if ((offset & 1) == 0) {
1430 value = PlatformDependent.getShort(b, offset);
1431 } else {
1432 value = (short) (PlatformDependent.getByte(b, offset) << 8 |
1433 PlatformDependent.getByte(b, offset + 1));
1434 }
1435 return FLIP_BYTES? Short.reverseBytes(value) : value;
1436 }
1437
1438 private int loadInt(long offset) {
1439 if (ACCESS_UNALIGNED) {
1440 var value = PlatformDependent.getInt(base, offset);
1441 return FLIP_BYTES? Integer.reverseBytes(value) : value;
1442 }
1443 return loadIntUnaligned(offset);
1444 }
1445
1446 private int loadIntUnaligned(long offset) {
1447 final int value;
1448 Object b = base;
1449 if ((offset & 3) == 0) {
1450 value = PlatformDependent.getInt(b, offset);
1451 } else if ((offset & 1) == 0) {
1452 value = PlatformDependent.getShort(b, offset) << 16 |
1453 PlatformDependent.getShort(b, offset + 2);
1454 } else {
1455 value = PlatformDependent.getByte(b, offset) << 24 |
1456 PlatformDependent.getByte(b, offset + 1) << 16 |
1457 PlatformDependent.getByte(b, offset + 2) << 8 |
1458 PlatformDependent.getByte(b, offset + 3);
1459 }
1460 return FLIP_BYTES? Integer.reverseBytes(value) : value;
1461 }
1462
1463 private float loadFloat(long offset) {
1464 if (ACCESS_UNALIGNED) {
1465 if (FLIP_BYTES) {
1466 var value = PlatformDependent.getInt(base, offset);
1467 return Float.intBitsToFloat(Integer.reverseBytes(value));
1468 }
1469 return PlatformDependent.getFloat(base, offset);
1470 }
1471 return loadFloatUnaligned(offset);
1472 }
1473
1474 private float loadFloatUnaligned(long offset) {
1475 return Float.intBitsToFloat(loadIntUnaligned(offset));
1476 }
1477
1478 private long loadLong(long offset) {
1479 if (ACCESS_UNALIGNED) {
1480 var value = PlatformDependent.getLong(base, offset);
1481 return FLIP_BYTES? Long.reverseBytes(value) : value;
1482 }
1483 return loadLongUnaligned(offset);
1484 }
1485
1486 private long loadLongUnaligned(long offset) {
1487 final long value;
1488 Object b = base;
1489 if ((offset & 7) == 0) {
1490 value = PlatformDependent.getLong(b, offset);
1491 } else if ((offset & 3) == 0) {
1492 value = (long) PlatformDependent.getInt(b, offset) << 32 |
1493 PlatformDependent.getInt(b, offset + 4);
1494 } else if ((offset & 1) == 0) {
1495 value = (long) PlatformDependent.getShort(b, offset) << 48 |
1496 (long) PlatformDependent.getShort(b, offset + 2) << 32 |
1497 (long) PlatformDependent.getShort(b, offset + 4) << 16 |
1498 PlatformDependent.getShort(b, offset + 6);
1499 } else {
1500 value = (long) PlatformDependent.getByte(b, offset) << 54 |
1501 (long) PlatformDependent.getByte(b, offset + 1) << 48 |
1502 (long) PlatformDependent.getByte(b, offset + 2) << 40 |
1503 (long) PlatformDependent.getByte(b, offset + 3) << 32 |
1504 (long) PlatformDependent.getByte(b, offset + 4) << 24 |
1505 (long) PlatformDependent.getByte(b, offset + 5) << 16 |
1506 (long) PlatformDependent.getByte(b, offset + 6) << 8 |
1507 PlatformDependent.getByte(b, offset + 7);
1508 }
1509 return FLIP_BYTES? Long.reverseBytes(value) : value;
1510 }
1511
1512 private double loadDouble(long offset) {
1513 if (ACCESS_UNALIGNED) {
1514 if (FLIP_BYTES) {
1515 var value = PlatformDependent.getLong(base, offset);
1516 return Double.longBitsToDouble(Long.reverseBytes(value));
1517 }
1518 return PlatformDependent.getDouble(base, offset);
1519 }
1520 return loadDoubleUnaligned(offset);
1521 }
1522
1523 private double loadDoubleUnaligned(long offset) {
1524 return Double.longBitsToDouble(loadLongUnaligned(offset));
1525 }
1526
1527 private void storeByte(long offset, byte value) {
1528 PlatformDependent.putByte(base, offset, value);
1529 }
1530
1531 private void storeChar(long offset, char value) {
1532 if (FLIP_BYTES) {
1533 value = Character.reverseBytes(value);
1534 }
1535 if (ACCESS_UNALIGNED) {
1536 PlatformDependent.putChar(base, offset, value);
1537 } else {
1538 storeCharUnaligned(offset, value);
1539 }
1540 }
1541
1542 private void storeCharUnaligned(long offset, char value) {
1543 Object b = base;
1544 if ((offset & 1) == 0) {
1545 PlatformDependent.putChar(b, offset, value);
1546 } else {
1547 PlatformDependent.putByte(b, offset, (byte) (value >> 8));
1548 PlatformDependent.putByte(b, offset + 1, (byte) value);
1549 }
1550 }
1551
1552 private void storeShort(long offset, short value) {
1553 if (FLIP_BYTES) {
1554 value = Short.reverseBytes(value);
1555 }
1556 if (ACCESS_UNALIGNED) {
1557 PlatformDependent.putShort(base, offset, value);
1558 } else {
1559 storeShortUnaligned(offset, value);
1560 }
1561 }
1562
1563 private void storeShortUnaligned(long offset, short value) {
1564 Object b = base;
1565 if ((offset & 1) == 0) {
1566 PlatformDependent.putShort(b, offset, value);
1567 } else {
1568 PlatformDependent.putByte(b, offset, (byte) (value >> 8));
1569 PlatformDependent.putByte(b, offset + 1, (byte) value);
1570 }
1571 }
1572
1573 private void storeInt(long offset, int value) {
1574 if (FLIP_BYTES) {
1575 value = Integer.reverseBytes(value);
1576 }
1577 if (ACCESS_UNALIGNED) {
1578 PlatformDependent.putInt(base, offset, value);
1579 } else {
1580 storeIntUnaligned(offset, value);
1581 }
1582 }
1583
1584 private void storeIntUnaligned(long offset, int value) {
1585 Object b = base;
1586 if ((offset & 3) == 0) {
1587 PlatformDependent.putInt(b, offset, value);
1588 } else if ((offset & 1) == 0) {
1589 PlatformDependent.putShort(b, offset, (short) (value >> 16));
1590 PlatformDependent.putShort(b, offset + 2, (short) value);
1591 } else {
1592 PlatformDependent.putByte(b, offset, (byte) (value >> 24));
1593 PlatformDependent.putByte(b, offset + 1, (byte) (value >> 16));
1594 PlatformDependent.putByte(b, offset + 2, (byte) (value >> 8));
1595 PlatformDependent.putByte(b, offset + 3, (byte) value);
1596 }
1597 }
1598
1599 private void storeFloat(long offset, float value) {
1600 storeInt(offset, Float.floatToRawIntBits(value));
1601 }
1602
1603 private void storeLong(long offset, long value) {
1604 if (FLIP_BYTES) {
1605 value = Long.reverseBytes(value);
1606 }
1607 if (ACCESS_UNALIGNED) {
1608 PlatformDependent.putLong(base, offset, value);
1609 } else {
1610 storeLongUnaligned(offset, value);
1611 }
1612 }
1613
1614 private void storeLongUnaligned(long offset, long value) {
1615 Object b = base;
1616 if ((offset & 7) == 0) {
1617 PlatformDependent.putLong(b, offset, value);
1618 } else if ((offset & 3) == 0) {
1619 PlatformDependent.putInt(b, offset, (int) (value >> 32));
1620 PlatformDependent.putInt(b, offset + 4, (int) value);
1621 } else if ((offset & 1) == 0) {
1622 PlatformDependent.putShort(b, offset, (short) (value >> 48));
1623 PlatformDependent.putShort(b, offset + 16, (short) (value >> 32));
1624 PlatformDependent.putShort(b, offset + 32, (short) (value >> 16));
1625 PlatformDependent.putShort(b, offset + 48, (short) value);
1626 } else {
1627 PlatformDependent.putByte(b, offset, (byte) (value >> 56));
1628 PlatformDependent.putByte(b, offset + 1, (byte) (value >> 48));
1629 PlatformDependent.putByte(b, offset + 2, (byte) (value >> 40));
1630 PlatformDependent.putByte(b, offset + 3, (byte) (value >> 32));
1631 PlatformDependent.putByte(b, offset + 4, (byte) (value >> 24));
1632 PlatformDependent.putByte(b, offset + 5, (byte) (value >> 16));
1633 PlatformDependent.putByte(b, offset + 6, (byte) (value >> 8));
1634 PlatformDependent.putByte(b, offset + 7, (byte) value);
1635 }
1636 }
1637
1638 private void storeDouble(long offset, double value) {
1639 storeLong(offset, Double.doubleToRawLongBits(value));
1640 }
1641
1642 Object recover() {
1643 return memory;
1644 }
1645
1646 UnsafeBuffer newConstChild() {
1647 assert readOnly();
1648 Drop<UnsafeBuffer> drop = unsafeGetDrop().fork();
1649 UnsafeBuffer child = new UnsafeBuffer(this, drop);
1650 drop.attach(child);
1651 return child;
1652 }
1653
1654 private static final class ForwardUnsafeByteCursor implements ByteCursor {
1655 final UnsafeMemory memory;
1656 final Object baseObj;
1657 final long baseAddress;
1658 int index;
1659 final int end;
1660 byte byteValue;
1661
1662 ForwardUnsafeByteCursor(UnsafeMemory memory, Object base, long address, int fromOffset, int length) {
1663 this.memory = memory;
1664 baseObj = base;
1665 baseAddress = address;
1666 index = fromOffset;
1667 end = index + length;
1668 byteValue = -1;
1669 }
1670
1671 @Override
1672 public boolean readByte() {
1673 if (index < end) {
1674 try {
1675 byteValue = PlatformDependent.getByte(baseObj, baseAddress + index);
1676 } finally {
1677 Reference.reachabilityFence(memory);
1678 }
1679 index++;
1680 return true;
1681 }
1682 return false;
1683 }
1684
1685 @Override
1686 public byte getByte() {
1687 return byteValue;
1688 }
1689
1690 @Override
1691 public int currentOffset() {
1692 return index;
1693 }
1694
1695 @Override
1696 public int bytesLeft() {
1697 return end - index;
1698 }
1699 }
1700
1701 private static final class ReverseUnsafeByteCursor implements ByteCursor {
1702 final UnsafeMemory memory;
1703 final Object baseObj;
1704 final long baseAddress;
1705 int index;
1706 final int end;
1707 byte byteValue;
1708
1709 ReverseUnsafeByteCursor(UnsafeMemory memory, Object base, long address, int fromOffset, int length) {
1710 this.memory = memory;
1711 baseObj = base;
1712 baseAddress = address;
1713 index = fromOffset;
1714 end = index - length;
1715 byteValue = -1;
1716 }
1717
1718 @Override
1719 public boolean readByte() {
1720 if (index > end) {
1721 try {
1722 byteValue = PlatformDependent.getByte(baseObj, baseAddress + index);
1723 } finally {
1724 Reference.reachabilityFence(memory);
1725 }
1726 index--;
1727 return true;
1728 }
1729 return false;
1730 }
1731
1732 @Override
1733 public byte getByte() {
1734 return byteValue;
1735 }
1736
1737 @Override
1738 public int currentOffset() {
1739 return index;
1740 }
1741
1742 @Override
1743 public int bytesLeft() {
1744 return index - end;
1745 }
1746 }
1747 }