1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.buffer.api;
17
18 import io.netty5.buffer.api.ComponentIterator.Next;
19 import io.netty5.buffer.api.internal.ResourceSupport;
20 import io.netty5.buffer.api.internal.Statics;
21 import io.netty5.util.SafeCloseable;
22 import io.netty5.util.Send;
23
24 import java.io.IOException;
25 import java.nio.ByteBuffer;
26 import java.nio.ReadOnlyBufferException;
27 import java.nio.channels.FileChannel;
28 import java.nio.channels.GatheringByteChannel;
29 import java.nio.channels.ReadableByteChannel;
30 import java.nio.channels.ScatteringByteChannel;
31 import java.nio.channels.WritableByteChannel;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.IdentityHashMap;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.NoSuchElementException;
40 import java.util.Objects;
41 import java.util.function.Function;
42
43 import static io.netty5.buffer.api.internal.Statics.MAX_BUFFER_SIZE;
44 import static io.netty5.buffer.api.internal.Statics.bufferIsClosed;
45 import static io.netty5.buffer.api.internal.Statics.bufferIsReadOnly;
46 import static io.netty5.buffer.api.internal.Statics.checkImplicitCapacity;
47 import static io.netty5.buffer.api.internal.Statics.checkLength;
48 import static io.netty5.util.internal.ObjectUtil.checkPositiveOrZero;
49 import static io.netty5.util.internal.PlatformDependent.roundToPowerOfTwo;
50 import static java.lang.Math.addExact;
51 import static java.lang.Math.toIntExact;
52
53
54
55
56 final class DefaultCompositeBuffer extends ResourceSupport<Buffer, DefaultCompositeBuffer> implements CompositeBuffer {
57 private static final Drop<DefaultCompositeBuffer> COMPOSITE_DROP = new Drop<>() {
58 @Override
59 public void drop(DefaultCompositeBuffer buf) {
60 RuntimeException re = null;
61 for (Buffer b : buf.bufs) {
62 try {
63 b.close();
64 } catch (RuntimeException e) {
65 if (re == null) {
66 re = e;
67 } else {
68 re.addSuppressed(e);
69 }
70 }
71 }
72 }
73
74 @Override
75 public Drop<DefaultCompositeBuffer> fork() {
76 return this;
77 }
78
79 @Override
80 public void attach(DefaultCompositeBuffer obj) {
81 }
82
83 @Override
84 public String toString() {
85 return "COMPOSITE_DROP";
86 }
87 };
88 private static final Buffer[] EMPTY_BUFFER_ARRAY = new Buffer[0];
89
90
91
92
93
94
95
96
97
98
99
100
101 private static final int FIRST_AUTOMATIC_COMPONENT_SIZE = 256;
102
103 private final BufferAllocator allocator;
104 private final TornBufferAccessor tornBufAccessors;
105 private Buffer[] bufs;
106 private int[] offsets;
107 private int capacity;
108 private int roff;
109 private int woff;
110 private int subOffset;
111 private boolean closed;
112 private boolean readOnly;
113 private int implicitCapacityLimit;
114
115
116
117
118 public static CompositeBuffer compose(BufferAllocator allocator, Iterable<Send<Buffer>> sends) {
119 final List<Buffer> bufs;
120 if (sends instanceof Collection) {
121 bufs = new ArrayList<>(((Collection<?>) sends).size());
122 } else {
123 bufs = new ArrayList<>(4);
124 }
125 RuntimeException receiveException = null;
126 for (Send<Buffer> buf: sends) {
127 if (receiveException != null) {
128 try {
129 buf.close();
130 } catch (Exception closeExc) {
131 receiveException.addSuppressed(closeExc);
132 }
133 } else {
134 try {
135 bufs.add(buf.receive());
136 } catch (RuntimeException e) {
137
138
139 receiveException = e;
140 for (Buffer b: bufs) {
141 try {
142 b.close();
143 } catch (Exception closeExc) {
144 receiveException.addSuppressed(closeExc);
145 }
146 }
147 }
148 }
149 }
150 if (receiveException != null) {
151 throw receiveException;
152 }
153 return new DefaultCompositeBuffer(allocator, filterExternalBufs(bufs), COMPOSITE_DROP);
154 }
155
156
157
158
159 public static CompositeBuffer compose(BufferAllocator allocator) {
160 return new DefaultCompositeBuffer(allocator, EMPTY_BUFFER_ARRAY, COMPOSITE_DROP);
161 }
162
163 private static Buffer[] filterExternalBufs(Iterable<Buffer> externals) {
164
165
166
167
168
169
170
171
172 Collector collector = new Collector(externals);
173 collector.collect(externals);
174 return collector.toArray();
175 }
176
177 private static final class Collector {
178 private Buffer[] array;
179 private int index;
180
181 Collector(Iterable<Buffer> externals) {
182 final Map<Buffer, Buffer> dupeCheck;
183 if (externals instanceof Collection) {
184 dupeCheck = new IdentityHashMap<>(((Collection<?>) externals).size());
185 } else {
186 dupeCheck = new IdentityHashMap<>();
187 }
188 int size = 0;
189 for (Buffer buf : externals) {
190 if (dupeCheck.put(buf, buf) != null) {
191
192
193
194
195 closeAllAndThrowDupeException(externals);
196 }
197 size += buf.countComponents();
198 }
199 array = new Buffer[size];
200 }
201
202 private static void closeAllAndThrowDupeException(Iterable<Buffer> externals) {
203 IllegalArgumentException iae = new IllegalArgumentException("Cannot compose duplicate buffers.");
204 for (Buffer toClose : externals) {
205 try {
206 toClose.close();
207 } catch (Exception closeExc) {
208 iae.addSuppressed(closeExc);
209 }
210 }
211 throw iae;
212 }
213
214 void add(Buffer buffer) {
215 if (index == array.length) {
216 array = Arrays.copyOf(array, array.length * 2);
217 }
218 array[index] = buffer;
219 index++;
220 }
221
222 void collect(Iterable<Buffer> externals) {
223 for (Buffer buf : externals) {
224 if (buf.capacity() == 0) {
225 buf.close();
226 } else if (CompositeBuffer.isComposite(buf)) {
227 CompositeBuffer cbuf = (CompositeBuffer) buf;
228 collect(Arrays.asList(cbuf.decomposeBuffer()));
229 } else {
230 add(buf);
231 }
232 }
233 }
234
235 Buffer[] toArray() {
236 int firstReadable = -1;
237 int lastReadable = -1;
238 for (int i = 0; i < index; i++) {
239 if (array[i].readableBytes() != 0) {
240 if (firstReadable == -1) {
241 firstReadable = i;
242 }
243 lastReadable = i;
244 }
245 }
246
247
248 if (firstReadable != -1) {
249
250 for (int i = firstReadable + 1; i < lastReadable; i++) {
251 Buffer buf = array[i];
252 if (buf.readableBytes() == 0) {
253 buf.close();
254 if (i <= index - 2) {
255 System.arraycopy(array, i + 1, array, i, index - i - 1);
256 }
257 i--;
258 index--;
259 lastReadable--;
260 }
261 }
262
263 for (int i = firstReadable + 1; i < index; i++) {
264 Buffer buf = array[i];
265 if (buf.readerOffset() > 0) {
266 buf.readSplit(0).close();
267 }
268 }
269
270 for (int i = 0; i < lastReadable; i++) {
271 Buffer buf = array[i];
272 if (buf.writableBytes() > 0) {
273 array[i] = buf.split();
274 buf.close();
275 }
276 }
277 }
278 return array.length == index? array : Arrays.copyOf(array, index);
279 }
280 }
281
282 private static final class ConcatIterable<T> implements Iterable<T> {
283 private final Iterable<T> first;
284 private final Iterable<T> second;
285
286 ConcatIterable(Iterable<T> first, Iterable<T> second) {
287 this.first = first;
288 this.second = second;
289 }
290
291 @Override
292 public Iterator<T> iterator() {
293 return new ConcatIterator<>(first.iterator(), second.iterator());
294 }
295 }
296
297 private static final class ConcatIterator<T> implements Iterator<T> {
298 private Iterator<T> current;
299 private Iterator<T> next;
300
301 ConcatIterator(Iterator<T> first, Iterator<T> second) {
302 current = first;
303 next = second;
304 }
305
306 @Override
307 public boolean hasNext() {
308 return current != null && current.hasNext() || next != null && next.hasNext();
309 }
310
311 @Override
312 public T next() {
313 while (current != null) {
314 if (current.hasNext()) {
315 return current.next();
316 }
317 current = next;
318 next = null;
319 }
320 throw new NoSuchElementException();
321 }
322 }
323
324 private DefaultCompositeBuffer(BufferAllocator allocator, Buffer[] bufs, Drop<DefaultCompositeBuffer> drop) {
325 super(drop);
326 try {
327 this.allocator = Objects.requireNonNull(allocator, "BufferAllocator cannot be null.");
328 if (bufs.length > 0) {
329 boolean targetReadOnly = bufs[0].readOnly();
330 for (Buffer buf : bufs) {
331 if (buf.readOnly() != targetReadOnly) {
332 throw new IllegalArgumentException("Constituent buffers have inconsistent read-only state.");
333 }
334 }
335 readOnly = targetReadOnly;
336 }
337 this.bufs = bufs;
338 computeBufferOffsets();
339 implicitCapacityLimit = MAX_BUFFER_SIZE;
340 tornBufAccessors = new TornBufferAccessor(this);
341 } catch (Exception e) {
342
343 for (Buffer buf : bufs) {
344 try {
345 buf.close();
346 } catch (Exception closeExc) {
347 e.addSuppressed(closeExc);
348 }
349 }
350 throw e;
351 }
352 }
353
354 private void computeBufferOffsets() {
355 int woff = 0;
356 int roff = 0;
357 if (bufs.length > 0) {
358 boolean woffMidpoint = false;
359 for (Buffer buf : bufs) {
360 if (!woffMidpoint) {
361
362 woff += buf.writerOffset();
363 if (buf.writableBytes() > 0) {
364
365 woffMidpoint = true;
366 }
367 } else if (buf.writerOffset() != 0) {
368
369 throw new AssertionError(
370 "The given buffers cannot be composed because they leave an unwritten gap: " +
371 Arrays.toString(bufs) + '.');
372 }
373 }
374 boolean roffMidpoint = false;
375 for (Buffer buf : bufs) {
376 if (!roffMidpoint) {
377
378 roff += buf.readerOffset();
379 if (buf.readableBytes() > 0 || buf.writableBytes() > 0) {
380 roffMidpoint = true;
381 }
382 } else if (buf.readerOffset() != 0) {
383 throw new AssertionError(
384 "The given buffers cannot be composed because they leave an unread gap: " +
385 Arrays.toString(bufs) + '.');
386 }
387 }
388 }
389
390 this.woff = woff;
391 this.roff = roff;
392
393 offsets = new int[bufs.length];
394 long cap = 0;
395 for (int i = 0; i < bufs.length; i++) {
396 offsets[i] = (int) cap;
397 cap += bufs[i].capacity();
398 }
399 if (cap > MAX_BUFFER_SIZE) {
400 throw new IllegalArgumentException(
401 "Combined size of the constituent buffers is too big. " +
402 "The maximum buffer capacity is " + MAX_BUFFER_SIZE + " (Integer.MAX_VALUE - 8), " +
403 "but the sum of the constituent buffer capacities was " + cap + '.');
404 }
405 capacity = (int) cap;
406 }
407
408 @Override
409 public String toString() {
410 return "Buffer[roff:" + roff + ", woff:" + woff + ", cap:" + capacity + ']';
411 }
412
413 @Override
414 protected RuntimeException createResourceClosedException() {
415 return bufferIsClosed(this);
416 }
417
418 @Override
419 public int capacity() {
420 return capacity;
421 }
422
423 @Override
424 public int readerOffset() {
425 return roff;
426 }
427
428 @Override
429 public CompositeBuffer readerOffset(int index) {
430 checkReadBounds(index, 0);
431 int indexLeft = index;
432 for (Buffer buf : bufs) {
433 buf.readerOffset(Math.min(indexLeft, buf.capacity()));
434 indexLeft = Math.max(0, indexLeft - buf.capacity());
435 }
436 roff = index;
437 return this;
438 }
439
440 @Override
441 public int writerOffset() {
442 return woff;
443 }
444
445 @Override
446 public CompositeBuffer writerOffset(int index) {
447 checkWriteBounds(index, 0);
448 int indexLeft = index;
449 for (Buffer buf : bufs) {
450 buf.writerOffset(Math.min(indexLeft, buf.capacity()));
451 indexLeft = Math.max(0, indexLeft - buf.capacity());
452 }
453 woff = index;
454 return this;
455 }
456
457 @Override
458 public CompositeBuffer fill(byte value) {
459 if (closed) {
460 throw bufferIsClosed(this);
461 }
462 for (Buffer buf : bufs) {
463 buf.fill(value);
464 }
465 return this;
466 }
467
468 @Override
469 public CompositeBuffer makeReadOnly() {
470 for (Buffer buf : bufs) {
471 buf.makeReadOnly();
472 }
473 readOnly = true;
474 return this;
475 }
476
477 @Override
478 public boolean readOnly() {
479 return readOnly;
480 }
481
482 @Override
483 public boolean isDirect() {
484
485 for (Buffer buf : bufs) {
486 if (!buf.isDirect()) {
487 return false;
488 }
489 }
490 return true;
491 }
492
493 @Override
494 public CompositeBuffer implicitCapacityLimit(int limit) {
495 checkImplicitCapacity(limit, capacity());
496 implicitCapacityLimit = limit;
497 return this;
498 }
499
500 @Override
501 public int implicitCapacityLimit() {
502 return implicitCapacityLimit;
503 }
504
505 @Override
506 public CompositeBuffer copy(int offset, int length, boolean readOnly) {
507 checkLength(length);
508 checkGetBounds(offset, length);
509 if (closed) {
510 throw bufferIsClosed(this);
511 }
512 Buffer[] copies;
513
514 if (bufs.length == 0) {
515
516 assert length == 0 && offset == 0;
517 copies = bufs;
518 } else {
519 Buffer choice = (Buffer) chooseBuffer(offset, 0);
520 if (length > 0) {
521 copies = new Buffer[bufs.length];
522 int off = subOffset;
523 int cap = length;
524 int i;
525 int j = 0;
526 for (i = searchOffsets(offset); cap > 0; i++) {
527 var buf = bufs[i];
528 int avail = buf.capacity() - off;
529 copies[j++] = buf.copy(off, Math.min(cap, avail), readOnly);
530 cap -= avail;
531 off = 0;
532 }
533 copies = Arrays.copyOf(copies, j);
534 } else {
535
536 copies = new Buffer[] { choice.copy(subOffset, 0) };
537 }
538 }
539
540 return new DefaultCompositeBuffer(allocator, copies, COMPOSITE_DROP);
541 }
542
543 @Override
544 public void copyInto(int srcPos, byte[] dest, int destPos, int length) {
545 copyInto(srcPos, (s, b, d, l) -> b.copyInto(s, dest, d, l), destPos, length);
546 }
547
548 @Override
549 public void copyInto(int srcPos, ByteBuffer dest, int destPos, int length) {
550 if (dest.isReadOnly()) {
551 throw new ReadOnlyBufferException();
552 }
553 copyInto(srcPos, (s, b, d, l) -> b.copyInto(s, dest, d, l), destPos, length);
554 }
555
556 private void copyInto(int srcPos, CopyInto dest, int destPos, int length) {
557 if (!isAccessible()) {
558 throw attachTrace(bufferIsClosed(this));
559 }
560 if (length < 0) {
561 throw new IndexOutOfBoundsException("Length cannot be negative: " + length + '.');
562 }
563 if (srcPos < 0) {
564 throw indexOutOfBounds(srcPos, false);
565 }
566 if (srcPos + length > capacity) {
567 throw indexOutOfBounds(srcPos + length, false);
568 }
569 while (length > 0) {
570 var buf = (Buffer) chooseBuffer(srcPos, 0);
571 int toCopy = Math.min(buf.capacity() - subOffset, length);
572 dest.copyInto(subOffset, buf, destPos, toCopy);
573 srcPos += toCopy;
574 destPos += toCopy;
575 length -= toCopy;
576 }
577 }
578
579 @FunctionalInterface
580 private interface CopyInto {
581 void copyInto(int srcPos, Buffer src, int destPos, int length);
582 }
583
584 @Override
585 public void copyInto(int srcPos, Buffer dest, int destPos, int length) {
586 if (!isAccessible()) {
587 throw attachTrace(bufferIsClosed(this));
588 }
589 if (length < 0) {
590 throw new IndexOutOfBoundsException("Length cannot be negative: " + length + '.');
591 }
592 if (srcPos < 0) {
593 throw indexOutOfBounds(srcPos, false);
594 }
595 if (addExact(srcPos, length) > capacity) {
596 throw indexOutOfBounds(srcPos + length, false);
597 }
598 if (dest.readOnly()) {
599 throw bufferIsReadOnly(dest);
600 }
601 if (length == 0) {
602 return;
603 }
604
605
606
607 var cursor = openReverseCursor(srcPos + length - 1, length);
608 while (cursor.readByte()) {
609 dest.setByte(destPos + --length, cursor.getByte());
610 }
611 }
612
613 @Override
614 public int transferTo(WritableByteChannel channel, int length) throws IOException {
615 if (!isAccessible()) {
616 throw bufferIsClosed(this);
617 }
618 length = Math.min(readableBytes(), length);
619 if (length == 0) {
620 return 0;
621 }
622 checkReadBounds(readerOffset(), length);
623 ByteBufferCollector collector = new ByteBufferCollector(countReadableComponents());
624 forEachReadable(0, collector);
625 ByteBuffer[] byteBuffers = collector.buffers;
626 int bufferCount = countAndPrepareBuffersForChannelIO(length, byteBuffers);
627 int totalBytesWritten = 0;
628 try {
629 if (channel instanceof GatheringByteChannel) {
630 GatheringByteChannel gatheringChannel = (GatheringByteChannel) channel;
631 totalBytesWritten = toIntExact(gatheringChannel.write(byteBuffers, 0, bufferCount));
632 } else {
633 for (int i = 0; i < bufferCount; i++) {
634 int bytesWritten = channel.write(byteBuffers[i]);
635 totalBytesWritten = addExact(totalBytesWritten, bytesWritten);
636 }
637 }
638 } finally {
639 skipReadableBytes(totalBytesWritten);
640 }
641 return totalBytesWritten;
642 }
643
644 @Override
645 public int transferFrom(FileChannel channel, long position, int length) throws IOException {
646 checkPositiveOrZero(position, "position");
647 checkPositiveOrZero(length, "length");
648 if (!isAccessible()) {
649 throw bufferIsClosed(this);
650 }
651 if (readOnly()) {
652 throw bufferIsReadOnly(this);
653 }
654 length = Math.min(writableBytes(), length);
655 if (length == 0) {
656 return 0;
657 }
658 checkWriteBounds(writerOffset(), length);
659 ByteBufferCollector collector = new ByteBufferCollector(countWritableComponents());
660 forEachWritable(0, collector);
661 ByteBuffer[] byteBuffers = collector.buffers;
662 int bufferCount = countAndPrepareBuffersForChannelIO(length, byteBuffers);
663 int totalBytesRead = 0;
664 try {
665 for (int i = 0; i < bufferCount; i++) {
666 int bytesRead = channel.read(byteBuffers[i], position + totalBytesRead);
667 if (bytesRead == -1) {
668 if (i == 0) {
669 return -1;
670 }
671 break;
672 }
673 totalBytesRead = addExact(totalBytesRead, bytesRead);
674 }
675 } finally {
676 if (totalBytesRead > 0) {
677 skipWritableBytes(totalBytesRead);
678 }
679 }
680 return totalBytesRead;
681 }
682
683 @Override
684 public int transferFrom(ReadableByteChannel channel, int length) throws IOException {
685 if (!isAccessible()) {
686 throw bufferIsClosed(this);
687 }
688 if (readOnly()) {
689 throw bufferIsReadOnly(this);
690 }
691 length = Math.min(writableBytes(), length);
692 if (length == 0) {
693 return 0;
694 }
695 checkWriteBounds(writerOffset(), length);
696 ByteBufferCollector collector = new ByteBufferCollector(countWritableComponents());
697 forEachWritable(0, collector);
698 ByteBuffer[] byteBuffers = collector.buffers;
699 int bufferCount = countAndPrepareBuffersForChannelIO(length, byteBuffers);
700 int totalBytesRead = 0;
701 try {
702 if (channel instanceof ScatteringByteChannel) {
703 ScatteringByteChannel scatteringChannel = (ScatteringByteChannel) channel;
704 totalBytesRead = toIntExact(scatteringChannel.read(byteBuffers, 0, bufferCount));
705 } else {
706 for (int i = 0; i < bufferCount; i++) {
707 int bytesRead = channel.read(byteBuffers[i]);
708 if (bytesRead == -1) {
709 if (i == 0) {
710 return -1;
711 }
712 break;
713 }
714 totalBytesRead = addExact(totalBytesRead, bytesRead);
715 }
716 }
717 } finally {
718 if (totalBytesRead > 0) {
719 skipWritableBytes(totalBytesRead);
720 }
721 }
722 return totalBytesRead;
723 }
724
725 private static int countAndPrepareBuffersForChannelIO(int byteLength, ByteBuffer[] byteBuffers) {
726 int bufferCount = 0;
727 int byteSum = 0;
728 for (ByteBuffer buffer : byteBuffers) {
729 byteSum += buffer.remaining();
730 bufferCount++;
731 if (byteSum >= byteLength) {
732 int diff = byteSum - byteLength;
733 if (diff > 0) {
734 buffer.limit(buffer.limit() - diff);
735 }
736 break;
737 }
738 }
739 return bufferCount;
740 }
741
742 @Override
743 public int bytesBefore(byte needle) {
744 if (!isAccessible()) {
745 throw bufferIsClosed(this);
746 }
747 final int length = readableBytes();
748 for (int i = searchOffsets(readerOffset()), skip = 0; skip < length; i++) {
749 Buffer buf = bufs[i];
750 int found = buf.bytesBefore(needle);
751 if (found != -1) {
752 return skip + found;
753 }
754 skip += buf.readableBytes();
755 }
756 return -1;
757 }
758
759 @Override
760 public int bytesBefore(Buffer needle) {
761 return Statics.bytesBefore(this, null, needle, null);
762 }
763
764 @Override
765 public ByteCursor openCursor() {
766 return openCursor(readerOffset(), readableBytes());
767 }
768
769 @Override
770 public ByteCursor openCursor(int fromOffset, int length) {
771 if (fromOffset < 0) {
772 throw new IndexOutOfBoundsException("The fromOffset cannot be negative: " + fromOffset + '.');
773 }
774 checkLength(length);
775 if (capacity < addExact(fromOffset, length)) {
776 throw new IndexOutOfBoundsException("The fromOffset+length is beyond the end of the buffer: " +
777 "fromOffset=" + fromOffset + ", length=" + length + '.');
778 }
779 if (closed) {
780 throw bufferIsClosed(this);
781 }
782 int startBufferIndex = searchOffsets(fromOffset);
783 int off = fromOffset - offsets[startBufferIndex];
784 Buffer startBuf = bufs[startBufferIndex];
785 ByteCursor startCursor = startBuf.openCursor(off, Math.min(startBuf.capacity() - off, length));
786 return new ForwardCompositeByteCursor(bufs, fromOffset, length, startBufferIndex, startCursor);
787 }
788
789 @Override
790 public ByteCursor openReverseCursor(int fromOffset, int length) {
791 if (fromOffset < 0) {
792 throw new IndexOutOfBoundsException("The fromOffset cannot be negative: " + fromOffset + '.');
793 }
794 checkLength(length);
795 if (fromOffset - length < -1) {
796 throw new IndexOutOfBoundsException("The fromOffset-length would underflow the buffer: " +
797 "fromOffset=" + fromOffset + ", length=" + length + '.');
798 }
799 if (closed) {
800 throw bufferIsClosed(this);
801 }
802 int startBufferIndex = searchOffsets(fromOffset);
803 int off = fromOffset - offsets[startBufferIndex];
804 Buffer startBuf = bufs[startBufferIndex];
805 ByteCursor startCursor = startBuf.openReverseCursor(off, Math.min(off + 1, length));
806 return new ReverseCompositeByteCursor(bufs, fromOffset, length, startBufferIndex, startCursor);
807 }
808
809 @Override
810 public CompositeBuffer ensureWritable(int size, int minimumGrowth, boolean allowCompaction) {
811 if (!isAccessible()) {
812 throw bufferIsClosed(this);
813 }
814 if (!isOwned()) {
815 throw new IllegalStateException("Buffer is not owned. Only owned buffers can call ensureWritable.");
816 }
817 if (size < 0) {
818 throw new IllegalArgumentException("Cannot ensure writable for a negative size: " + size + '.');
819 }
820 if (minimumGrowth < 0) {
821 throw new IllegalArgumentException("The minimum growth cannot be negative: " + minimumGrowth + '.');
822 }
823 if (readOnly) {
824 throw bufferIsReadOnly(this);
825 }
826 if (writableBytes() >= size) {
827
828 return this;
829 }
830
831 if (allowCompaction && size <= roff) {
832
833
834 int compactableBuffers = 0;
835 for (Buffer buf : bufs) {
836 if (buf.capacity() != buf.readerOffset()) {
837 break;
838 }
839 compactableBuffers++;
840 }
841 if (compactableBuffers > 0) {
842 Buffer[] compactable;
843 if (compactableBuffers < bufs.length) {
844 compactable = new Buffer[compactableBuffers];
845 System.arraycopy(bufs, 0, compactable, 0, compactable.length);
846 System.arraycopy(bufs, compactable.length, bufs, 0, bufs.length - compactable.length);
847 System.arraycopy(compactable, 0, bufs, bufs.length - compactable.length, compactable.length);
848 } else {
849 compactable = bufs;
850 }
851 for (Buffer buf : compactable) {
852 buf.resetOffsets();
853 }
854 computeBufferOffsets();
855 if (writableBytes() >= size) {
856
857 return this;
858 }
859 } else if (bufs.length == 1) {
860
861 bufs[0].compact();
862 computeBufferOffsets();
863 if (writableBytes() >= size) {
864
865 return this;
866 }
867 }
868 }
869
870 int growth = Math.max(size - writableBytes(), minimumGrowth);
871 Statics.assertValidBufferSize(capacity() + (long) growth);
872 Buffer extension = allocator.allocate(growth);
873 unsafeExtendWith(extension);
874 return this;
875 }
876
877 @Override
878 public CompositeBuffer extendWith(Send<Buffer> extension) {
879 Buffer buffer = Objects.requireNonNull(extension, "Extension buffer cannot be null.").receive();
880 if (!isAccessible() || !isOwned()) {
881 buffer.close();
882 if (!isAccessible()) {
883 throw bufferIsClosed(this);
884 }
885 throw new IllegalStateException("This buffer cannot be extended because it is not in an owned state.");
886 }
887 if (bufs.length > 0 && buffer.readOnly() != readOnly()) {
888 buffer.close();
889 throw new IllegalArgumentException(
890 "This buffer is " + (readOnly? "read-only" : "writable") + ", " +
891 "and cannot be extended with a buffer that is " +
892 (buffer.readOnly()? "read-only." : "writable."));
893 }
894
895 long extensionCapacity = buffer.capacity();
896 if (extensionCapacity == 0) {
897
898
899
900
901 buffer.close();
902 return this;
903 }
904
905 long newSize = capacity() + extensionCapacity;
906 Statics.assertValidBufferSize(newSize);
907
908 Buffer[] restoreTemp = bufs;
909 try {
910 bufs = filterExternalBufs(new ConcatIterable<>(Arrays.asList(bufs), List.of(buffer)));
911 computeBufferOffsets();
912 if (restoreTemp.length == 0) {
913 readOnly = buffer.readOnly();
914 }
915 } catch (Exception e) {
916 bufs = restoreTemp;
917 throw e;
918 }
919 return this;
920 }
921
922 private void unsafeExtendWith(Buffer extension) {
923 bufs = Arrays.copyOf(bufs, bufs.length + 1);
924 bufs[bufs.length - 1] = extension;
925 computeBufferOffsets();
926 }
927
928 private void checkSplit(int splitOffset) {
929 if (splitOffset < 0) {
930 throw new IllegalArgumentException("The split offset cannot be negative: " + splitOffset + '.');
931 }
932 if (capacity() < splitOffset) {
933 throw new IllegalArgumentException("The split offset cannot be greater than the buffer capacity, " +
934 "but the split offset was " + splitOffset + ", and capacity is " + capacity() + '.');
935 }
936 if (!isAccessible()) {
937 throw attachTrace(bufferIsClosed(this));
938 }
939 if (!isOwned()) {
940 throw new IllegalStateException("Cannot split a buffer that is not owned.");
941 }
942 }
943
944 @Override
945 public CompositeBuffer split() {
946 return split(writerOffset());
947 }
948
949 @Override
950 public CompositeBuffer split(int splitOffset) {
951 checkSplit(splitOffset);
952 if (bufs.length == 0) {
953
954 return new DefaultCompositeBuffer(allocator, bufs, unsafeGetDrop());
955 }
956
957 int i = searchOffsets(splitOffset);
958 int off = splitOffset - offsets[i];
959 Buffer[] splits = Arrays.copyOf(bufs, off == 0? i : 1 + i);
960 bufs = Arrays.copyOfRange(bufs, off == bufs[i].capacity()? 1 + i : i, bufs.length);
961 if (off > 0 && splits.length > 0 && off < splits[splits.length - 1].capacity()) {
962 splits[splits.length - 1] = bufs[0].split(off);
963 }
964 computeBufferOffsets();
965 return buildSplitBuffer(splits);
966 }
967
968 private CompositeBuffer buildSplitBuffer(Buffer[] splits) {
969
970 return new DefaultCompositeBuffer(allocator, splits, unsafeGetDrop());
971 }
972
973 @Override
974 public CompositeBuffer splitComponentsFloor(int splitOffset) {
975 checkSplit(splitOffset);
976 if (bufs.length == 0) {
977
978 return new DefaultCompositeBuffer(allocator, bufs, unsafeGetDrop());
979 }
980
981 int i = searchOffsets(splitOffset);
982 int off = splitOffset - offsets[i];
983 if (off == bufs[i].capacity()) {
984 i++;
985 }
986 Buffer[] splits = Arrays.copyOf(bufs, i);
987 bufs = Arrays.copyOfRange(bufs, i, bufs.length);
988 computeBufferOffsets();
989 return buildSplitBuffer(splits);
990 }
991
992 @Override
993 public CompositeBuffer splitComponentsCeil(int splitOffset) {
994 checkSplit(splitOffset);
995 if (bufs.length == 0) {
996
997 return new DefaultCompositeBuffer(allocator, bufs, unsafeGetDrop());
998 }
999
1000 int i = searchOffsets(splitOffset);
1001 int off = splitOffset - offsets[i];
1002 if (0 < off && off <= bufs[i].capacity()) {
1003 i++;
1004 }
1005 Buffer[] splits = Arrays.copyOf(bufs, i);
1006 bufs = Arrays.copyOfRange(bufs, i, bufs.length);
1007 computeBufferOffsets();
1008 return buildSplitBuffer(splits);
1009 }
1010
1011 @Override
1012 public Buffer[] decomposeBuffer() {
1013 Buffer[] result = bufs;
1014 bufs = EMPTY_BUFFER_ARRAY;
1015 try {
1016 close();
1017 } catch (Throwable e) {
1018 for (Buffer buffer : result) {
1019 try {
1020 buffer.close();
1021 } catch (Throwable ex) {
1022 e.addSuppressed(ex);
1023 }
1024 }
1025 throw e;
1026 }
1027 return result;
1028 }
1029
1030 @Override
1031 public CompositeBuffer compact() {
1032 if (!isAccessible()) {
1033 throw attachTrace(bufferIsClosed(this));
1034 }
1035 if (!isOwned()) {
1036 throw attachTrace(new IllegalStateException("Buffer must be owned in order to compact."));
1037 }
1038 if (readOnly()) {
1039 throw new BufferReadOnlyException("Buffer must be writable in order to compact, but was read-only.");
1040 }
1041 int distance = roff;
1042 if (distance == 0) {
1043 return this;
1044 }
1045 int pos = 0;
1046
1047 var cursor = openCursor();
1048 while (cursor.readByte()) {
1049 setByte(pos, cursor.getByte());
1050 pos++;
1051 }
1052 readerOffset(0);
1053 writerOffset(woff - distance);
1054 return this;
1055 }
1056
1057 @Override
1058 public int countComponents() {
1059 int sum = 0;
1060 for (Buffer buf : bufs) {
1061 sum += buf.countComponents();
1062 }
1063 return sum;
1064 }
1065
1066 @Override
1067 public int countReadableComponents() {
1068 int sum = 0;
1069 for (Buffer buf : bufs) {
1070 sum += buf.countReadableComponents();
1071 }
1072 return sum;
1073 }
1074
1075 @Override
1076 public int countWritableComponents() {
1077 int sum = 0;
1078 for (Buffer buf : bufs) {
1079 sum += buf.countWritableComponents();
1080 }
1081 return sum;
1082 }
1083
1084 @Override
1085 public <E extends Exception> int forEachReadable(int initialIndex, ReadableComponentProcessor<E> processor)
1086 throws E {
1087 if (!isAccessible()) {
1088 throw attachTrace(bufferIsClosed(this));
1089 }
1090 int readableBytes = readableBytes();
1091 if (readableBytes == 0) {
1092 return 0;
1093 }
1094 checkReadBounds(readerOffset(), readableBytes);
1095 int visited = 0;
1096 for (Buffer buf : bufs) {
1097 if (buf.readableBytes() > 0) {
1098 int roffBefore = buf.readerOffset();
1099 int count = buf.forEachReadable(visited + initialIndex, processor);
1100 int roffAfter = buf.readerOffset();
1101 if (roffAfter != roffBefore) {
1102 buf.readerOffset(roffBefore);
1103 skipReadableBytes(roffAfter - roffBefore);
1104 }
1105 if (count > 0) {
1106 visited += count;
1107 } else {
1108 visited = -visited + count;
1109 break;
1110 }
1111 }
1112 }
1113 return visited;
1114 }
1115
1116 @Override
1117 public <T extends ReadableComponent & Next> ComponentIterator<T> forEachReadable() {
1118 return new CompositeComponentIterator<>((DefaultCompositeBuffer) acquire(), Buffer::forEachReadable);
1119 }
1120
1121 @Override
1122 public <E extends Exception> int forEachWritable(int initialIndex, WritableComponentProcessor<E> processor)
1123 throws E {
1124 if (!isAccessible()) {
1125 throw attachTrace(bufferIsClosed(this));
1126 }
1127 int writableBytes = writableBytes();
1128 if (writableBytes == 0) {
1129 return 0;
1130 }
1131 checkWriteBounds(writerOffset(), writableBytes);
1132 int visited = 0;
1133 for (Buffer buf : bufs) {
1134 if (buf.writableBytes() > 0) {
1135 int woffBefore = buf.writerOffset();
1136 int count = buf.forEachWritable(visited + initialIndex, processor);
1137 int woffAfter = buf.writerOffset();
1138 if (woffAfter != woffBefore) {
1139 buf.writerOffset(woffBefore);
1140 skipWritableBytes(woffAfter - woffBefore);
1141 }
1142 if (count > 0) {
1143 visited += count;
1144 } else {
1145 visited = -visited + count;
1146 break;
1147 }
1148 }
1149 }
1150 return visited;
1151 }
1152
1153 @Override
1154 public <T extends WritableComponent & Next> ComponentIterator<T> forEachWritable() {
1155 checkWriteBounds(writerOffset(), writableBytes());
1156 return new CompositeComponentIterator<>((DefaultCompositeBuffer) acquire(), Buffer::forEachWritable);
1157 }
1158
1159
1160 @Override
1161 public byte readByte() {
1162 return prepRead(Byte.BYTES).readByte();
1163 }
1164
1165 @Override
1166 public byte getByte(int roff) {
1167 return prepGet(roff, Byte.BYTES).getByte(subOffset);
1168 }
1169
1170 @Override
1171 public int readUnsignedByte() {
1172 return prepRead(Byte.BYTES).readUnsignedByte();
1173 }
1174
1175 @Override
1176 public int getUnsignedByte(int roff) {
1177 return prepGet(roff, Byte.BYTES).getUnsignedByte(subOffset);
1178 }
1179
1180 @Override
1181 public CompositeBuffer writeByte(byte value) {
1182 prepWrite(Byte.BYTES).writeByte(value);
1183 return this;
1184 }
1185
1186 @Override
1187 public CompositeBuffer setByte(int woff, byte value) {
1188 prepWrite(woff, Byte.BYTES).setByte(subOffset, value);
1189 return this;
1190 }
1191
1192 @Override
1193 public CompositeBuffer writeUnsignedByte(int value) {
1194 prepWrite(Byte.BYTES).writeUnsignedByte(value);
1195 return this;
1196 }
1197
1198 @Override
1199 public CompositeBuffer setUnsignedByte(int woff, int value) {
1200 prepWrite(woff, Byte.BYTES).setUnsignedByte(subOffset, value);
1201 return this;
1202 }
1203
1204 @Override
1205 public char readChar() {
1206 return prepRead(Character.BYTES).readChar();
1207 }
1208
1209 @Override
1210 public char getChar(int roff) {
1211 return prepGet(roff, Character.BYTES).getChar(subOffset);
1212 }
1213
1214 @Override
1215 public CompositeBuffer writeChar(char value) {
1216 prepWrite(Character.BYTES).writeChar(value);
1217 return this;
1218 }
1219
1220 @Override
1221 public CompositeBuffer setChar(int woff, char value) {
1222 prepWrite(woff, Character.BYTES).setChar(subOffset, value);
1223 return this;
1224 }
1225
1226 @Override
1227 public short readShort() {
1228 return prepRead(Short.BYTES).readShort();
1229 }
1230
1231 @Override
1232 public short getShort(int roff) {
1233 return prepGet(roff, Short.BYTES).getShort(subOffset);
1234 }
1235
1236 @Override
1237 public int readUnsignedShort() {
1238 return prepRead(Short.BYTES).readUnsignedShort();
1239 }
1240
1241 @Override
1242 public int getUnsignedShort(int roff) {
1243 return prepGet(roff, Short.BYTES).getUnsignedShort(subOffset);
1244 }
1245
1246 @Override
1247 public CompositeBuffer writeShort(short value) {
1248 prepWrite(Short.BYTES).writeShort(value);
1249 return this;
1250 }
1251
1252 @Override
1253 public CompositeBuffer setShort(int woff, short value) {
1254 prepWrite(woff, Short.BYTES).setShort(subOffset, value);
1255 return this;
1256 }
1257
1258 @Override
1259 public CompositeBuffer writeUnsignedShort(int value) {
1260 prepWrite(Short.BYTES).writeUnsignedShort(value);
1261 return this;
1262 }
1263
1264 @Override
1265 public CompositeBuffer setUnsignedShort(int woff, int value) {
1266 prepWrite(woff, Short.BYTES).setUnsignedShort(subOffset, value);
1267 return this;
1268 }
1269
1270 @Override
1271 public int readMedium() {
1272 return prepRead(3).readMedium();
1273 }
1274
1275 @Override
1276 public int getMedium(int roff) {
1277 return prepGet(roff, 3).getMedium(subOffset);
1278 }
1279
1280 @Override
1281 public int readUnsignedMedium() {
1282 return prepRead(3).readUnsignedMedium();
1283 }
1284
1285 @Override
1286 public int getUnsignedMedium(int roff) {
1287 return prepGet(roff, 3).getUnsignedMedium(subOffset);
1288 }
1289
1290 @Override
1291 public CompositeBuffer writeMedium(int value) {
1292 prepWrite(3).writeMedium(value);
1293 return this;
1294 }
1295
1296 @Override
1297 public CompositeBuffer setMedium(int woff, int value) {
1298 prepWrite(woff, 3).setMedium(subOffset, value);
1299 return this;
1300 }
1301
1302 @Override
1303 public CompositeBuffer writeUnsignedMedium(int value) {
1304 prepWrite(3).writeUnsignedMedium(value);
1305 return this;
1306 }
1307
1308 @Override
1309 public CompositeBuffer setUnsignedMedium(int woff, int value) {
1310 prepWrite(woff, 3).setUnsignedMedium(subOffset, value);
1311 return this;
1312 }
1313
1314 @Override
1315 public int readInt() {
1316 return prepRead(Integer.BYTES).readInt();
1317 }
1318
1319 @Override
1320 public int getInt(int roff) {
1321 return prepGet(roff, Integer.BYTES).getInt(subOffset);
1322 }
1323
1324 @Override
1325 public long readUnsignedInt() {
1326 return prepRead(Integer.BYTES).readUnsignedInt();
1327 }
1328
1329 @Override
1330 public long getUnsignedInt(int roff) {
1331 return prepGet(roff, Integer.BYTES).getUnsignedInt(subOffset);
1332 }
1333
1334 @Override
1335 public CompositeBuffer writeInt(int value) {
1336 prepWrite(Integer.BYTES).writeInt(value);
1337 return this;
1338 }
1339
1340 @Override
1341 public CompositeBuffer setInt(int woff, int value) {
1342 prepWrite(woff, Integer.BYTES).setInt(subOffset, value);
1343 return this;
1344 }
1345
1346 @Override
1347 public CompositeBuffer writeUnsignedInt(long value) {
1348 prepWrite(Integer.BYTES).writeUnsignedInt(value);
1349 return this;
1350 }
1351
1352 @Override
1353 public CompositeBuffer setUnsignedInt(int woff, long value) {
1354 prepWrite(woff, Integer.BYTES).setUnsignedInt(subOffset, value);
1355 return this;
1356 }
1357
1358 @Override
1359 public float readFloat() {
1360 return prepRead(Float.BYTES).readFloat();
1361 }
1362
1363 @Override
1364 public float getFloat(int roff) {
1365 return prepGet(roff, Float.BYTES).getFloat(subOffset);
1366 }
1367
1368 @Override
1369 public CompositeBuffer writeFloat(float value) {
1370 prepWrite(Float.BYTES).writeFloat(value);
1371 return this;
1372 }
1373
1374 @Override
1375 public CompositeBuffer setFloat(int woff, float value) {
1376 prepWrite(woff, Float.BYTES).setFloat(subOffset, value);
1377 return this;
1378 }
1379
1380 @Override
1381 public long readLong() {
1382 return prepRead(Long.BYTES).readLong();
1383 }
1384
1385 @Override
1386 public long getLong(int roff) {
1387 return prepGet(roff, Long.BYTES).getLong(subOffset);
1388 }
1389
1390 @Override
1391 public CompositeBuffer writeLong(long value) {
1392 prepWrite(Long.BYTES).writeLong(value);
1393 return this;
1394 }
1395
1396 @Override
1397 public CompositeBuffer setLong(int woff, long value) {
1398 prepWrite(woff, Long.BYTES).setLong(subOffset, value);
1399 return this;
1400 }
1401
1402 @Override
1403 public double readDouble() {
1404 return prepRead(Double.BYTES).readDouble();
1405 }
1406
1407 @Override
1408 public double getDouble(int roff) {
1409 return prepGet(roff, Double.BYTES).getDouble(subOffset);
1410 }
1411
1412 @Override
1413 public CompositeBuffer writeDouble(double value) {
1414 prepWrite(Double.BYTES).writeDouble(value);
1415 return this;
1416 }
1417
1418 @Override
1419 public CompositeBuffer setDouble(int woff, double value) {
1420 prepWrite(woff, Double.BYTES).setDouble(subOffset, value);
1421 return this;
1422 }
1423
1424
1425 @Override
1426 protected Owned<DefaultCompositeBuffer> prepareSend() {
1427 @SuppressWarnings("unchecked")
1428 Send<Buffer>[] sends = new Send[bufs.length];
1429 try {
1430 for (int i = 0; i < bufs.length; i++) {
1431 sends[i] = bufs[i].send();
1432 }
1433 } catch (Throwable throwable) {
1434
1435 for (int i = 0; i < sends.length; i++) {
1436 if (sends[i] != null) {
1437 try {
1438 bufs[i] = sends[i].receive();
1439 } catch (Exception e) {
1440 throwable.addSuppressed(e);
1441 }
1442 }
1443 }
1444 throw throwable;
1445 }
1446 boolean readOnly = this.readOnly;
1447 int implicitCapacityLimit = this.implicitCapacityLimit;
1448 return drop -> {
1449 Buffer[] received = new Buffer[sends.length];
1450 for (int i = 0; i < sends.length; i++) {
1451 received[i] = sends[i].receive();
1452 }
1453 var composite = new DefaultCompositeBuffer(allocator, received, drop);
1454 composite.readOnly = readOnly;
1455 composite.implicitCapacityLimit = implicitCapacityLimit;
1456 drop.attach(composite);
1457 return composite;
1458 };
1459 }
1460
1461 @Override
1462 protected void makeInaccessible() {
1463 capacity = 0;
1464 roff = 0;
1465 woff = 0;
1466 readOnly = false;
1467 closed = true;
1468 }
1469
1470 @Override
1471 protected boolean isOwned() {
1472 return super.isOwned() && allConstituentsAreOwned();
1473 }
1474
1475 @Override
1476 public CompositeBuffer touch(Object hint) {
1477 super.touch(hint);
1478 for (Buffer buf : bufs) {
1479 buf.touch(hint);
1480 }
1481 return this;
1482 }
1483
1484 private boolean allConstituentsAreOwned() {
1485 boolean result = true;
1486 for (Buffer buf : bufs) {
1487 result &= Statics.isOwned((ResourceSupport<?, ?>) buf);
1488 }
1489 return result;
1490 }
1491
1492 long readPassThrough() {
1493 var buf = choosePassThroughBuffer(subOffset++);
1494 assert buf != tornBufAccessors: "Recursive call to torn buffer.";
1495 return buf.readUnsignedByte();
1496 }
1497
1498 void writePassThrough(int value) {
1499 var buf = choosePassThroughBuffer(subOffset++);
1500 assert buf != tornBufAccessors: "Recursive call to torn buffer.";
1501 buf.writeUnsignedByte(value);
1502 }
1503
1504 long getPassThrough(int roff) {
1505 var buf = chooseBuffer(roff, 1);
1506 assert buf != tornBufAccessors: "Recursive call to torn buffer.";
1507 return buf.getUnsignedByte(subOffset);
1508 }
1509
1510 void setPassThrough(int woff, int value) {
1511 var buf = chooseBuffer(woff, 1);
1512 assert buf != tornBufAccessors: "Recursive call to torn buffer.";
1513 buf.setUnsignedByte(subOffset, value);
1514 }
1515
1516 private BufferAccessor prepRead(int size) {
1517 var buf = prepRead(roff, size);
1518 roff += size;
1519 return buf;
1520 }
1521
1522 private BufferAccessor prepRead(int index, int size) {
1523 checkReadBounds(index, size);
1524 return chooseBuffer(index, size);
1525 }
1526
1527 private void checkReadBounds(int index, int size) {
1528 if (index < 0 || woff < index + size) {
1529 throw indexOutOfBounds(index, false);
1530 }
1531 }
1532
1533 private BufferAccessor prepGet(int index, int size) {
1534 checkGetBounds(index, size);
1535 return chooseBuffer(index, size);
1536 }
1537
1538 private void checkGetBounds(int index, int size) {
1539 if (index < 0 || capacity < index + size) {
1540 throw indexOutOfBounds(index, false);
1541 }
1542 }
1543
1544 private BufferAccessor prepWrite(int size) {
1545 if (writableBytes() < size && woff + size <= implicitCapacityLimit && isOwned()) {
1546 final int minGrowth;
1547 if (bufs.length == 0) {
1548 minGrowth = Math.min(implicitCapacityLimit, FIRST_AUTOMATIC_COMPONENT_SIZE);
1549 } else {
1550 minGrowth = Math.min(
1551 Math.max(roundToPowerOfTwo(capacity() / bufs.length), size),
1552 implicitCapacityLimit - capacity);
1553 }
1554 ensureWritable(size, minGrowth, false);
1555 }
1556 var buf = prepWrite(woff, size);
1557 woff += size;
1558 return buf;
1559 }
1560
1561 private BufferAccessor prepWrite(int index, int size) {
1562 checkWriteBounds(index, size);
1563 return chooseBuffer(index, size);
1564 }
1565
1566 private void checkWriteBounds(int index, int size) {
1567 if (index < 0 || capacity < index + size || readOnly) {
1568 throw indexOutOfBounds(index, true);
1569 }
1570 }
1571
1572 private RuntimeException indexOutOfBounds(int index, boolean write) {
1573 if (closed) {
1574 return bufferIsClosed(this);
1575 }
1576 if (write && readOnly) {
1577 return bufferIsReadOnly(this);
1578 }
1579 return new IndexOutOfBoundsException(
1580 "Index " + index + " is out of bounds: [read 0 to " + woff + ", write 0 to " +
1581 capacity + "].");
1582 }
1583
1584 private BufferAccessor chooseBuffer(int index, int size) {
1585 int i = searchOffsets(index);
1586 if (i == bufs.length) {
1587
1588
1589 return null;
1590 }
1591 int off = index - offsets[i];
1592 Buffer candidate = bufs[i];
1593 if (off + size <= candidate.capacity()) {
1594 subOffset = off;
1595 return candidate;
1596 }
1597 subOffset = index;
1598 return tornBufAccessors;
1599 }
1600
1601 private BufferAccessor choosePassThroughBuffer(int index) {
1602 int i = searchOffsets(index);
1603 return bufs[i];
1604 }
1605
1606 private int searchOffsets(int index) {
1607 int i = Arrays.binarySearch(offsets, index);
1608 return i < 0? -(i + 2) : i;
1609 }
1610
1611 @Override
1612 public boolean equals(Object o) {
1613 return o instanceof Buffer && Statics.equals(this, (Buffer) o);
1614 }
1615
1616 @Override
1617 public int hashCode() {
1618 return Statics.hashCode(this);
1619 }
1620
1621
1622 private static final class TornBufferAccessor implements BufferAccessor {
1623 private final DefaultCompositeBuffer buf;
1624
1625 private TornBufferAccessor(DefaultCompositeBuffer buf) {
1626 this.buf = buf;
1627 }
1628
1629 @Override
1630 public byte readByte() {
1631 throw new AssertionError("Method should not be used.");
1632 }
1633
1634 @Override
1635 public byte getByte(int roff) {
1636 throw new AssertionError("Method should not be used.");
1637 }
1638
1639 @Override
1640 public int readUnsignedByte() {
1641 throw new AssertionError("Method should not be used.");
1642 }
1643
1644 @Override
1645 public int getUnsignedByte(int roff) {
1646 throw new AssertionError("Method should not be used.");
1647 }
1648
1649 @Override
1650 public Buffer writeByte(byte value) {
1651 throw new AssertionError("Method should not be used.");
1652 }
1653
1654 @Override
1655 public Buffer setByte(int woff, byte value) {
1656 throw new AssertionError("Method should not be used.");
1657 }
1658
1659 @Override
1660 public Buffer writeUnsignedByte(int value) {
1661 throw new AssertionError("Method should not be used.");
1662 }
1663
1664 @Override
1665 public Buffer setUnsignedByte(int woff, int value) {
1666 throw new AssertionError("Method should not be used.");
1667 }
1668
1669 @Override
1670 public char readChar() {
1671 return (char) (read() << 8 | read());
1672 }
1673
1674 @Override
1675 public char getChar(int roff) {
1676 return (char) (read(roff) << 8 | read(roff + 1));
1677 }
1678
1679 @Override
1680 public Buffer writeChar(char value) {
1681 write(value >>> 8);
1682 write(value & 0xFF);
1683 return buf;
1684 }
1685
1686 @Override
1687 public Buffer setChar(int woff, char value) {
1688 write(woff, value >>> 8);
1689 write(woff + 1, value & 0xFF);
1690 return buf;
1691 }
1692
1693 @Override
1694 public short readShort() {
1695 return (short) (read() << 8 | read());
1696 }
1697
1698 @Override
1699 public short getShort(int roff) {
1700 return (short) (read(roff) << 8 | read(roff + 1));
1701 }
1702
1703 @Override
1704 public int readUnsignedShort() {
1705 return (int) (read() << 8 | read()) & 0xFFFF;
1706 }
1707
1708 @Override
1709 public int getUnsignedShort(int roff) {
1710 return (int) (read(roff) << 8 | read(roff + 1)) & 0xFFFF;
1711 }
1712
1713 @Override
1714 public Buffer writeShort(short value) {
1715 write(value >>> 8);
1716 write(value & 0xFF);
1717 return buf;
1718 }
1719
1720 @Override
1721 public Buffer setShort(int woff, short value) {
1722 write(woff, value >>> 8);
1723 write(woff + 1, value & 0xFF);
1724 return buf;
1725 }
1726
1727 @Override
1728 public Buffer writeUnsignedShort(int value) {
1729 write(value >>> 8);
1730 write(value & 0xFF);
1731 return buf;
1732 }
1733
1734 @Override
1735 public Buffer setUnsignedShort(int woff, int value) {
1736 write(woff, value >>> 8);
1737 write(woff + 1, value & 0xFF);
1738 return buf;
1739 }
1740
1741 @Override
1742 public int readMedium() {
1743 return (int) (read() << 16 | read() << 8 | read());
1744 }
1745
1746 @Override
1747 public int getMedium(int roff) {
1748 return (int) (read(roff) << 16 | read(roff + 1) << 8 | read(roff + 2));
1749 }
1750
1751 @Override
1752 public int readUnsignedMedium() {
1753 return (int) (read() << 16 | read() << 8 | read()) & 0xFFFFFF;
1754 }
1755
1756 @Override
1757 public int getUnsignedMedium(int roff) {
1758 return (int) (read(roff) << 16 | read(roff + 1) << 8 | read(roff + 2)) & 0xFFFFFF;
1759 }
1760
1761 @Override
1762 public Buffer writeMedium(int value) {
1763 write(value >>> 16);
1764 write(value >>> 8 & 0xFF);
1765 write(value & 0xFF);
1766 return buf;
1767 }
1768
1769 @Override
1770 public Buffer setMedium(int woff, int value) {
1771 write(woff, value >>> 16);
1772 write(woff + 1, value >>> 8 & 0xFF);
1773 write(woff + 2, value & 0xFF);
1774 return buf;
1775 }
1776
1777 @Override
1778 public Buffer writeUnsignedMedium(int value) {
1779 write(value >>> 16);
1780 write(value >>> 8 & 0xFF);
1781 write(value & 0xFF);
1782 return buf;
1783 }
1784
1785 @Override
1786 public Buffer setUnsignedMedium(int woff, int value) {
1787 write(woff, value >>> 16);
1788 write(woff + 1, value >>> 8 & 0xFF);
1789 write(woff + 2, value & 0xFF);
1790 return buf;
1791 }
1792
1793 @Override
1794 public int readInt() {
1795 return (int) (read() << 24 | read() << 16 | read() << 8 | read());
1796 }
1797
1798 @Override
1799 public int getInt(int roff) {
1800 return (int) (read(roff) << 24 | read(roff + 1) << 16 | read(roff + 2) << 8 | read(roff + 3));
1801 }
1802
1803 @Override
1804 public long readUnsignedInt() {
1805 return (read() << 24 | read() << 16 | read() << 8 | read()) & 0xFFFFFFFFL;
1806 }
1807
1808 @Override
1809 public long getUnsignedInt(int roff) {
1810 return (read(roff) << 24 | read(roff + 1) << 16 | read(roff + 2) << 8 | read(roff + 3)) & 0xFFFFFFFFL;
1811 }
1812
1813 @Override
1814 public Buffer writeInt(int value) {
1815 write(value >>> 24);
1816 write(value >>> 16 & 0xFF);
1817 write(value >>> 8 & 0xFF);
1818 write(value & 0xFF);
1819 return buf;
1820 }
1821
1822 @Override
1823 public Buffer setInt(int woff, int value) {
1824 write(woff, value >>> 24);
1825 write(woff + 1, value >>> 16 & 0xFF);
1826 write(woff + 2, value >>> 8 & 0xFF);
1827 write(woff + 3, value & 0xFF);
1828 return buf;
1829 }
1830
1831 @Override
1832 public Buffer writeUnsignedInt(long value) {
1833 write((int) (value >>> 24));
1834 write((int) (value >>> 16 & 0xFF));
1835 write((int) (value >>> 8 & 0xFF));
1836 write((int) (value & 0xFF));
1837 return buf;
1838 }
1839
1840 @Override
1841 public Buffer setUnsignedInt(int woff, long value) {
1842 write(woff, (int) (value >>> 24));
1843 write(woff + 1, (int) (value >>> 16 & 0xFF));
1844 write(woff + 2, (int) (value >>> 8 & 0xFF));
1845 write(woff + 3, (int) (value & 0xFF));
1846 return buf;
1847 }
1848
1849 @Override
1850 public float readFloat() {
1851 return Float.intBitsToFloat(readInt());
1852 }
1853
1854 @Override
1855 public float getFloat(int roff) {
1856 return Float.intBitsToFloat(getInt(roff));
1857 }
1858
1859 @Override
1860 public Buffer writeFloat(float value) {
1861 return writeUnsignedInt(Float.floatToRawIntBits(value));
1862 }
1863
1864 @Override
1865 public Buffer setFloat(int woff, float value) {
1866 return setUnsignedInt(woff, Float.floatToRawIntBits(value));
1867 }
1868
1869 @Override
1870 public long readLong() {
1871 return read() << 56 | read() << 48 | read() << 40 | read() << 32 |
1872 read() << 24 | read() << 16 | read() << 8 | read();
1873 }
1874
1875 @Override
1876 public long getLong(int roff) {
1877 return read(roff) << 56 | read(roff + 1) << 48 | read(roff + 2) << 40 | read(roff + 3) << 32 |
1878 read(roff + 4) << 24 | read(roff + 5) << 16 | read(roff + 6) << 8 | read(roff + 7);
1879 }
1880
1881 @Override
1882 public Buffer writeLong(long value) {
1883 write((int) (value >>> 56));
1884 write((int) (value >>> 48 & 0xFF));
1885 write((int) (value >>> 40 & 0xFF));
1886 write((int) (value >>> 32 & 0xFF));
1887 write((int) (value >>> 24 & 0xFF));
1888 write((int) (value >>> 16 & 0xFF));
1889 write((int) (value >>> 8 & 0xFF));
1890 write((int) (value & 0xFF));
1891 return buf;
1892 }
1893
1894 @Override
1895 public Buffer setLong(int woff, long value) {
1896 write(woff, (int) (value >>> 56));
1897 write(woff + 1, (int) (value >>> 48 & 0xFF));
1898 write(woff + 2, (int) (value >>> 40 & 0xFF));
1899 write(woff + 3, (int) (value >>> 32 & 0xFF));
1900 write(woff + 4, (int) (value >>> 24 & 0xFF));
1901 write(woff + 5, (int) (value >>> 16 & 0xFF));
1902 write(woff + 6, (int) (value >>> 8 & 0xFF));
1903 write(woff + 7, (int) (value & 0xFF));
1904 return buf;
1905 }
1906
1907 @Override
1908 public double readDouble() {
1909 return Double.longBitsToDouble(readLong());
1910 }
1911
1912 @Override
1913 public double getDouble(int roff) {
1914 return Double.longBitsToDouble(getLong(roff));
1915 }
1916
1917 @Override
1918 public Buffer writeDouble(double value) {
1919 return writeLong(Double.doubleToRawLongBits(value));
1920 }
1921
1922 @Override
1923 public Buffer setDouble(int woff, double value) {
1924 return setLong(woff, Double.doubleToRawLongBits(value));
1925 }
1926
1927 private long read() {
1928 return buf.readPassThrough();
1929 }
1930
1931 private void write(int value) {
1932 buf.writePassThrough(value);
1933 }
1934
1935 private long read(int roff) {
1936 return buf.getPassThrough(roff);
1937 }
1938
1939 private void write(int woff, int value) {
1940 buf.setPassThrough(woff, value);
1941 }
1942 }
1943
1944
1945 private static final class ForwardCompositeByteCursor implements ByteCursor {
1946 final Buffer[] bufs;
1947 int index;
1948 final int end;
1949 int bufferIndex;
1950 int initOffset;
1951 ByteCursor cursor;
1952 byte byteValue;
1953
1954 ForwardCompositeByteCursor(Buffer[] bufs, int fromOffset, int length, int startBufferIndex,
1955 ByteCursor startCursor) {
1956 this.bufs = bufs;
1957 index = fromOffset;
1958 end = fromOffset + length;
1959 bufferIndex = startBufferIndex;
1960 initOffset = startCursor.currentOffset();
1961 cursor = startCursor;
1962 byteValue = -1;
1963 }
1964
1965 @Override
1966 public boolean readByte() {
1967 if (cursor.readByte()) {
1968 byteValue = cursor.getByte();
1969 return true;
1970 }
1971 if (bytesLeft() > 0) {
1972 nextCursor();
1973 cursor.readByte();
1974 byteValue = cursor.getByte();
1975 return true;
1976 }
1977 return false;
1978 }
1979
1980 private void nextCursor() {
1981 bufferIndex++;
1982 Buffer nextBuf = bufs[bufferIndex];
1983 cursor = nextBuf.openCursor(0, Math.min(nextBuf.capacity(), bytesLeft()));
1984 initOffset = 0;
1985 }
1986
1987 @Override
1988 public byte getByte() {
1989 return byteValue;
1990 }
1991
1992 @Override
1993 public int currentOffset() {
1994 int currOff = cursor.currentOffset();
1995 index += currOff - initOffset;
1996 initOffset = currOff;
1997 return index;
1998 }
1999
2000 @Override
2001 public int bytesLeft() {
2002 return end - currentOffset();
2003 }
2004 }
2005
2006 private static final class ReverseCompositeByteCursor implements ByteCursor {
2007 final Buffer[] bufs;
2008 int index;
2009 final int end;
2010 int bufferIndex;
2011 int initOffset;
2012 ByteCursor cursor;
2013 byte byteValue;
2014
2015 ReverseCompositeByteCursor(Buffer[] bufs, int fromOffset, int length,
2016 int startBufferIndex, ByteCursor startCursor) {
2017 this.bufs = bufs;
2018 index = fromOffset;
2019 end = fromOffset - length;
2020 bufferIndex = startBufferIndex;
2021 initOffset = startCursor.currentOffset();
2022 cursor = startCursor;
2023 byteValue = -1;
2024 }
2025
2026 @Override
2027 public boolean readByte() {
2028 if (cursor.readByte()) {
2029 byteValue = cursor.getByte();
2030 return true;
2031 }
2032 if (bytesLeft() > 0) {
2033 nextCursor();
2034 cursor.readByte();
2035 byteValue = cursor.getByte();
2036 return true;
2037 }
2038 return false;
2039 }
2040
2041 private void nextCursor() {
2042 bufferIndex--;
2043 Buffer nextBuf = bufs[bufferIndex];
2044 int length = Math.min(nextBuf.capacity(), bytesLeft());
2045 int offset = nextBuf.capacity() - 1;
2046 cursor = nextBuf.openReverseCursor(offset, length);
2047 initOffset = offset;
2048 }
2049
2050 @Override
2051 public byte getByte() {
2052 return byteValue;
2053 }
2054
2055 @Override
2056 public int currentOffset() {
2057 int currOff = cursor.currentOffset();
2058 index -= initOffset - currOff;
2059 initOffset = currOff;
2060 return index;
2061 }
2062
2063 @Override
2064 public int bytesLeft() {
2065 return currentOffset() - end;
2066 }
2067 }
2068
2069 private static final class ByteBufferCollector
2070 implements ReadableComponentProcessor<RuntimeException>, WritableComponentProcessor<RuntimeException> {
2071 final ByteBuffer[] buffers;
2072
2073 private ByteBufferCollector(int expectedBufferCount) {
2074 buffers = new ByteBuffer[expectedBufferCount];
2075 }
2076
2077 @Override
2078 public boolean process(int index, ReadableComponent component) {
2079 buffers[index] = component.readableBuffer();
2080 return true;
2081 }
2082
2083 @Override
2084 public boolean process(int index, WritableComponent component) {
2085 buffers[index] = component.writableBuffer();
2086 return true;
2087 }
2088 }
2089
2090 private static final class CompositeComponentIterator<T extends Next> implements ComponentIterator<T> {
2091 private final DefaultCompositeBuffer compositeBuffer;
2092 private final Function<Buffer, ComponentIterator<T>> intoIterator;
2093 NextComponent<T> readableNext;
2094
2095 private CompositeComponentIterator(DefaultCompositeBuffer compositeBuffer,
2096 Function<Buffer, ComponentIterator<T>> intoIterator) {
2097 this.compositeBuffer = compositeBuffer;
2098 this.intoIterator = intoIterator;
2099 }
2100
2101 @SuppressWarnings("unchecked")
2102 @Override
2103 public T first() {
2104 return compositeBuffer.bufs.length > 0 ?
2105 (T) (readableNext = new NextComponent<>(compositeBuffer, intoIterator)) : null;
2106 }
2107
2108 @Override
2109 public void close() {
2110 if (readableNext != null) {
2111 readableNext.close();
2112 }
2113 compositeBuffer.close();
2114 }
2115 }
2116
2117 private static final class NextComponent<T extends Next>
2118 implements ReadableComponent, WritableComponent, Next, SafeCloseable {
2119 private final DefaultCompositeBuffer compositeBuffer;
2120 private final Function<Buffer, ComponentIterator<T>> intoIterator;
2121 private final Buffer[] bufs;
2122 int nextIndex;
2123 ComponentIterator<T> currentItr;
2124 T currentComponent;
2125 int pastOffset;
2126 int currentReadSkip;
2127 int currentWriteSkip;
2128
2129 private NextComponent(DefaultCompositeBuffer compositeBuffer,
2130 Function<Buffer, ComponentIterator<T>> intoIterator) {
2131 this.compositeBuffer = compositeBuffer;
2132 this.intoIterator = intoIterator;
2133 bufs = compositeBuffer.bufs;
2134 nextComponent();
2135 }
2136
2137 @SuppressWarnings("unchecked")
2138 @Override
2139 public <N extends Next> N next() {
2140 if (currentComponent == null) {
2141 return null;
2142 }
2143 nextComponent();
2144 return currentComponent != null? (N) this : null;
2145 }
2146
2147 private void nextComponent() {
2148 if (currentComponent != null) {
2149 currentComponent = currentComponent.next();
2150 }
2151 while (currentComponent == null) {
2152 if (currentItr != null) {
2153 currentItr.close();
2154 currentItr = null;
2155 }
2156 if (nextIndex >= bufs.length) {
2157 return;
2158 }
2159 currentItr = intoIterator.apply(bufs[nextIndex]);
2160 nextIndex++;
2161 currentComponent = currentItr.first();
2162 }
2163 }
2164
2165 @Override
2166 public boolean hasReadableArray() {
2167 return ((ReadableComponent) currentComponent).hasReadableArray();
2168 }
2169
2170 @Override
2171 public byte[] readableArray() {
2172 return ((ReadableComponent) currentComponent).readableArray();
2173 }
2174
2175 @Override
2176 public int readableArrayOffset() {
2177 return ((ReadableComponent) currentComponent).readableArrayOffset();
2178 }
2179
2180 @Override
2181 public int readableArrayLength() {
2182 return ((ReadableComponent) currentComponent).readableArrayLength();
2183 }
2184
2185 @Override
2186 public long readableNativeAddress() {
2187 return ((ReadableComponent) currentComponent).readableNativeAddress();
2188 }
2189
2190 @Override
2191 public ByteBuffer readableBuffer() {
2192 return ((ReadableComponent) currentComponent).readableBuffer();
2193 }
2194
2195 @Override
2196 public int readableBytes() {
2197 return ((ReadableComponent) currentComponent).readableBytes();
2198 }
2199
2200 @Override
2201 public ByteCursor openCursor() {
2202 return ((ReadableComponent) currentComponent).openCursor();
2203 }
2204
2205 @Override
2206 public ReadableComponent skipReadableBytes(int byteCount) {
2207 ((ReadableComponent) currentComponent).skipReadableBytes(byteCount);
2208 compositeBuffer.readerOffset(pastOffset + currentReadSkip + byteCount);
2209 currentReadSkip += byteCount;
2210 return this;
2211 }
2212
2213 @Override
2214 public boolean hasWritableArray() {
2215 return ((WritableComponent) currentComponent).hasWritableArray();
2216 }
2217
2218 @Override
2219 public byte[] writableArray() {
2220 return ((WritableComponent) currentComponent).writableArray();
2221 }
2222
2223 @Override
2224 public int writableArrayOffset() {
2225 return ((WritableComponent) currentComponent).writableArrayOffset();
2226 }
2227
2228 @Override
2229 public int writableArrayLength() {
2230 return ((WritableComponent) currentComponent).writableArrayLength();
2231 }
2232
2233 @Override
2234 public long writableNativeAddress() {
2235 return ((WritableComponent) currentComponent).writableNativeAddress();
2236 }
2237
2238 @Override
2239 public int writableBytes() {
2240 return ((WritableComponent) currentComponent).writableBytes();
2241 }
2242
2243 @Override
2244 public ByteBuffer writableBuffer() {
2245 return ((WritableComponent) currentComponent).writableBuffer();
2246 }
2247
2248 @Override
2249 public WritableComponent skipWritableBytes(int byteCount) {
2250 ((WritableComponent) currentComponent).skipWritableBytes(byteCount);
2251 compositeBuffer.writerOffset(pastOffset + currentWriteSkip + byteCount);
2252 currentWriteSkip += byteCount;
2253 return this;
2254 }
2255
2256 @Override
2257 public void close() {
2258 currentComponent = null;
2259 if (currentItr != null) {
2260 currentItr.close();
2261 currentItr = null;
2262 }
2263 }
2264 }
2265 }