1
16 package io.netty.buffer;
17
18 import io.netty.util.ByteProcessor;
19 import io.netty.util.IllegalReferenceCountException;
20 import io.netty.util.ReferenceCountUtil;
21 import io.netty.util.internal.EmptyArrays;
22 import io.netty.util.internal.ObjectUtil;
23 import io.netty.util.internal.RecyclableArrayList;
24
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.nio.ByteBuffer;
29 import java.nio.ByteOrder;
30 import java.nio.channels.FileChannel;
31 import java.nio.channels.GatheringByteChannel;
32 import java.nio.channels.ScatteringByteChannel;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.ConcurrentModificationException;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.NoSuchElementException;
41
42 import static io.netty.util.internal.ObjectUtil.checkNotNull;
43
44
49 public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable<ByteBuf> {
50
51 private static final ByteBuffer EMPTY_NIO_BUFFER = Unpooled.EMPTY_BUFFER.nioBuffer();
52 private static final Iterator<ByteBuf> EMPTY_ITERATOR = Collections.<ByteBuf>emptyList().iterator();
53
54 private final ByteBufAllocator alloc;
55 private final boolean direct;
56 private final int maxNumComponents;
57
58 private int componentCount;
59 private Component[] components;
60
61 private boolean freed;
62
63 private CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, int initSize) {
64 super(AbstractByteBufAllocator.DEFAULT_MAX_CAPACITY);
65
66 this.alloc = ObjectUtil.checkNotNull(alloc, "alloc");
67 if (maxNumComponents < 1) {
68 throw new IllegalArgumentException(
69 "maxNumComponents: " + maxNumComponents + " (expected: >= 1)");
70 }
71
72 this.direct = direct;
73 this.maxNumComponents = maxNumComponents;
74 components = newCompArray(initSize, maxNumComponents);
75 }
76
77 public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents) {
78 this(alloc, direct, maxNumComponents, 0);
79 }
80
81 public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf... buffers) {
82 this(alloc, direct, maxNumComponents, buffers, 0);
83 }
84
85 CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents,
86 ByteBuf[] buffers, int offset) {
87 this(alloc, direct, maxNumComponents, buffers.length - offset);
88
89 addComponents0(false, 0, buffers, offset);
90 consolidateIfNeeded();
91 setIndex0(0, capacity());
92 }
93
94 public CompositeByteBuf(
95 ByteBufAllocator alloc, boolean direct, int maxNumComponents, Iterable<ByteBuf> buffers) {
96 this(alloc, direct, maxNumComponents,
97 buffers instanceof Collection ? ((Collection<ByteBuf>) buffers).size() : 0);
98
99 addComponents(false, 0, buffers);
100 setIndex(0, capacity());
101 }
102
103
104 interface ByteWrapper<T> {
105 ByteBuf wrap(T bytes);
106 boolean isEmpty(T bytes);
107 }
108
109 static final ByteWrapper<byte[]> BYTE_ARRAY_WRAPPER = new ByteWrapper<byte[]>() {
110 @Override
111 public ByteBuf wrap(byte[] bytes) {
112 return Unpooled.wrappedBuffer(bytes);
113 }
114 @Override
115 public boolean isEmpty(byte[] bytes) {
116 return bytes.length == 0;
117 }
118 };
119
120 static final ByteWrapper<ByteBuffer> BYTE_BUFFER_WRAPPER = new ByteWrapper<ByteBuffer>() {
121 @Override
122 public ByteBuf wrap(ByteBuffer bytes) {
123 return Unpooled.wrappedBuffer(bytes);
124 }
125 @Override
126 public boolean isEmpty(ByteBuffer bytes) {
127 return !bytes.hasRemaining();
128 }
129 };
130
131 <T> CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents,
132 ByteWrapper<T> wrapper, T[] buffers, int offset) {
133 this(alloc, direct, maxNumComponents, buffers.length - offset);
134
135 addComponents0(false, 0, wrapper, buffers, offset);
136 consolidateIfNeeded();
137 setIndex(0, capacity());
138 }
139
140 private static Component[] newCompArray(int initComponents, int maxNumComponents) {
141 int capacityGuess = Math.min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents);
142 return new Component[Math.max(initComponents, capacityGuess)];
143 }
144
145
146 CompositeByteBuf(ByteBufAllocator alloc) {
147 super(Integer.MAX_VALUE);
148 this.alloc = alloc;
149 direct = false;
150 maxNumComponents = 0;
151 components = null;
152 }
153
154
164 public CompositeByteBuf addComponent(ByteBuf buffer) {
165 return addComponent(false, buffer);
166 }
167
168
179 public CompositeByteBuf addComponents(ByteBuf... buffers) {
180 return addComponents(false, buffers);
181 }
182
183
194 public CompositeByteBuf addComponents(Iterable<ByteBuf> buffers) {
195 return addComponents(false, buffers);
196 }
197
198
209 public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) {
210 return addComponent(false, cIndex, buffer);
211 }
212
213
221 public CompositeByteBuf addComponent(boolean increaseWriterIndex, ByteBuf buffer) {
222 return addComponent(increaseWriterIndex, componentCount, buffer);
223 }
224
225
234 public CompositeByteBuf addComponents(boolean increaseWriterIndex, ByteBuf... buffers) {
235 checkNotNull(buffers, "buffers");
236 addComponents0(increaseWriterIndex, componentCount, buffers, 0);
237 consolidateIfNeeded();
238 return this;
239 }
240
241
250 public CompositeByteBuf addComponents(boolean increaseWriterIndex, Iterable<ByteBuf> buffers) {
251 return addComponents(increaseWriterIndex, componentCount, buffers);
252 }
253
254
263 public CompositeByteBuf addComponent(boolean increaseWriterIndex, int cIndex, ByteBuf buffer) {
264 checkNotNull(buffer, "buffer");
265 addComponent0(increaseWriterIndex, cIndex, buffer);
266 consolidateIfNeeded();
267 return this;
268 }
269
270 private static void checkForOverflow(int capacity, int readableBytes) {
271 if (capacity + readableBytes < 0) {
272 throw new IllegalArgumentException("Can't increase by " + readableBytes + " as capacity(" + capacity + ")" +
273 " would overflow " + Integer.MAX_VALUE);
274 }
275 }
276
277
280 private int addComponent0(boolean increaseWriterIndex, int cIndex, ByteBuf buffer) {
281 assert buffer != null;
282 boolean wasAdded = false;
283 try {
284 checkComponentIndex(cIndex);
285
286
287 Component c = newComponent(ensureAccessible(buffer), 0);
288 int readableBytes = c.length();
289
290
291
292 checkForOverflow(capacity(), readableBytes);
293
294 addComp(cIndex, c);
295 wasAdded = true;
296 if (readableBytes > 0 && cIndex < componentCount - 1) {
297 updateComponentOffsets(cIndex);
298 } else if (cIndex > 0) {
299 c.reposition(components[cIndex - 1].endOffset);
300 }
301 if (increaseWriterIndex) {
302 writerIndex += readableBytes;
303 }
304 return cIndex;
305 } finally {
306 if (!wasAdded) {
307 buffer.release();
308 }
309 }
310 }
311
312 private static ByteBuf ensureAccessible(final ByteBuf buf) {
313 if (checkAccessible && !buf.isAccessible()) {
314 throw new IllegalReferenceCountException(0);
315 }
316 return buf;
317 }
318
319 @SuppressWarnings("deprecation")
320 private Component newComponent(final ByteBuf buf, final int offset) {
321 final int srcIndex = buf.readerIndex();
322 final int len = buf.readableBytes();
323
324
325 ByteBuf unwrapped = buf;
326 int unwrappedIndex = srcIndex;
327 while (unwrapped instanceof WrappedByteBuf || unwrapped instanceof SwappedByteBuf) {
328 unwrapped = unwrapped.unwrap();
329 }
330
331
332 if (unwrapped instanceof AbstractUnpooledSlicedByteBuf) {
333 unwrappedIndex += ((AbstractUnpooledSlicedByteBuf) unwrapped).idx(0);
334 unwrapped = unwrapped.unwrap();
335 } else if (unwrapped instanceof PooledSlicedByteBuf) {
336 unwrappedIndex += ((PooledSlicedByteBuf) unwrapped).adjustment;
337 unwrapped = unwrapped.unwrap();
338 } else if (unwrapped instanceof DuplicatedByteBuf || unwrapped instanceof PooledDuplicatedByteBuf) {
339 unwrapped = unwrapped.unwrap();
340 }
341
342
343
344 final ByteBuf slice = buf.capacity() == len ? buf : null;
345
346 return new Component(buf.order(ByteOrder.BIG_ENDIAN), srcIndex,
347 unwrapped.order(ByteOrder.BIG_ENDIAN), unwrappedIndex, offset, len, slice);
348 }
349
350
364 public CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers) {
365 checkNotNull(buffers, "buffers");
366 addComponents0(false, cIndex, buffers, 0);
367 consolidateIfNeeded();
368 return this;
369 }
370
371 private CompositeByteBuf addComponents0(boolean increaseWriterIndex,
372 final int cIndex, ByteBuf[] buffers, int arrOffset) {
373 final int len = buffers.length, count = len - arrOffset;
374
375 int readableBytes = 0;
376 int capacity = capacity();
377 for (int i = 0; i < buffers.length; i++) {
378 readableBytes += buffers[i].readableBytes();
379
380
381
382 checkForOverflow(capacity, readableBytes);
383 }
384
385 int ci = Integer.MAX_VALUE;
386 try {
387 checkComponentIndex(cIndex);
388 shiftComps(cIndex, count);
389 int nextOffset = cIndex > 0 ? components[cIndex - 1].endOffset : 0;
390 for (ci = cIndex; arrOffset < len; arrOffset++, ci++) {
391 ByteBuf b = buffers[arrOffset];
392 if (b == null) {
393 break;
394 }
395 Component c = newComponent(ensureAccessible(b), nextOffset);
396 components[ci] = c;
397 nextOffset = c.endOffset;
398 }
399 return this;
400 } finally {
401
402 if (ci < componentCount) {
403 if (ci < cIndex + count) {
404
405 removeCompRange(ci, cIndex + count);
406 for (; arrOffset < len; ++arrOffset) {
407 ReferenceCountUtil.safeRelease(buffers[arrOffset]);
408 }
409 }
410 updateComponentOffsets(ci);
411 }
412 if (increaseWriterIndex && ci > cIndex && ci <= componentCount) {
413 writerIndex += components[ci - 1].endOffset - components[cIndex].offset;
414 }
415 }
416 }
417
418 private <T> int addComponents0(boolean increaseWriterIndex, int cIndex,
419 ByteWrapper<T> wrapper, T[] buffers, int offset) {
420 checkComponentIndex(cIndex);
421
422
423 for (int i = offset, len = buffers.length; i < len; i++) {
424 T b = buffers[i];
425 if (b == null) {
426 break;
427 }
428 if (!wrapper.isEmpty(b)) {
429 cIndex = addComponent0(increaseWriterIndex, cIndex, wrapper.wrap(b)) + 1;
430 int size = componentCount;
431 if (cIndex > size) {
432 cIndex = size;
433 }
434 }
435 }
436 return cIndex;
437 }
438
439
452 public CompositeByteBuf addComponents(int cIndex, Iterable<ByteBuf> buffers) {
453 return addComponents(false, cIndex, buffers);
454 }
455
456
466 public CompositeByteBuf addFlattenedComponents(boolean increaseWriterIndex, ByteBuf buffer) {
467 checkNotNull(buffer, "buffer");
468 final int ridx = buffer.readerIndex();
469 final int widx = buffer.writerIndex();
470 if (ridx == widx) {
471 buffer.release();
472 return this;
473 }
474 if (!(buffer instanceof CompositeByteBuf)) {
475 addComponent0(increaseWriterIndex, componentCount, buffer);
476 consolidateIfNeeded();
477 return this;
478 }
479 final CompositeByteBuf from;
480 if (buffer instanceof WrappedCompositeByteBuf) {
481 from = (CompositeByteBuf) buffer.unwrap();
482 } else {
483 from = (CompositeByteBuf) buffer;
484 }
485 from.checkIndex(ridx, widx - ridx);
486 final Component[] fromComponents = from.components;
487 final int compCountBefore = componentCount;
488 final int writerIndexBefore = writerIndex;
489 try {
490 for (int cidx = from.toComponentIndex0(ridx), newOffset = capacity();; cidx++) {
491 final Component component = fromComponents[cidx];
492 final int compOffset = component.offset;
493 final int fromIdx = Math.max(ridx, compOffset);
494 final int toIdx = Math.min(widx, component.endOffset);
495 final int len = toIdx - fromIdx;
496 if (len > 0) {
497 addComp(componentCount, new Component(
498 component.srcBuf.retain(), component.srcIdx(fromIdx),
499 component.buf, component.idx(fromIdx), newOffset, len, null));
500 }
501 if (widx == toIdx) {
502 break;
503 }
504 newOffset += len;
505 }
506 if (increaseWriterIndex) {
507 writerIndex = writerIndexBefore + (widx - ridx);
508 }
509 consolidateIfNeeded();
510 buffer.release();
511 buffer = null;
512 return this;
513 } finally {
514 if (buffer != null) {
515
516 if (increaseWriterIndex) {
517 writerIndex = writerIndexBefore;
518 }
519 for (int cidx = componentCount - 1; cidx >= compCountBefore; cidx--) {
520 components[cidx].free();
521 removeComp(cidx);
522 }
523 }
524 }
525 }
526
527
528
529
530 private CompositeByteBuf addComponents(boolean increaseIndex, int cIndex, Iterable<ByteBuf> buffers) {
531 if (buffers instanceof ByteBuf) {
532
533 return addComponent(increaseIndex, cIndex, (ByteBuf) buffers);
534 }
535 checkNotNull(buffers, "buffers");
536 Iterator<ByteBuf> it = buffers.iterator();
537 try {
538 checkComponentIndex(cIndex);
539
540
541 while (it.hasNext()) {
542 ByteBuf b = it.next();
543 if (b == null) {
544 break;
545 }
546 cIndex = addComponent0(increaseIndex, cIndex, b) + 1;
547 cIndex = Math.min(cIndex, componentCount);
548 }
549 } finally {
550 while (it.hasNext()) {
551 ReferenceCountUtil.safeRelease(it.next());
552 }
553 }
554 consolidateIfNeeded();
555 return this;
556 }
557
558
562 private void consolidateIfNeeded() {
563
564
565 int size = componentCount;
566 if (size > maxNumComponents) {
567 consolidate0(0, size);
568 }
569 }
570
571 private void checkComponentIndex(int cIndex) {
572 ensureAccessible();
573 if (cIndex < 0 || cIndex > componentCount) {
574 throw new IndexOutOfBoundsException(String.format(
575 "cIndex: %d (expected: >= 0 && <= numComponents(%d))",
576 cIndex, componentCount));
577 }
578 }
579
580 private void checkComponentIndex(int cIndex, int numComponents) {
581 ensureAccessible();
582 if (cIndex < 0 || cIndex + numComponents > componentCount) {
583 throw new IndexOutOfBoundsException(String.format(
584 "cIndex: %d, numComponents: %d " +
585 "(expected: cIndex >= 0 && cIndex + numComponents <= totalNumComponents(%d))",
586 cIndex, numComponents, componentCount));
587 }
588 }
589
590 private void updateComponentOffsets(int cIndex) {
591 int size = componentCount;
592 if (size <= cIndex) {
593 return;
594 }
595
596 int nextIndex = cIndex > 0 ? components[cIndex - 1].endOffset : 0;
597 for (; cIndex < size; cIndex++) {
598 Component c = components[cIndex];
599 c.reposition(nextIndex);
600 nextIndex = c.endOffset;
601 }
602 }
603
604
609 public CompositeByteBuf removeComponent(int cIndex) {
610 checkComponentIndex(cIndex);
611 Component comp = components[cIndex];
612 if (lastAccessed == comp) {
613 lastAccessed = null;
614 }
615 comp.free();
616 removeComp(cIndex);
617 if (comp.length() > 0) {
618
619 updateComponentOffsets(cIndex);
620 }
621 return this;
622 }
623
624
630 public CompositeByteBuf removeComponents(int cIndex, int numComponents) {
631 checkComponentIndex(cIndex, numComponents);
632
633 if (numComponents == 0) {
634 return this;
635 }
636 int endIndex = cIndex + numComponents;
637 boolean needsUpdate = false;
638 for (int i = cIndex; i < endIndex; ++i) {
639 Component c = components[i];
640 if (c.length() > 0) {
641 needsUpdate = true;
642 }
643 if (lastAccessed == c) {
644 lastAccessed = null;
645 }
646 c.free();
647 }
648 removeCompRange(cIndex, endIndex);
649
650 if (needsUpdate) {
651
652 updateComponentOffsets(cIndex);
653 }
654 return this;
655 }
656
657 @Override
658 public Iterator<ByteBuf> iterator() {
659 ensureAccessible();
660 return componentCount == 0 ? EMPTY_ITERATOR : new CompositeByteBufIterator();
661 }
662
663 @Override
664 protected int forEachByteAsc0(int start, int end, ByteProcessor processor) throws Exception {
665 if (end <= start) {
666 return -1;
667 }
668 for (int i = toComponentIndex0(start), length = end - start; length > 0; i++) {
669 Component c = components[i];
670 if (c.offset == c.endOffset) {
671 continue;
672 }
673 ByteBuf s = c.buf;
674 int localStart = c.idx(start);
675 int localLength = Math.min(length, c.endOffset - start);
676
677 int result = s instanceof AbstractByteBuf
678 ? ((AbstractByteBuf) s).forEachByteAsc0(localStart, localStart + localLength, processor)
679 : s.forEachByte(localStart, localLength, processor);
680 if (result != -1) {
681 return result - c.adjustment;
682 }
683 start += localLength;
684 length -= localLength;
685 }
686 return -1;
687 }
688
689 @Override
690 protected int forEachByteDesc0(int rStart, int rEnd, ByteProcessor processor) throws Exception {
691 if (rEnd > rStart) {
692 return -1;
693 }
694 for (int i = toComponentIndex0(rStart), length = 1 + rStart - rEnd; length > 0; i--) {
695 Component c = components[i];
696 if (c.offset == c.endOffset) {
697 continue;
698 }
699 ByteBuf s = c.buf;
700 int localRStart = c.idx(length + rEnd);
701 int localLength = Math.min(length, localRStart), localIndex = localRStart - localLength;
702
703 int result = s instanceof AbstractByteBuf
704 ? ((AbstractByteBuf) s).forEachByteDesc0(localRStart - 1, localIndex, processor)
705 : s.forEachByteDesc(localIndex, localLength, processor);
706
707 if (result != -1) {
708 return result - c.adjustment;
709 }
710 length -= localLength;
711 }
712 return -1;
713 }
714
715
718 public List<ByteBuf> decompose(int offset, int length) {
719 checkIndex(offset, length);
720 if (length == 0) {
721 return Collections.emptyList();
722 }
723
724 int componentId = toComponentIndex0(offset);
725 int bytesToSlice = length;
726
727 Component firstC = components[componentId];
728
729 ByteBuf slice = firstC.buf.slice(firstC.idx(offset), Math.min(firstC.endOffset - offset, bytesToSlice));
730 bytesToSlice -= slice.readableBytes();
731
732 if (bytesToSlice == 0) {
733 return Collections.singletonList(slice);
734 }
735
736 List<ByteBuf> sliceList = new ArrayList<ByteBuf>(componentCount - componentId);
737 sliceList.add(slice);
738
739
740 do {
741 Component component = components[++componentId];
742 slice = component.buf.slice(component.idx(component.offset), Math.min(component.length(), bytesToSlice));
743 bytesToSlice -= slice.readableBytes();
744 sliceList.add(slice);
745 } while (bytesToSlice > 0);
746
747 return sliceList;
748 }
749
750 @Override
751 public boolean isDirect() {
752 int size = componentCount;
753 if (size == 0) {
754 return false;
755 }
756 for (int i = 0; i < size; i++) {
757 if (!components[i].buf.isDirect()) {
758 return false;
759 }
760 }
761 return true;
762 }
763
764 @Override
765 public boolean hasArray() {
766 switch (componentCount) {
767 case 0:
768 return true;
769 case 1:
770 return components[0].buf.hasArray();
771 default:
772 return false;
773 }
774 }
775
776 @Override
777 public byte[] array() {
778 switch (componentCount) {
779 case 0:
780 return EmptyArrays.EMPTY_BYTES;
781 case 1:
782 return components[0].buf.array();
783 default:
784 throw new UnsupportedOperationException();
785 }
786 }
787
788 @Override
789 public int arrayOffset() {
790 switch (componentCount) {
791 case 0:
792 return 0;
793 case 1:
794 Component c = components[0];
795 return c.idx(c.buf.arrayOffset());
796 default:
797 throw new UnsupportedOperationException();
798 }
799 }
800
801 @Override
802 public boolean hasMemoryAddress() {
803 switch (componentCount) {
804 case 0:
805 return Unpooled.EMPTY_BUFFER.hasMemoryAddress();
806 case 1:
807 return components[0].buf.hasMemoryAddress();
808 default:
809 return false;
810 }
811 }
812
813 @Override
814 public long memoryAddress() {
815 switch (componentCount) {
816 case 0:
817 return Unpooled.EMPTY_BUFFER.memoryAddress();
818 case 1:
819 Component c = components[0];
820 return c.buf.memoryAddress() + c.adjustment;
821 default:
822 throw new UnsupportedOperationException();
823 }
824 }
825
826 @Override
827 public int capacity() {
828 int size = componentCount;
829 return size > 0 ? components[size - 1].endOffset : 0;
830 }
831
832 @Override
833 public CompositeByteBuf capacity(int newCapacity) {
834 checkNewCapacity(newCapacity);
835
836 final int size = componentCount, oldCapacity = capacity();
837 if (newCapacity > oldCapacity) {
838 final int paddingLength = newCapacity - oldCapacity;
839 ByteBuf padding = allocBuffer(paddingLength).setIndex(0, paddingLength);
840 addComponent0(false, size, padding);
841 if (componentCount >= maxNumComponents) {
842
843
844 consolidateIfNeeded();
845 }
846 } else if (newCapacity < oldCapacity) {
847 lastAccessed = null;
848 int i = size - 1;
849 for (int bytesToTrim = oldCapacity - newCapacity; i >= 0; i--) {
850 Component c = components[i];
851 final int cLength = c.length();
852 if (bytesToTrim < cLength) {
853
854 c.endOffset -= bytesToTrim;
855 ByteBuf slice = c.slice;
856 if (slice != null) {
857
858
859 c.slice = slice.slice(0, c.length());
860 }
861 break;
862 }
863 c.free();
864 bytesToTrim -= cLength;
865 }
866 removeCompRange(i + 1, size);
867
868 if (readerIndex() > newCapacity) {
869 setIndex0(newCapacity, newCapacity);
870 } else if (writerIndex > newCapacity) {
871 writerIndex = newCapacity;
872 }
873 }
874 return this;
875 }
876
877 @Override
878 public ByteBufAllocator alloc() {
879 return alloc;
880 }
881
882 @Override
883 public ByteOrder order() {
884 return ByteOrder.BIG_ENDIAN;
885 }
886
887
890 public int numComponents() {
891 return componentCount;
892 }
893
894
897 public int maxNumComponents() {
898 return maxNumComponents;
899 }
900
901
904 public int toComponentIndex(int offset) {
905 checkIndex(offset);
906 return toComponentIndex0(offset);
907 }
908
909 private int toComponentIndex0(int offset) {
910 int size = componentCount;
911 if (offset == 0) {
912 for (int i = 0; i < size; i++) {
913 if (components[i].endOffset > 0) {
914 return i;
915 }
916 }
917 }
918 if (size <= 2) {
919 return size == 1 || offset < components[0].endOffset ? 0 : 1;
920 }
921 for (int low = 0, high = size; low <= high;) {
922 int mid = low + high >>> 1;
923 Component c = components[mid];
924 if (offset >= c.endOffset) {
925 low = mid + 1;
926 } else if (offset < c.offset) {
927 high = mid - 1;
928 } else {
929 return mid;
930 }
931 }
932
933 throw new Error("should not reach here");
934 }
935
936 public int toByteIndex(int cIndex) {
937 checkComponentIndex(cIndex);
938 return components[cIndex].offset;
939 }
940
941 @Override
942 public byte getByte(int index) {
943 Component c = findComponent(index);
944 return c.buf.getByte(c.idx(index));
945 }
946
947 @Override
948 protected byte _getByte(int index) {
949 Component c = findComponent0(index);
950 return c.buf.getByte(c.idx(index));
951 }
952
953 @Override
954 protected short _getShort(int index) {
955 Component c = findComponent0(index);
956 if (index + 2 <= c.endOffset) {
957 return c.buf.getShort(c.idx(index));
958 } else if (order() == ByteOrder.BIG_ENDIAN) {
959 return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff);
960 } else {
961 return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8);
962 }
963 }
964
965 @Override
966 protected short _getShortLE(int index) {
967 Component c = findComponent0(index);
968 if (index + 2 <= c.endOffset) {
969 return c.buf.getShortLE(c.idx(index));
970 } else if (order() == ByteOrder.BIG_ENDIAN) {
971 return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8);
972 } else {
973 return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff);
974 }
975 }
976
977 @Override
978 protected int _getUnsignedMedium(int index) {
979 Component c = findComponent0(index);
980 if (index + 3 <= c.endOffset) {
981 return c.buf.getUnsignedMedium(c.idx(index));
982 } else if (order() == ByteOrder.BIG_ENDIAN) {
983 return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff;
984 } else {
985 return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16;
986 }
987 }
988
989 @Override
990 protected int _getUnsignedMediumLE(int index) {
991 Component c = findComponent0(index);
992 if (index + 3 <= c.endOffset) {
993 return c.buf.getUnsignedMediumLE(c.idx(index));
994 } else if (order() == ByteOrder.BIG_ENDIAN) {
995 return _getShortLE(index) & 0xffff | (_getByte(index + 2) & 0xff) << 16;
996 } else {
997 return (_getShortLE(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff;
998 }
999 }
1000
1001 @Override
1002 protected int _getInt(int index) {
1003 Component c = findComponent0(index);
1004 if (index + 4 <= c.endOffset) {
1005 return c.buf.getInt(c.idx(index));
1006 } else if (order() == ByteOrder.BIG_ENDIAN) {
1007 return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff;
1008 } else {
1009 return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16;
1010 }
1011 }
1012
1013 @Override
1014 protected int _getIntLE(int index) {
1015 Component c = findComponent0(index);
1016 if (index + 4 <= c.endOffset) {
1017 return c.buf.getIntLE(c.idx(index));
1018 } else if (order() == ByteOrder.BIG_ENDIAN) {
1019 return _getShortLE(index) & 0xffff | (_getShortLE(index + 2) & 0xffff) << 16;
1020 } else {
1021 return (_getShortLE(index) & 0xffff) << 16 | _getShortLE(index + 2) & 0xffff;
1022 }
1023 }
1024
1025 @Override
1026 protected long _getLong(int index) {
1027 Component c = findComponent0(index);
1028 if (index + 8 <= c.endOffset) {
1029 return c.buf.getLong(c.idx(index));
1030 } else if (order() == ByteOrder.BIG_ENDIAN) {
1031 return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL;
1032 } else {
1033 return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32;
1034 }
1035 }
1036
1037 @Override
1038 protected long _getLongLE(int index) {
1039 Component c = findComponent0(index);
1040 if (index + 8 <= c.endOffset) {
1041 return c.buf.getLongLE(c.idx(index));
1042 } else if (order() == ByteOrder.BIG_ENDIAN) {
1043 return _getIntLE(index) & 0xffffffffL | (_getIntLE(index + 4) & 0xffffffffL) << 32;
1044 } else {
1045 return (_getIntLE(index) & 0xffffffffL) << 32 | _getIntLE(index + 4) & 0xffffffffL;
1046 }
1047 }
1048
1049 @Override
1050 public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
1051 checkDstIndex(index, length, dstIndex, dst.length);
1052 if (length == 0) {
1053 return this;
1054 }
1055
1056 int i = toComponentIndex0(index);
1057 while (length > 0) {
1058 Component c = components[i];
1059 int localLength = Math.min(length, c.endOffset - index);
1060 c.buf.getBytes(c.idx(index), dst, dstIndex, localLength);
1061 index += localLength;
1062 dstIndex += localLength;
1063 length -= localLength;
1064 i ++;
1065 }
1066 return this;
1067 }
1068
1069 @Override
1070 public CompositeByteBuf getBytes(int index, ByteBuffer dst) {
1071 int limit = dst.limit();
1072 int length = dst.remaining();
1073
1074 checkIndex(index, length);
1075 if (length == 0) {
1076 return this;
1077 }
1078
1079 int i = toComponentIndex0(index);
1080 try {
1081 while (length > 0) {
1082 Component c = components[i];
1083 int localLength = Math.min(length, c.endOffset - index);
1084 dst.limit(dst.position() + localLength);
1085 c.buf.getBytes(c.idx(index), dst);
1086 index += localLength;
1087 length -= localLength;
1088 i ++;
1089 }
1090 } finally {
1091 dst.limit(limit);
1092 }
1093 return this;
1094 }
1095
1096 @Override
1097 public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
1098 checkDstIndex(index, length, dstIndex, dst.capacity());
1099 if (length == 0) {
1100 return this;
1101 }
1102
1103 int i = toComponentIndex0(index);
1104 while (length > 0) {
1105 Component c = components[i];
1106 int localLength = Math.min(length, c.endOffset - index);
1107 c.buf.getBytes(c.idx(index), dst, dstIndex, localLength);
1108 index += localLength;
1109 dstIndex += localLength;
1110 length -= localLength;
1111 i ++;
1112 }
1113 return this;
1114 }
1115
1116 @Override
1117 public int getBytes(int index, GatheringByteChannel out, int length)
1118 throws IOException {
1119 int count = nioBufferCount();
1120 if (count == 1) {
1121 return out.write(internalNioBuffer(index, length));
1122 } else {
1123 long writtenBytes = out.write(nioBuffers(index, length));
1124 if (writtenBytes > Integer.MAX_VALUE) {
1125 return Integer.MAX_VALUE;
1126 } else {
1127 return (int) writtenBytes;
1128 }
1129 }
1130 }
1131
1132 @Override
1133 public int getBytes(int index, FileChannel out, long position, int length)
1134 throws IOException {
1135 int count = nioBufferCount();
1136 if (count == 1) {
1137 return out.write(internalNioBuffer(index, length), position);
1138 } else {
1139 long writtenBytes = 0;
1140 for (ByteBuffer buf : nioBuffers(index, length)) {
1141 writtenBytes += out.write(buf, position + writtenBytes);
1142 }
1143 if (writtenBytes > Integer.MAX_VALUE) {
1144 return Integer.MAX_VALUE;
1145 }
1146 return (int) writtenBytes;
1147 }
1148 }
1149
1150 @Override
1151 public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
1152 checkIndex(index, length);
1153 if (length == 0) {
1154 return this;
1155 }
1156
1157 int i = toComponentIndex0(index);
1158 while (length > 0) {
1159 Component c = components[i];
1160 int localLength = Math.min(length, c.endOffset - index);
1161 c.buf.getBytes(c.idx(index), out, localLength);
1162 index += localLength;
1163 length -= localLength;
1164 i ++;
1165 }
1166 return this;
1167 }
1168
1169 @Override
1170 public CompositeByteBuf setByte(int index, int value) {
1171 Component c = findComponent(index);
1172 c.buf.setByte(c.idx(index), value);
1173 return this;
1174 }
1175
1176 @Override
1177 protected void _setByte(int index, int value) {
1178 Component c = findComponent0(index);
1179 c.buf.setByte(c.idx(index), value);
1180 }
1181
1182 @Override
1183 public CompositeByteBuf setShort(int index, int value) {
1184 checkIndex(index, 2);
1185 _setShort(index, value);
1186 return this;
1187 }
1188
1189 @Override
1190 protected void _setShort(int index, int value) {
1191 Component c = findComponent0(index);
1192 if (index + 2 <= c.endOffset) {
1193 c.buf.setShort(c.idx(index), value);
1194 } else if (order() == ByteOrder.BIG_ENDIAN) {
1195 _setByte(index, (byte) (value >>> 8));
1196 _setByte(index + 1, (byte) value);
1197 } else {
1198 _setByte(index, (byte) value);
1199 _setByte(index + 1, (byte) (value >>> 8));
1200 }
1201 }
1202
1203 @Override
1204 protected void _setShortLE(int index, int value) {
1205 Component c = findComponent0(index);
1206 if (index + 2 <= c.endOffset) {
1207 c.buf.setShortLE(c.idx(index), value);
1208 } else if (order() == ByteOrder.BIG_ENDIAN) {
1209 _setByte(index, (byte) value);
1210 _setByte(index + 1, (byte) (value >>> 8));
1211 } else {
1212 _setByte(index, (byte) (value >>> 8));
1213 _setByte(index + 1, (byte) value);
1214 }
1215 }
1216
1217 @Override
1218 public CompositeByteBuf setMedium(int index, int value) {
1219 checkIndex(index, 3);
1220 _setMedium(index, value);
1221 return this;
1222 }
1223
1224 @Override
1225 protected void _setMedium(int index, int value) {
1226 Component c = findComponent0(index);
1227 if (index + 3 <= c.endOffset) {
1228 c.buf.setMedium(c.idx(index), value);
1229 } else if (order() == ByteOrder.BIG_ENDIAN) {
1230 _setShort(index, (short) (value >> 8));
1231 _setByte(index + 2, (byte) value);
1232 } else {
1233 _setShort(index, (short) value);
1234 _setByte(index + 2, (byte) (value >>> 16));
1235 }
1236 }
1237
1238 @Override
1239 protected void _setMediumLE(int index, int value) {
1240 Component c = findComponent0(index);
1241 if (index + 3 <= c.endOffset) {
1242 c.buf.setMediumLE(c.idx(index), value);
1243 } else if (order() == ByteOrder.BIG_ENDIAN) {
1244 _setShortLE(index, (short) value);
1245 _setByte(index + 2, (byte) (value >>> 16));
1246 } else {
1247 _setShortLE(index, (short) (value >> 8));
1248 _setByte(index + 2, (byte) value);
1249 }
1250 }
1251
1252 @Override
1253 public CompositeByteBuf setInt(int index, int value) {
1254 checkIndex(index, 4);
1255 _setInt(index, value);
1256 return this;
1257 }
1258
1259 @Override
1260 protected void _setInt(int index, int value) {
1261 Component c = findComponent0(index);
1262 if (index + 4 <= c.endOffset) {
1263 c.buf.setInt(c.idx(index), value);
1264 } else if (order() == ByteOrder.BIG_ENDIAN) {
1265 _setShort(index, (short) (value >>> 16));
1266 _setShort(index + 2, (short) value);
1267 } else {
1268 _setShort(index, (short) value);
1269 _setShort(index + 2, (short) (value >>> 16));
1270 }
1271 }
1272
1273 @Override
1274 protected void _setIntLE(int index, int value) {
1275 Component c = findComponent0(index);
1276 if (index + 4 <= c.endOffset) {
1277 c.buf.setIntLE(c.idx(index), value);
1278 } else if (order() == ByteOrder.BIG_ENDIAN) {
1279 _setShortLE(index, (short) value);
1280 _setShortLE(index + 2, (short) (value >>> 16));
1281 } else {
1282 _setShortLE(index, (short) (value >>> 16));
1283 _setShortLE(index + 2, (short) value);
1284 }
1285 }
1286
1287 @Override
1288 public CompositeByteBuf setLong(int index, long value) {
1289 checkIndex(index, 8);
1290 _setLong(index, value);
1291 return this;
1292 }
1293
1294 @Override
1295 protected void _setLong(int index, long value) {
1296 Component c = findComponent0(index);
1297 if (index + 8 <= c.endOffset) {
1298 c.buf.setLong(c.idx(index), value);
1299 } else if (order() == ByteOrder.BIG_ENDIAN) {
1300 _setInt(index, (int) (value >>> 32));
1301 _setInt(index + 4, (int) value);
1302 } else {
1303 _setInt(index, (int) value);
1304 _setInt(index + 4, (int) (value >>> 32));
1305 }
1306 }
1307
1308 @Override
1309 protected void _setLongLE(int index, long value) {
1310 Component c = findComponent0(index);
1311 if (index + 8 <= c.endOffset) {
1312 c.buf.setLongLE(c.idx(index), value);
1313 } else if (order() == ByteOrder.BIG_ENDIAN) {
1314 _setIntLE(index, (int) value);
1315 _setIntLE(index + 4, (int) (value >>> 32));
1316 } else {
1317 _setIntLE(index, (int) (value >>> 32));
1318 _setIntLE(index + 4, (int) value);
1319 }
1320 }
1321
1322 @Override
1323 public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
1324 checkSrcIndex(index, length, srcIndex, src.length);
1325 if (length == 0) {
1326 return this;
1327 }
1328
1329 int i = toComponentIndex0(index);
1330 while (length > 0) {
1331 Component c = components[i];
1332 int localLength = Math.min(length, c.endOffset - index);
1333 c.buf.setBytes(c.idx(index), src, srcIndex, localLength);
1334 index += localLength;
1335 srcIndex += localLength;
1336 length -= localLength;
1337 i ++;
1338 }
1339 return this;
1340 }
1341
1342 @Override
1343 public CompositeByteBuf setBytes(int index, ByteBuffer src) {
1344 int limit = src.limit();
1345 int length = src.remaining();
1346
1347 checkIndex(index, length);
1348 if (length == 0) {
1349 return this;
1350 }
1351
1352 int i = toComponentIndex0(index);
1353 try {
1354 while (length > 0) {
1355 Component c = components[i];
1356 int localLength = Math.min(length, c.endOffset - index);
1357 src.limit(src.position() + localLength);
1358 c.buf.setBytes(c.idx(index), src);
1359 index += localLength;
1360 length -= localLength;
1361 i ++;
1362 }
1363 } finally {
1364 src.limit(limit);
1365 }
1366 return this;
1367 }
1368
1369 @Override
1370 public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
1371 checkSrcIndex(index, length, srcIndex, src.capacity());
1372 if (length == 0) {
1373 return this;
1374 }
1375
1376 int i = toComponentIndex0(index);
1377 while (length > 0) {
1378 Component c = components[i];
1379 int localLength = Math.min(length, c.endOffset - index);
1380 c.buf.setBytes(c.idx(index), src, srcIndex, localLength);
1381 index += localLength;
1382 srcIndex += localLength;
1383 length -= localLength;
1384 i ++;
1385 }
1386 return this;
1387 }
1388
1389 @Override
1390 public int setBytes(int index, InputStream in, int length) throws IOException {
1391 checkIndex(index, length);
1392 if (length == 0) {
1393 return in.read(EmptyArrays.EMPTY_BYTES);
1394 }
1395
1396 int i = toComponentIndex0(index);
1397 int readBytes = 0;
1398 do {
1399 Component c = components[i];
1400 int localLength = Math.min(length, c.endOffset - index);
1401 if (localLength == 0) {
1402
1403 i++;
1404 continue;
1405 }
1406 int localReadBytes = c.buf.setBytes(c.idx(index), in, localLength);
1407 if (localReadBytes < 0) {
1408 if (readBytes == 0) {
1409 return -1;
1410 } else {
1411 break;
1412 }
1413 }
1414
1415 index += localReadBytes;
1416 length -= localReadBytes;
1417 readBytes += localReadBytes;
1418 if (localReadBytes == localLength) {
1419 i ++;
1420 }
1421 } while (length > 0);
1422
1423 return readBytes;
1424 }
1425
1426 @Override
1427 public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
1428 checkIndex(index, length);
1429 if (length == 0) {
1430 return in.read(EMPTY_NIO_BUFFER);
1431 }
1432
1433 int i = toComponentIndex0(index);
1434 int readBytes = 0;
1435 do {
1436 Component c = components[i];
1437 int localLength = Math.min(length, c.endOffset - index);
1438 if (localLength == 0) {
1439
1440 i++;
1441 continue;
1442 }
1443 int localReadBytes = c.buf.setBytes(c.idx(index), in, localLength);
1444
1445 if (localReadBytes == 0) {
1446 break;
1447 }
1448
1449 if (localReadBytes < 0) {
1450 if (readBytes == 0) {
1451 return -1;
1452 } else {
1453 break;
1454 }
1455 }
1456
1457 index += localReadBytes;
1458 length -= localReadBytes;
1459 readBytes += localReadBytes;
1460 if (localReadBytes == localLength) {
1461 i ++;
1462 }
1463 } while (length > 0);
1464
1465 return readBytes;
1466 }
1467
1468 @Override
1469 public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
1470 checkIndex(index, length);
1471 if (length == 0) {
1472 return in.read(EMPTY_NIO_BUFFER, position);
1473 }
1474
1475 int i = toComponentIndex0(index);
1476 int readBytes = 0;
1477 do {
1478 Component c = components[i];
1479 int localLength = Math.min(length, c.endOffset - index);
1480 if (localLength == 0) {
1481
1482 i++;
1483 continue;
1484 }
1485 int localReadBytes = c.buf.setBytes(c.idx(index), in, position + readBytes, localLength);
1486
1487 if (localReadBytes == 0) {
1488 break;
1489 }
1490
1491 if (localReadBytes < 0) {
1492 if (readBytes == 0) {
1493 return -1;
1494 } else {
1495 break;
1496 }
1497 }
1498
1499 index += localReadBytes;
1500 length -= localReadBytes;
1501 readBytes += localReadBytes;
1502 if (localReadBytes == localLength) {
1503 i ++;
1504 }
1505 } while (length > 0);
1506
1507 return readBytes;
1508 }
1509
1510 @Override
1511 public ByteBuf copy(int index, int length) {
1512 checkIndex(index, length);
1513 ByteBuf dst = allocBuffer(length);
1514 if (length != 0) {
1515 copyTo(index, length, toComponentIndex0(index), dst);
1516 }
1517 return dst;
1518 }
1519
1520 private void copyTo(int index, int length, int componentId, ByteBuf dst) {
1521 int dstIndex = 0;
1522 int i = componentId;
1523
1524 while (length > 0) {
1525 Component c = components[i];
1526 int localLength = Math.min(length, c.endOffset - index);
1527 c.buf.getBytes(c.idx(index), dst, dstIndex, localLength);
1528 index += localLength;
1529 dstIndex += localLength;
1530 length -= localLength;
1531 i ++;
1532 }
1533
1534 dst.writerIndex(dst.capacity());
1535 }
1536
1537
1543 public ByteBuf component(int cIndex) {
1544 checkComponentIndex(cIndex);
1545 return components[cIndex].duplicate();
1546 }
1547
1548
1554 public ByteBuf componentAtOffset(int offset) {
1555 return findComponent(offset).duplicate();
1556 }
1557
1558
1564 public ByteBuf internalComponent(int cIndex) {
1565 checkComponentIndex(cIndex);
1566 return components[cIndex].slice();
1567 }
1568
1569
1575 public ByteBuf internalComponentAtOffset(int offset) {
1576 return findComponent(offset).slice();
1577 }
1578
1579
1580 private Component lastAccessed;
1581
1582 private Component findComponent(int offset) {
1583 Component la = lastAccessed;
1584 if (la != null && offset >= la.offset && offset < la.endOffset) {
1585 ensureAccessible();
1586 return la;
1587 }
1588 checkIndex(offset);
1589 return findIt(offset);
1590 }
1591
1592 private Component findComponent0(int offset) {
1593 Component la = lastAccessed;
1594 if (la != null && offset >= la.offset && offset < la.endOffset) {
1595 return la;
1596 }
1597 return findIt(offset);
1598 }
1599
1600 private Component findIt(int offset) {
1601 for (int low = 0, high = componentCount; low <= high;) {
1602 int mid = low + high >>> 1;
1603 Component c = components[mid];
1604 if (offset >= c.endOffset) {
1605 low = mid + 1;
1606 } else if (offset < c.offset) {
1607 high = mid - 1;
1608 } else {
1609 lastAccessed = c;
1610 return c;
1611 }
1612 }
1613
1614 throw new Error("should not reach here");
1615 }
1616
1617 @Override
1618 public int nioBufferCount() {
1619 int size = componentCount;
1620 switch (size) {
1621 case 0:
1622 return 1;
1623 case 1:
1624 return components[0].buf.nioBufferCount();
1625 default:
1626 int count = 0;
1627 for (int i = 0; i < size; i++) {
1628 count += components[i].buf.nioBufferCount();
1629 }
1630 return count;
1631 }
1632 }
1633
1634 @Override
1635 public ByteBuffer internalNioBuffer(int index, int length) {
1636 switch (componentCount) {
1637 case 0:
1638 return EMPTY_NIO_BUFFER;
1639 case 1:
1640 return components[0].internalNioBuffer(index, length);
1641 default:
1642 throw new UnsupportedOperationException();
1643 }
1644 }
1645
1646 @Override
1647 public ByteBuffer nioBuffer(int index, int length) {
1648 checkIndex(index, length);
1649
1650 switch (componentCount) {
1651 case 0:
1652 return EMPTY_NIO_BUFFER;
1653 case 1:
1654 Component c = components[0];
1655 ByteBuf buf = c.buf;
1656 if (buf.nioBufferCount() == 1) {
1657 return buf.nioBuffer(c.idx(index), length);
1658 }
1659 }
1660
1661 ByteBuffer[] buffers = nioBuffers(index, length);
1662
1663 if (buffers.length == 1) {
1664 return buffers[0];
1665 }
1666
1667 ByteBuffer merged = ByteBuffer.allocate(length).order(order());
1668 for (ByteBuffer buf: buffers) {
1669 merged.put(buf);
1670 }
1671
1672 merged.flip();
1673 return merged;
1674 }
1675
1676 @Override
1677 public ByteBuffer[] nioBuffers(int index, int length) {
1678 checkIndex(index, length);
1679 if (length == 0) {
1680 return new ByteBuffer[] { EMPTY_NIO_BUFFER };
1681 }
1682
1683 RecyclableArrayList buffers = RecyclableArrayList.newInstance(componentCount);
1684 try {
1685 int i = toComponentIndex0(index);
1686 while (length > 0) {
1687 Component c = components[i];
1688 ByteBuf s = c.buf;
1689 int localLength = Math.min(length, c.endOffset - index);
1690 switch (s.nioBufferCount()) {
1691 case 0:
1692 throw new UnsupportedOperationException();
1693 case 1:
1694 buffers.add(s.nioBuffer(c.idx(index), localLength));
1695 break;
1696 default:
1697 Collections.addAll(buffers, s.nioBuffers(c.idx(index), localLength));
1698 }
1699
1700 index += localLength;
1701 length -= localLength;
1702 i ++;
1703 }
1704
1705 return buffers.toArray(new ByteBuffer[0]);
1706 } finally {
1707 buffers.recycle();
1708 }
1709 }
1710
1711
1714 public CompositeByteBuf consolidate() {
1715 ensureAccessible();
1716 consolidate0(0, componentCount);
1717 return this;
1718 }
1719
1720
1726 public CompositeByteBuf consolidate(int cIndex, int numComponents) {
1727 checkComponentIndex(cIndex, numComponents);
1728 consolidate0(cIndex, numComponents);
1729 return this;
1730 }
1731
1732 private void consolidate0(int cIndex, int numComponents) {
1733 if (numComponents <= 1) {
1734 return;
1735 }
1736
1737 final int endCIndex = cIndex + numComponents;
1738 final int startOffset = cIndex != 0 ? components[cIndex].offset : 0;
1739 final int capacity = components[endCIndex - 1].endOffset - startOffset;
1740 final ByteBuf consolidated = allocBuffer(capacity);
1741
1742 for (int i = cIndex; i < endCIndex; i ++) {
1743 components[i].transferTo(consolidated);
1744 }
1745 lastAccessed = null;
1746 removeCompRange(cIndex + 1, endCIndex);
1747 components[cIndex] = newComponent(consolidated, 0);
1748 if (cIndex != 0 || numComponents != componentCount) {
1749 updateComponentOffsets(cIndex);
1750 }
1751 }
1752
1753
1756 public CompositeByteBuf discardReadComponents() {
1757 ensureAccessible();
1758 final int readerIndex = readerIndex();
1759 if (readerIndex == 0) {
1760 return this;
1761 }
1762
1763
1764 int writerIndex = writerIndex();
1765 if (readerIndex == writerIndex && writerIndex == capacity()) {
1766 for (int i = 0, size = componentCount; i < size; i++) {
1767 components[i].free();
1768 }
1769 lastAccessed = null;
1770 clearComps();
1771 setIndex(0, 0);
1772 adjustMarkers(readerIndex);
1773 return this;
1774 }
1775
1776
1777 int firstComponentId = 0;
1778 Component c = null;
1779 for (int size = componentCount; firstComponentId < size; firstComponentId++) {
1780 c = components[firstComponentId];
1781 if (c.endOffset > readerIndex) {
1782 break;
1783 }
1784 c.free();
1785 }
1786 if (firstComponentId == 0) {
1787 return this;
1788 }
1789 Component la = lastAccessed;
1790 if (la != null && la.endOffset <= readerIndex) {
1791 lastAccessed = null;
1792 }
1793 removeCompRange(0, firstComponentId);
1794
1795
1796 int offset = c.offset;
1797 updateComponentOffsets(0);
1798 setIndex(readerIndex - offset, writerIndex - offset);
1799 adjustMarkers(offset);
1800 return this;
1801 }
1802
1803 @Override
1804 public CompositeByteBuf discardReadBytes() {
1805 ensureAccessible();
1806 final int readerIndex = readerIndex();
1807 if (readerIndex == 0) {
1808 return this;
1809 }
1810
1811
1812 int writerIndex = writerIndex();
1813 if (readerIndex == writerIndex && writerIndex == capacity()) {
1814 for (int i = 0, size = componentCount; i < size; i++) {
1815 components[i].free();
1816 }
1817 lastAccessed = null;
1818 clearComps();
1819 setIndex(0, 0);
1820 adjustMarkers(readerIndex);
1821 return this;
1822 }
1823
1824 int firstComponentId = 0;
1825 Component c = null;
1826 for (int size = componentCount; firstComponentId < size; firstComponentId++) {
1827 c = components[firstComponentId];
1828 if (c.endOffset > readerIndex) {
1829 break;
1830 }
1831 c.free();
1832 }
1833
1834
1835 int trimmedBytes = readerIndex - c.offset;
1836 c.offset = 0;
1837 c.endOffset -= readerIndex;
1838 c.srcAdjustment += readerIndex;
1839 c.adjustment += readerIndex;
1840 ByteBuf slice = c.slice;
1841 if (slice != null) {
1842
1843
1844 c.slice = slice.slice(trimmedBytes, c.length());
1845 }
1846 Component la = lastAccessed;
1847 if (la != null && la.endOffset <= readerIndex) {
1848 lastAccessed = null;
1849 }
1850
1851 removeCompRange(0, firstComponentId);
1852
1853
1854 updateComponentOffsets(0);
1855 setIndex(0, writerIndex - readerIndex);
1856 adjustMarkers(readerIndex);
1857 return this;
1858 }
1859
1860 private ByteBuf allocBuffer(int capacity) {
1861 return direct ? alloc().directBuffer(capacity) : alloc().heapBuffer(capacity);
1862 }
1863
1864 @Override
1865 public String toString() {
1866 String result = super.toString();
1867 result = result.substring(0, result.length() - 1);
1868 return result + ", components=" + componentCount + ')';
1869 }
1870
1871 private static final class Component {
1872 final ByteBuf srcBuf;
1873 final ByteBuf buf;
1874
1875 int srcAdjustment;
1876 int adjustment;
1877
1878 int offset;
1879 int endOffset;
1880
1881 private ByteBuf slice;
1882
1883 Component(ByteBuf srcBuf, int srcOffset, ByteBuf buf, int bufOffset,
1884 int offset, int len, ByteBuf slice) {
1885 this.srcBuf = srcBuf;
1886 this.srcAdjustment = srcOffset - offset;
1887 this.buf = buf;
1888 this.adjustment = bufOffset - offset;
1889 this.offset = offset;
1890 this.endOffset = offset + len;
1891 this.slice = slice;
1892 }
1893
1894 int srcIdx(int index) {
1895 return index + srcAdjustment;
1896 }
1897
1898 int idx(int index) {
1899 return index + adjustment;
1900 }
1901
1902 int length() {
1903 return endOffset - offset;
1904 }
1905
1906 void reposition(int newOffset) {
1907 int move = newOffset - offset;
1908 endOffset += move;
1909 srcAdjustment -= move;
1910 adjustment -= move;
1911 offset = newOffset;
1912 }
1913
1914
1915 void transferTo(ByteBuf dst) {
1916 dst.writeBytes(buf, idx(offset), length());
1917 free();
1918 }
1919
1920 ByteBuf slice() {
1921 ByteBuf s = slice;
1922 if (s == null) {
1923 slice = s = srcBuf.slice(srcIdx(offset), length());
1924 }
1925 return s;
1926 }
1927
1928 ByteBuf duplicate() {
1929 return srcBuf.duplicate();
1930 }
1931
1932 ByteBuffer internalNioBuffer(int index, int length) {
1933
1934 return srcBuf.internalNioBuffer(srcIdx(index), length);
1935 }
1936
1937 void free() {
1938 slice = null;
1939
1940
1941 srcBuf.release();
1942 }
1943 }
1944
1945 @Override
1946 public CompositeByteBuf readerIndex(int readerIndex) {
1947 super.readerIndex(readerIndex);
1948 return this;
1949 }
1950
1951 @Override
1952 public CompositeByteBuf writerIndex(int writerIndex) {
1953 super.writerIndex(writerIndex);
1954 return this;
1955 }
1956
1957 @Override
1958 public CompositeByteBuf setIndex(int readerIndex, int writerIndex) {
1959 super.setIndex(readerIndex, writerIndex);
1960 return this;
1961 }
1962
1963 @Override
1964 public CompositeByteBuf clear() {
1965 super.clear();
1966 return this;
1967 }
1968
1969 @Override
1970 public CompositeByteBuf markReaderIndex() {
1971 super.markReaderIndex();
1972 return this;
1973 }
1974
1975 @Override
1976 public CompositeByteBuf resetReaderIndex() {
1977 super.resetReaderIndex();
1978 return this;
1979 }
1980
1981 @Override
1982 public CompositeByteBuf markWriterIndex() {
1983 super.markWriterIndex();
1984 return this;
1985 }
1986
1987 @Override
1988 public CompositeByteBuf resetWriterIndex() {
1989 super.resetWriterIndex();
1990 return this;
1991 }
1992
1993 @Override
1994 public CompositeByteBuf ensureWritable(int minWritableBytes) {
1995 super.ensureWritable(minWritableBytes);
1996 return this;
1997 }
1998
1999 @Override
2000 public CompositeByteBuf getBytes(int index, ByteBuf dst) {
2001 return getBytes(index, dst, dst.writableBytes());
2002 }
2003
2004 @Override
2005 public CompositeByteBuf getBytes(int index, ByteBuf dst, int length) {
2006 getBytes(index, dst, dst.writerIndex(), length);
2007 dst.writerIndex(dst.writerIndex() + length);
2008 return this;
2009 }
2010
2011 @Override
2012 public CompositeByteBuf getBytes(int index, byte[] dst) {
2013 return getBytes(index, dst, 0, dst.length);
2014 }
2015
2016 @Override
2017 public CompositeByteBuf setBoolean(int index, boolean value) {
2018 return setByte(index, value? 1 : 0);
2019 }
2020
2021 @Override
2022 public CompositeByteBuf setChar(int index, int value) {
2023 return setShort(index, value);
2024 }
2025
2026 @Override
2027 public CompositeByteBuf setFloat(int index, float value) {
2028 return setInt(index, Float.floatToRawIntBits(value));
2029 }
2030
2031 @Override
2032 public CompositeByteBuf setDouble(int index, double value) {
2033 return setLong(index, Double.doubleToRawLongBits(value));
2034 }
2035
2036 @Override
2037 public CompositeByteBuf setBytes(int index, ByteBuf src) {
2038 super.setBytes(index, src, src.readableBytes());
2039 return this;
2040 }
2041
2042 @Override
2043 public CompositeByteBuf setBytes(int index, ByteBuf src, int length) {
2044 super.setBytes(index, src, length);
2045 return this;
2046 }
2047
2048 @Override
2049 public CompositeByteBuf setBytes(int index, byte[] src) {
2050 return setBytes(index, src, 0, src.length);
2051 }
2052
2053 @Override
2054 public CompositeByteBuf setZero(int index, int length) {
2055 super.setZero(index, length);
2056 return this;
2057 }
2058
2059 @Override
2060 public CompositeByteBuf readBytes(ByteBuf dst) {
2061 super.readBytes(dst, dst.writableBytes());
2062 return this;
2063 }
2064
2065 @Override
2066 public CompositeByteBuf readBytes(ByteBuf dst, int length) {
2067 super.readBytes(dst, length);
2068 return this;
2069 }
2070
2071 @Override
2072 public CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
2073 super.readBytes(dst, dstIndex, length);
2074 return this;
2075 }
2076
2077 @Override
2078 public CompositeByteBuf readBytes(byte[] dst) {
2079 super.readBytes(dst, 0, dst.length);
2080 return this;
2081 }
2082
2083 @Override
2084 public CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) {
2085 super.readBytes(dst, dstIndex, length);
2086 return this;
2087 }
2088
2089 @Override
2090 public CompositeByteBuf readBytes(ByteBuffer dst) {
2091 super.readBytes(dst);
2092 return this;
2093 }
2094
2095 @Override
2096 public CompositeByteBuf readBytes(OutputStream out, int length) throws IOException {
2097 super.readBytes(out, length);
2098 return this;
2099 }
2100
2101 @Override
2102 public CompositeByteBuf skipBytes(int length) {
2103 super.skipBytes(length);
2104 return this;
2105 }
2106
2107 @Override
2108 public CompositeByteBuf writeBoolean(boolean value) {
2109 writeByte(value ? 1 : 0);
2110 return this;
2111 }
2112
2113 @Override
2114 public CompositeByteBuf writeByte(int value) {
2115 ensureWritable0(1);
2116 _setByte(writerIndex++, value);
2117 return this;
2118 }
2119
2120 @Override
2121 public CompositeByteBuf writeShort(int value) {
2122 super.writeShort(value);
2123 return this;
2124 }
2125
2126 @Override
2127 public CompositeByteBuf writeMedium(int value) {
2128 super.writeMedium(value);
2129 return this;
2130 }
2131
2132 @Override
2133 public CompositeByteBuf writeInt(int value) {
2134 super.writeInt(value);
2135 return this;
2136 }
2137
2138 @Override
2139 public CompositeByteBuf writeLong(long value) {
2140 super.writeLong(value);
2141 return this;
2142 }
2143
2144 @Override
2145 public CompositeByteBuf writeChar(int value) {
2146 super.writeShort(value);
2147 return this;
2148 }
2149
2150 @Override
2151 public CompositeByteBuf writeFloat(float value) {
2152 super.writeInt(Float.floatToRawIntBits(value));
2153 return this;
2154 }
2155
2156 @Override
2157 public CompositeByteBuf writeDouble(double value) {
2158 super.writeLong(Double.doubleToRawLongBits(value));
2159 return this;
2160 }
2161
2162 @Override
2163 public CompositeByteBuf writeBytes(ByteBuf src) {
2164 super.writeBytes(src, src.readableBytes());
2165 return this;
2166 }
2167
2168 @Override
2169 public CompositeByteBuf writeBytes(ByteBuf src, int length) {
2170 super.writeBytes(src, length);
2171 return this;
2172 }
2173
2174 @Override
2175 public CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
2176 super.writeBytes(src, srcIndex, length);
2177 return this;
2178 }
2179
2180 @Override
2181 public CompositeByteBuf writeBytes(byte[] src) {
2182 super.writeBytes(src, 0, src.length);
2183 return this;
2184 }
2185
2186 @Override
2187 public CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) {
2188 super.writeBytes(src, srcIndex, length);
2189 return this;
2190 }
2191
2192 @Override
2193 public CompositeByteBuf writeBytes(ByteBuffer src) {
2194 super.writeBytes(src);
2195 return this;
2196 }
2197
2198 @Override
2199 public CompositeByteBuf writeZero(int length) {
2200 super.writeZero(length);
2201 return this;
2202 }
2203
2204 @Override
2205 public CompositeByteBuf retain(int increment) {
2206 super.retain(increment);
2207 return this;
2208 }
2209
2210 @Override
2211 public CompositeByteBuf retain() {
2212 super.retain();
2213 return this;
2214 }
2215
2216 @Override
2217 public CompositeByteBuf touch() {
2218 return this;
2219 }
2220
2221 @Override
2222 public CompositeByteBuf touch(Object hint) {
2223 return this;
2224 }
2225
2226 @Override
2227 public ByteBuffer[] nioBuffers() {
2228 return nioBuffers(readerIndex(), readableBytes());
2229 }
2230
2231 @Override
2232 public CompositeByteBuf discardSomeReadBytes() {
2233 return discardReadComponents();
2234 }
2235
2236 @Override
2237 protected void deallocate() {
2238 if (freed) {
2239 return;
2240 }
2241
2242 freed = true;
2243
2244
2245 for (int i = 0, size = componentCount; i < size; i++) {
2246 components[i].free();
2247 }
2248 }
2249
2250 @Override
2251 boolean isAccessible() {
2252 return !freed;
2253 }
2254
2255 @Override
2256 public ByteBuf unwrap() {
2257 return null;
2258 }
2259
2260 private final class CompositeByteBufIterator implements Iterator<ByteBuf> {
2261 private final int size = numComponents();
2262 private int index;
2263
2264 @Override
2265 public boolean hasNext() {
2266 return size > index;
2267 }
2268
2269 @Override
2270 public ByteBuf next() {
2271 if (size != numComponents()) {
2272 throw new ConcurrentModificationException();
2273 }
2274 if (!hasNext()) {
2275 throw new NoSuchElementException();
2276 }
2277 try {
2278 return components[index++].slice();
2279 } catch (IndexOutOfBoundsException e) {
2280 throw new ConcurrentModificationException();
2281 }
2282 }
2283
2284 @Override
2285 public void remove() {
2286 throw new UnsupportedOperationException("Read-Only");
2287 }
2288 }
2289
2290
2291
2292 private void clearComps() {
2293 removeCompRange(0, componentCount);
2294 }
2295
2296 private void removeComp(int i) {
2297 removeCompRange(i, i + 1);
2298 }
2299
2300 private void removeCompRange(int from, int to) {
2301 if (from >= to) {
2302 return;
2303 }
2304 final int size = componentCount;
2305 assert from >= 0 && to <= size;
2306 if (to < size) {
2307 System.arraycopy(components, to, components, from, size - to);
2308 }
2309 int newSize = size - to + from;
2310 for (int i = newSize; i < size; i++) {
2311 components[i] = null;
2312 }
2313 componentCount = newSize;
2314 }
2315
2316 private void addComp(int i, Component c) {
2317 shiftComps(i, 1);
2318 components[i] = c;
2319 }
2320
2321 private void shiftComps(int i, int count) {
2322 final int size = componentCount, newSize = size + count;
2323 assert i >= 0 && i <= size && count > 0;
2324 if (newSize > components.length) {
2325
2326 int newArrSize = Math.max(size + (size >> 1), newSize);
2327 Component[] newArr;
2328 if (i == size) {
2329 newArr = Arrays.copyOf(components, newArrSize, Component[].class);
2330 } else {
2331 newArr = new Component[newArrSize];
2332 if (i > 0) {
2333 System.arraycopy(components, 0, newArr, 0, i);
2334 }
2335 if (i < size) {
2336 System.arraycopy(components, i, newArr, i + count, size - i);
2337 }
2338 }
2339 components = newArr;
2340 } else if (i < size) {
2341 System.arraycopy(components, i, components, i + count, size - i);
2342 }
2343 componentCount = newSize;
2344 }
2345 }
2346