1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import io.netty.util.internal.EmptyArrays;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 import java.nio.channels.GatheringByteChannel;
26 import java.nio.channels.ScatteringByteChannel;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.ConcurrentModificationException;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.ListIterator;
34 import java.util.NoSuchElementException;
35
36 import static io.netty.util.internal.ObjectUtil.checkNotNull;
37
38
39
40
41
42
43 public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable<ByteBuf> {
44
45 private static final ByteBuffer EMPTY_NIO_BUFFER = Unpooled.EMPTY_BUFFER.nioBuffer();
46 private static final Iterator<ByteBuf> EMPTY_ITERATOR = Collections.<ByteBuf>emptyList().iterator();
47
48 private final ByteBufAllocator alloc;
49 private final boolean direct;
50 private final ComponentList components;
51 private final int maxNumComponents;
52
53 private boolean freed;
54
55 public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents) {
56 super(AbstractByteBufAllocator.DEFAULT_MAX_CAPACITY);
57 if (alloc == null) {
58 throw new NullPointerException("alloc");
59 }
60 this.alloc = alloc;
61 this.direct = direct;
62 this.maxNumComponents = maxNumComponents;
63 components = newList(maxNumComponents);
64 }
65
66 public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf... buffers) {
67 this(alloc, direct, maxNumComponents, buffers, 0, buffers.length);
68 }
69
70 CompositeByteBuf(
71 ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf[] buffers, int offset, int len) {
72 super(AbstractByteBufAllocator.DEFAULT_MAX_CAPACITY);
73 if (alloc == null) {
74 throw new NullPointerException("alloc");
75 }
76 if (maxNumComponents < 2) {
77 throw new IllegalArgumentException(
78 "maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
79 }
80
81 this.alloc = alloc;
82 this.direct = direct;
83 this.maxNumComponents = maxNumComponents;
84 components = newList(maxNumComponents);
85
86 addComponents0(false, 0, buffers, offset, len);
87 consolidateIfNeeded();
88 setIndex(0, capacity());
89 }
90
91 public CompositeByteBuf(
92 ByteBufAllocator alloc, boolean direct, int maxNumComponents, Iterable<ByteBuf> buffers) {
93 super(AbstractByteBufAllocator.DEFAULT_MAX_CAPACITY);
94 if (alloc == null) {
95 throw new NullPointerException("alloc");
96 }
97 if (maxNumComponents < 2) {
98 throw new IllegalArgumentException(
99 "maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
100 }
101
102 this.alloc = alloc;
103 this.direct = direct;
104 this.maxNumComponents = maxNumComponents;
105 components = newList(maxNumComponents);
106
107 addComponents0(false, 0, buffers);
108 consolidateIfNeeded();
109 setIndex(0, capacity());
110 }
111
112 private static ComponentList newList(int maxNumComponents) {
113 return new ComponentList(Math.min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents));
114 }
115
116
117 CompositeByteBuf(ByteBufAllocator alloc) {
118 super(Integer.MAX_VALUE);
119 this.alloc = alloc;
120 direct = false;
121 maxNumComponents = 0;
122 components = null;
123 }
124
125
126
127
128
129
130
131
132
133
134
135 public CompositeByteBuf addComponent(ByteBuf buffer) {
136 return addComponent(false, buffer);
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150 public CompositeByteBuf addComponents(ByteBuf... buffers) {
151 return addComponents(false, buffers);
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165 public CompositeByteBuf addComponents(Iterable<ByteBuf> buffers) {
166 return addComponents(false, buffers);
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180 public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) {
181 return addComponent(false, cIndex, buffer);
182 }
183
184
185
186
187
188
189
190
191
192 public CompositeByteBuf addComponent(boolean increaseWriterIndex, ByteBuf buffer) {
193 checkNotNull(buffer, "buffer");
194 addComponent0(increaseWriterIndex, components.size(), buffer);
195 consolidateIfNeeded();
196 return this;
197 }
198
199
200
201
202
203
204
205
206
207
208 public CompositeByteBuf addComponents(boolean increaseWriterIndex, ByteBuf... buffers) {
209 addComponents0(increaseWriterIndex, components.size(), buffers, 0, buffers.length);
210 consolidateIfNeeded();
211 return this;
212 }
213
214
215
216
217
218
219
220
221
222
223 public CompositeByteBuf addComponents(boolean increaseWriterIndex, Iterable<ByteBuf> buffers) {
224 addComponents0(increaseWriterIndex, components.size(), buffers);
225 consolidateIfNeeded();
226 return this;
227 }
228
229
230
231
232
233
234
235
236
237
238 public CompositeByteBuf addComponent(boolean increaseWriterIndex, int cIndex, ByteBuf buffer) {
239 checkNotNull(buffer, "buffer");
240 addComponent0(increaseWriterIndex, cIndex, buffer);
241 consolidateIfNeeded();
242 return this;
243 }
244
245
246
247
248 private int addComponent0(boolean increaseWriterIndex, int cIndex, ByteBuf buffer) {
249 assert buffer != null;
250 boolean wasAdded = false;
251 try {
252 checkComponentIndex(cIndex);
253
254 int readableBytes = buffer.readableBytes();
255
256
257 @SuppressWarnings("deprecation")
258 Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice());
259 if (cIndex == components.size()) {
260 wasAdded = components.add(c);
261 if (cIndex == 0) {
262 c.endOffset = readableBytes;
263 } else {
264 Component prev = components.get(cIndex - 1);
265 c.offset = prev.endOffset;
266 c.endOffset = c.offset + readableBytes;
267 }
268 } else {
269 components.add(cIndex, c);
270 wasAdded = true;
271 if (readableBytes != 0) {
272 updateComponentOffsets(cIndex);
273 }
274 }
275 if (increaseWriterIndex) {
276 writerIndex(writerIndex() + buffer.readableBytes());
277 }
278 return cIndex;
279 } finally {
280 if (!wasAdded) {
281 buffer.release();
282 }
283 }
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300 public CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers) {
301 addComponents0(false, cIndex, buffers, 0, buffers.length);
302 consolidateIfNeeded();
303 return this;
304 }
305
306 private int addComponents0(boolean increaseWriterIndex, int cIndex, ByteBuf[] buffers, int offset, int len) {
307 checkNotNull(buffers, "buffers");
308 int i = offset;
309 try {
310 checkComponentIndex(cIndex);
311
312
313 while (i < len) {
314
315
316 ByteBuf b = buffers[i++];
317 if (b == null) {
318 break;
319 }
320 cIndex = addComponent0(increaseWriterIndex, cIndex, b) + 1;
321 int size = components.size();
322 if (cIndex > size) {
323 cIndex = size;
324 }
325 }
326 return cIndex;
327 } finally {
328 for (; i < len; ++i) {
329 ByteBuf b = buffers[i];
330 if (b != null) {
331 try {
332 b.release();
333 } catch (Throwable ignored) {
334
335 }
336 }
337 }
338 }
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 public CompositeByteBuf addComponents(int cIndex, Iterable<ByteBuf> buffers) {
355 addComponents0(false, cIndex, buffers);
356 consolidateIfNeeded();
357 return this;
358 }
359
360 private int addComponents0(boolean increaseIndex, int cIndex, Iterable<ByteBuf> buffers) {
361 if (buffers instanceof ByteBuf) {
362
363 return addComponent0(increaseIndex, cIndex, (ByteBuf) buffers);
364 }
365 checkNotNull(buffers, "buffers");
366
367 if (!(buffers instanceof Collection)) {
368 List<ByteBuf> list = new ArrayList<ByteBuf>();
369 try {
370 for (ByteBuf b: buffers) {
371 list.add(b);
372 }
373 buffers = list;
374 } finally {
375 if (buffers != list) {
376 for (ByteBuf b: buffers) {
377 if (b != null) {
378 try {
379 b.release();
380 } catch (Throwable ignored) {
381
382 }
383 }
384 }
385 }
386 }
387 }
388
389 Collection<ByteBuf> col = (Collection<ByteBuf>) buffers;
390 return addComponents0(increaseIndex, cIndex, col.toArray(new ByteBuf[col.size()]), 0 , col.size());
391 }
392
393
394
395
396
397 private void consolidateIfNeeded() {
398
399
400 final int numComponents = components.size();
401 if (numComponents > maxNumComponents) {
402 final int capacity = components.get(numComponents - 1).endOffset;
403
404 ByteBuf consolidated = allocBuffer(capacity);
405
406
407 for (int i = 0; i < numComponents; i ++) {
408 Component c = components.get(i);
409 ByteBuf b = c.buf;
410 consolidated.writeBytes(b);
411 c.freeIfNecessary();
412 }
413 Component c = new Component(consolidated);
414 c.endOffset = c.length;
415 components.clear();
416 components.add(c);
417 }
418 }
419
420 private void checkComponentIndex(int cIndex) {
421 ensureAccessible();
422 if (cIndex < 0 || cIndex > components.size()) {
423 throw new IndexOutOfBoundsException(String.format(
424 "cIndex: %d (expected: >= 0 && <= numComponents(%d))",
425 cIndex, components.size()));
426 }
427 }
428
429 private void checkComponentIndex(int cIndex, int numComponents) {
430 ensureAccessible();
431 if (cIndex < 0 || cIndex + numComponents > components.size()) {
432 throw new IndexOutOfBoundsException(String.format(
433 "cIndex: %d, numComponents: %d " +
434 "(expected: cIndex >= 0 && cIndex + numComponents <= totalNumComponents(%d))",
435 cIndex, numComponents, components.size()));
436 }
437 }
438
439 private void updateComponentOffsets(int cIndex) {
440 int size = components.size();
441 if (size <= cIndex) {
442 return;
443 }
444
445 Component c = components.get(cIndex);
446 if (cIndex == 0) {
447 c.offset = 0;
448 c.endOffset = c.length;
449 cIndex ++;
450 }
451
452 for (int i = cIndex; i < size; i ++) {
453 Component prev = components.get(i - 1);
454 Component cur = components.get(i);
455 cur.offset = prev.endOffset;
456 cur.endOffset = cur.offset + cur.length;
457 }
458 }
459
460
461
462
463
464
465 public CompositeByteBuf removeComponent(int cIndex) {
466 checkComponentIndex(cIndex);
467 Component comp = components.remove(cIndex);
468 comp.freeIfNecessary();
469 if (comp.length > 0) {
470
471 updateComponentOffsets(cIndex);
472 }
473 return this;
474 }
475
476
477
478
479
480
481
482 public CompositeByteBuf removeComponents(int cIndex, int numComponents) {
483 checkComponentIndex(cIndex, numComponents);
484
485 if (numComponents == 0) {
486 return this;
487 }
488 int endIndex = cIndex + numComponents;
489 boolean needsUpdate = false;
490 for (int i = cIndex; i < endIndex; ++i) {
491 Component c = components.get(i);
492 if (c.length > 0) {
493 needsUpdate = true;
494 }
495 c.freeIfNecessary();
496 }
497 components.removeRange(cIndex, endIndex);
498
499 if (needsUpdate) {
500
501 updateComponentOffsets(cIndex);
502 }
503 return this;
504 }
505
506 @Override
507 public Iterator<ByteBuf> iterator() {
508 ensureAccessible();
509 if (components.isEmpty()) {
510 return EMPTY_ITERATOR;
511 }
512 return new CompositeByteBufIterator();
513 }
514
515
516
517
518 public List<ByteBuf> decompose(int offset, int length) {
519 checkIndex(offset, length);
520 if (length == 0) {
521 return Collections.emptyList();
522 }
523
524 int componentId = toComponentIndex(offset);
525 List<ByteBuf> slice = new ArrayList<ByteBuf>(components.size());
526
527
528 Component firstC = components.get(componentId);
529 ByteBuf first = firstC.buf.duplicate();
530 first.readerIndex(offset - firstC.offset);
531
532 ByteBuf buf = first;
533 int bytesToSlice = length;
534 do {
535 int readableBytes = buf.readableBytes();
536 if (bytesToSlice <= readableBytes) {
537
538 buf.writerIndex(buf.readerIndex() + bytesToSlice);
539 slice.add(buf);
540 break;
541 } else {
542
543 slice.add(buf);
544 bytesToSlice -= readableBytes;
545 componentId ++;
546
547
548 buf = components.get(componentId).buf.duplicate();
549 }
550 } while (bytesToSlice > 0);
551
552
553 for (int i = 0; i < slice.size(); i ++) {
554 slice.set(i, slice.get(i).slice());
555 }
556
557 return slice;
558 }
559
560 @Override
561 public boolean isDirect() {
562 int size = components.size();
563 if (size == 0) {
564 return false;
565 }
566 for (int i = 0; i < size; i++) {
567 if (!components.get(i).buf.isDirect()) {
568 return false;
569 }
570 }
571 return true;
572 }
573
574 @Override
575 public boolean hasArray() {
576 switch (components.size()) {
577 case 0:
578 return true;
579 case 1:
580 return components.get(0).buf.hasArray();
581 default:
582 return false;
583 }
584 }
585
586 @Override
587 public byte[] array() {
588 switch (components.size()) {
589 case 0:
590 return EmptyArrays.EMPTY_BYTES;
591 case 1:
592 return components.get(0).buf.array();
593 default:
594 throw new UnsupportedOperationException();
595 }
596 }
597
598 @Override
599 public int arrayOffset() {
600 switch (components.size()) {
601 case 0:
602 return 0;
603 case 1:
604 return components.get(0).buf.arrayOffset();
605 default:
606 throw new UnsupportedOperationException();
607 }
608 }
609
610 @Override
611 public boolean hasMemoryAddress() {
612 switch (components.size()) {
613 case 0:
614 return Unpooled.EMPTY_BUFFER.hasMemoryAddress();
615 case 1:
616 return components.get(0).buf.hasMemoryAddress();
617 default:
618 return false;
619 }
620 }
621
622 @Override
623 public long memoryAddress() {
624 switch (components.size()) {
625 case 0:
626 return Unpooled.EMPTY_BUFFER.memoryAddress();
627 case 1:
628 return components.get(0).buf.memoryAddress();
629 default:
630 throw new UnsupportedOperationException();
631 }
632 }
633
634 @Override
635 public int capacity() {
636 final int numComponents = components.size();
637 if (numComponents == 0) {
638 return 0;
639 }
640 return components.get(numComponents - 1).endOffset;
641 }
642
643 @Override
644 public CompositeByteBuf capacity(int newCapacity) {
645 checkNewCapacity(newCapacity);
646
647 int oldCapacity = capacity();
648 if (newCapacity > oldCapacity) {
649 final int paddingLength = newCapacity - oldCapacity;
650 ByteBuf padding;
651 int nComponents = components.size();
652 if (nComponents < maxNumComponents) {
653 padding = allocBuffer(paddingLength);
654 padding.setIndex(0, paddingLength);
655 addComponent0(false, components.size(), padding);
656 } else {
657 padding = allocBuffer(paddingLength);
658 padding.setIndex(0, paddingLength);
659
660
661 addComponent0(false, components.size(), padding);
662 consolidateIfNeeded();
663 }
664 } else if (newCapacity < oldCapacity) {
665 int bytesToTrim = oldCapacity - newCapacity;
666 for (ListIterator<Component> i = components.listIterator(components.size()); i.hasPrevious();) {
667 Component c = i.previous();
668 if (bytesToTrim >= c.length) {
669 bytesToTrim -= c.length;
670 i.remove();
671 continue;
672 }
673
674
675 Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim));
676 newC.offset = c.offset;
677 newC.endOffset = newC.offset + newC.length;
678 i.set(newC);
679 break;
680 }
681
682 if (readerIndex() > newCapacity) {
683 setIndex(newCapacity, newCapacity);
684 } else if (writerIndex() > newCapacity) {
685 writerIndex(newCapacity);
686 }
687 }
688 return this;
689 }
690
691 @Override
692 public ByteBufAllocator alloc() {
693 return alloc;
694 }
695
696 @Override
697 public ByteOrder order() {
698 return ByteOrder.BIG_ENDIAN;
699 }
700
701
702
703
704 public int numComponents() {
705 return components.size();
706 }
707
708
709
710
711 public int maxNumComponents() {
712 return maxNumComponents;
713 }
714
715
716
717
718 public int toComponentIndex(int offset) {
719 checkIndex(offset);
720
721 for (int low = 0, high = components.size(); low <= high;) {
722 int mid = low + high >>> 1;
723 Component c = components.get(mid);
724 if (offset >= c.endOffset) {
725 low = mid + 1;
726 } else if (offset < c.offset) {
727 high = mid - 1;
728 } else {
729 return mid;
730 }
731 }
732
733 throw new Error("should not reach here");
734 }
735
736 public int toByteIndex(int cIndex) {
737 checkComponentIndex(cIndex);
738 return components.get(cIndex).offset;
739 }
740
741 @Override
742 public byte getByte(int index) {
743 return _getByte(index);
744 }
745
746 @Override
747 protected byte _getByte(int index) {
748 Component c = findComponent(index);
749 return c.buf.getByte(index - c.offset);
750 }
751
752 @Override
753 protected short _getShort(int index) {
754 Component c = findComponent(index);
755 if (index + 2 <= c.endOffset) {
756 return c.buf.getShort(index - c.offset);
757 } else if (order() == ByteOrder.BIG_ENDIAN) {
758 return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff);
759 } else {
760 return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8);
761 }
762 }
763
764 @Override
765 protected int _getUnsignedMedium(int index) {
766 Component c = findComponent(index);
767 if (index + 3 <= c.endOffset) {
768 return c.buf.getUnsignedMedium(index - c.offset);
769 } else if (order() == ByteOrder.BIG_ENDIAN) {
770 return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff;
771 } else {
772 return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16;
773 }
774 }
775
776 @Override
777 protected int _getInt(int index) {
778 Component c = findComponent(index);
779 if (index + 4 <= c.endOffset) {
780 return c.buf.getInt(index - c.offset);
781 } else if (order() == ByteOrder.BIG_ENDIAN) {
782 return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff;
783 } else {
784 return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16;
785 }
786 }
787
788 @Override
789 protected long _getLong(int index) {
790 Component c = findComponent(index);
791 if (index + 8 <= c.endOffset) {
792 return c.buf.getLong(index - c.offset);
793 } else if (order() == ByteOrder.BIG_ENDIAN) {
794 return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL;
795 } else {
796 return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32;
797 }
798 }
799
800 @Override
801 public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
802 checkDstIndex(index, length, dstIndex, dst.length);
803 if (length == 0) {
804 return this;
805 }
806
807 int i = toComponentIndex(index);
808 while (length > 0) {
809 Component c = components.get(i);
810 ByteBuf s = c.buf;
811 int adjustment = c.offset;
812 int localLength = Math.min(length, s.capacity() - (index - adjustment));
813 s.getBytes(index - adjustment, dst, dstIndex, localLength);
814 index += localLength;
815 dstIndex += localLength;
816 length -= localLength;
817 i ++;
818 }
819 return this;
820 }
821
822 @Override
823 public CompositeByteBuf getBytes(int index, ByteBuffer dst) {
824 int limit = dst.limit();
825 int length = dst.remaining();
826
827 checkIndex(index, length);
828 if (length == 0) {
829 return this;
830 }
831
832 int i = toComponentIndex(index);
833 try {
834 while (length > 0) {
835 Component c = components.get(i);
836 ByteBuf s = c.buf;
837 int adjustment = c.offset;
838 int localLength = Math.min(length, s.capacity() - (index - adjustment));
839 dst.limit(dst.position() + localLength);
840 s.getBytes(index - adjustment, dst);
841 index += localLength;
842 length -= localLength;
843 i ++;
844 }
845 } finally {
846 dst.limit(limit);
847 }
848 return this;
849 }
850
851 @Override
852 public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
853 checkDstIndex(index, length, dstIndex, dst.capacity());
854 if (length == 0) {
855 return this;
856 }
857
858 int i = toComponentIndex(index);
859 while (length > 0) {
860 Component c = components.get(i);
861 ByteBuf s = c.buf;
862 int adjustment = c.offset;
863 int localLength = Math.min(length, s.capacity() - (index - adjustment));
864 s.getBytes(index - adjustment, dst, dstIndex, localLength);
865 index += localLength;
866 dstIndex += localLength;
867 length -= localLength;
868 i ++;
869 }
870 return this;
871 }
872
873 @Override
874 public int getBytes(int index, GatheringByteChannel out, int length)
875 throws IOException {
876 int count = nioBufferCount();
877 if (count == 1) {
878 return out.write(internalNioBuffer(index, length));
879 } else {
880 long writtenBytes = out.write(nioBuffers(index, length));
881 if (writtenBytes > Integer.MAX_VALUE) {
882 return Integer.MAX_VALUE;
883 } else {
884 return (int) writtenBytes;
885 }
886 }
887 }
888
889 @Override
890 public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
891 checkIndex(index, length);
892 if (length == 0) {
893 return this;
894 }
895
896 int i = toComponentIndex(index);
897 while (length > 0) {
898 Component c = components.get(i);
899 ByteBuf s = c.buf;
900 int adjustment = c.offset;
901 int localLength = Math.min(length, s.capacity() - (index - adjustment));
902 s.getBytes(index - adjustment, out, localLength);
903 index += localLength;
904 length -= localLength;
905 i ++;
906 }
907 return this;
908 }
909
910 @Override
911 public CompositeByteBuf setByte(int index, int value) {
912 Component c = findComponent(index);
913 c.buf.setByte(index - c.offset, value);
914 return this;
915 }
916
917 @Override
918 protected void _setByte(int index, int value) {
919 setByte(index, value);
920 }
921
922 @Override
923 public CompositeByteBuf setShort(int index, int value) {
924 return (CompositeByteBuf) super.setShort(index, value);
925 }
926
927 @Override
928 protected void _setShort(int index, int value) {
929 Component c = findComponent(index);
930 if (index + 2 <= c.endOffset) {
931 c.buf.setShort(index - c.offset, value);
932 } else if (order() == ByteOrder.BIG_ENDIAN) {
933 _setByte(index, (byte) (value >>> 8));
934 _setByte(index + 1, (byte) value);
935 } else {
936 _setByte(index, (byte) value);
937 _setByte(index + 1, (byte) (value >>> 8));
938 }
939 }
940
941 @Override
942 public CompositeByteBuf setMedium(int index, int value) {
943 return (CompositeByteBuf) super.setMedium(index, value);
944 }
945
946 @Override
947 protected void _setMedium(int index, int value) {
948 Component c = findComponent(index);
949 if (index + 3 <= c.endOffset) {
950 c.buf.setMedium(index - c.offset, value);
951 } else if (order() == ByteOrder.BIG_ENDIAN) {
952 _setShort(index, (short) (value >> 8));
953 _setByte(index + 2, (byte) value);
954 } else {
955 _setShort(index, (short) value);
956 _setByte(index + 2, (byte) (value >>> 16));
957 }
958 }
959
960 @Override
961 public CompositeByteBuf setInt(int index, int value) {
962 return (CompositeByteBuf) super.setInt(index, value);
963 }
964
965 @Override
966 protected void _setInt(int index, int value) {
967 Component c = findComponent(index);
968 if (index + 4 <= c.endOffset) {
969 c.buf.setInt(index - c.offset, value);
970 } else if (order() == ByteOrder.BIG_ENDIAN) {
971 _setShort(index, (short) (value >>> 16));
972 _setShort(index + 2, (short) value);
973 } else {
974 _setShort(index, (short) value);
975 _setShort(index + 2, (short) (value >>> 16));
976 }
977 }
978
979 @Override
980 public CompositeByteBuf setLong(int index, long value) {
981 return (CompositeByteBuf) super.setLong(index, value);
982 }
983
984 @Override
985 protected void _setLong(int index, long value) {
986 Component c = findComponent(index);
987 if (index + 8 <= c.endOffset) {
988 c.buf.setLong(index - c.offset, value);
989 } else if (order() == ByteOrder.BIG_ENDIAN) {
990 _setInt(index, (int) (value >>> 32));
991 _setInt(index + 4, (int) value);
992 } else {
993 _setInt(index, (int) value);
994 _setInt(index + 4, (int) (value >>> 32));
995 }
996 }
997
998 @Override
999 public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
1000 checkSrcIndex(index, length, srcIndex, src.length);
1001 if (length == 0) {
1002 return this;
1003 }
1004
1005 int i = toComponentIndex(index);
1006 while (length > 0) {
1007 Component c = components.get(i);
1008 ByteBuf s = c.buf;
1009 int adjustment = c.offset;
1010 int localLength = Math.min(length, s.capacity() - (index - adjustment));
1011 s.setBytes(index - adjustment, src, srcIndex, localLength);
1012 index += localLength;
1013 srcIndex += localLength;
1014 length -= localLength;
1015 i ++;
1016 }
1017 return this;
1018 }
1019
1020 @Override
1021 public CompositeByteBuf setBytes(int index, ByteBuffer src) {
1022 int limit = src.limit();
1023 int length = src.remaining();
1024
1025 checkIndex(index, length);
1026 if (length == 0) {
1027 return this;
1028 }
1029
1030 int i = toComponentIndex(index);
1031 try {
1032 while (length > 0) {
1033 Component c = components.get(i);
1034 ByteBuf s = c.buf;
1035 int adjustment = c.offset;
1036 int localLength = Math.min(length, s.capacity() - (index - adjustment));
1037 src.limit(src.position() + localLength);
1038 s.setBytes(index - adjustment, src);
1039 index += localLength;
1040 length -= localLength;
1041 i ++;
1042 }
1043 } finally {
1044 src.limit(limit);
1045 }
1046 return this;
1047 }
1048
1049 @Override
1050 public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
1051 checkSrcIndex(index, length, srcIndex, src.capacity());
1052 if (length == 0) {
1053 return this;
1054 }
1055
1056 int i = toComponentIndex(index);
1057 while (length > 0) {
1058 Component c = components.get(i);
1059 ByteBuf s = c.buf;
1060 int adjustment = c.offset;
1061 int localLength = Math.min(length, s.capacity() - (index - adjustment));
1062 s.setBytes(index - adjustment, src, srcIndex, localLength);
1063 index += localLength;
1064 srcIndex += localLength;
1065 length -= localLength;
1066 i ++;
1067 }
1068 return this;
1069 }
1070
1071 @Override
1072 public int setBytes(int index, InputStream in, int length) throws IOException {
1073 checkIndex(index, length);
1074 if (length == 0) {
1075 return in.read(EmptyArrays.EMPTY_BYTES);
1076 }
1077
1078 int i = toComponentIndex(index);
1079 int readBytes = 0;
1080
1081 do {
1082 Component c = components.get(i);
1083 ByteBuf s = c.buf;
1084 int adjustment = c.offset;
1085 int localLength = Math.min(length, s.capacity() - (index - adjustment));
1086 int localReadBytes = s.setBytes(index - adjustment, in, localLength);
1087 if (localReadBytes < 0) {
1088 if (readBytes == 0) {
1089 return -1;
1090 } else {
1091 break;
1092 }
1093 }
1094
1095 if (localReadBytes == localLength) {
1096 index += localLength;
1097 length -= localLength;
1098 readBytes += localLength;
1099 i ++;
1100 } else {
1101 index += localReadBytes;
1102 length -= localReadBytes;
1103 readBytes += localReadBytes;
1104 }
1105 } while (length > 0);
1106
1107 return readBytes;
1108 }
1109
1110 @Override
1111 public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
1112 checkIndex(index, length);
1113 if (length == 0) {
1114 return in.read(EMPTY_NIO_BUFFER);
1115 }
1116
1117 int i = toComponentIndex(index);
1118 int readBytes = 0;
1119 do {
1120 Component c = components.get(i);
1121 ByteBuf s = c.buf;
1122 int adjustment = c.offset;
1123 int localLength = Math.min(length, s.capacity() - (index - adjustment));
1124 int localReadBytes = s.setBytes(index - adjustment, in, localLength);
1125
1126 if (localReadBytes == 0) {
1127 break;
1128 }
1129
1130 if (localReadBytes < 0) {
1131 if (readBytes == 0) {
1132 return -1;
1133 } else {
1134 break;
1135 }
1136 }
1137
1138 if (localReadBytes == localLength) {
1139 index += localLength;
1140 length -= localLength;
1141 readBytes += localLength;
1142 i ++;
1143 } else {
1144 index += localReadBytes;
1145 length -= localReadBytes;
1146 readBytes += localReadBytes;
1147 }
1148 } while (length > 0);
1149
1150 return readBytes;
1151 }
1152
1153 @Override
1154 public ByteBuf copy(int index, int length) {
1155 checkIndex(index, length);
1156 ByteBuf dst = allocBuffer(length);
1157 if (length != 0) {
1158 copyTo(index, length, toComponentIndex(index), dst);
1159 }
1160 return dst;
1161 }
1162
1163 private void copyTo(int index, int length, int componentId, ByteBuf dst) {
1164 int dstIndex = 0;
1165 int i = componentId;
1166
1167 while (length > 0) {
1168 Component c = components.get(i);
1169 ByteBuf s = c.buf;
1170 int adjustment = c.offset;
1171 int localLength = Math.min(length, s.capacity() - (index - adjustment));
1172 s.getBytes(index - adjustment, dst, dstIndex, localLength);
1173 index += localLength;
1174 dstIndex += localLength;
1175 length -= localLength;
1176 i ++;
1177 }
1178
1179 dst.writerIndex(dst.capacity());
1180 }
1181
1182
1183
1184
1185
1186
1187
1188 public ByteBuf component(int cIndex) {
1189 return internalComponent(cIndex).duplicate();
1190 }
1191
1192
1193
1194
1195
1196
1197
1198 public ByteBuf componentAtOffset(int offset) {
1199 return internalComponentAtOffset(offset).duplicate();
1200 }
1201
1202
1203
1204
1205
1206
1207
1208 public ByteBuf internalComponent(int cIndex) {
1209 checkComponentIndex(cIndex);
1210 return components.get(cIndex).buf;
1211 }
1212
1213
1214
1215
1216
1217
1218
1219 public ByteBuf internalComponentAtOffset(int offset) {
1220 return findComponent(offset).buf;
1221 }
1222
1223 private Component findComponent(int offset) {
1224 checkIndex(offset);
1225
1226 for (int low = 0, high = components.size(); low <= high;) {
1227 int mid = low + high >>> 1;
1228 Component c = components.get(mid);
1229 if (offset >= c.endOffset) {
1230 low = mid + 1;
1231 } else if (offset < c.offset) {
1232 high = mid - 1;
1233 } else {
1234 assert c.length != 0;
1235 return c;
1236 }
1237 }
1238
1239 throw new Error("should not reach here");
1240 }
1241
1242 @Override
1243 public int nioBufferCount() {
1244 switch (components.size()) {
1245 case 0:
1246 return 1;
1247 case 1:
1248 return components.get(0).buf.nioBufferCount();
1249 default:
1250 int count = 0;
1251 int componentsCount = components.size();
1252 for (int i = 0; i < componentsCount; i++) {
1253 Component c = components.get(i);
1254 count += c.buf.nioBufferCount();
1255 }
1256 return count;
1257 }
1258 }
1259
1260 @Override
1261 public ByteBuffer internalNioBuffer(int index, int length) {
1262 switch (components.size()) {
1263 case 0:
1264 return EMPTY_NIO_BUFFER;
1265 case 1:
1266 return components.get(0).buf.internalNioBuffer(index, length);
1267 default:
1268 throw new UnsupportedOperationException();
1269 }
1270 }
1271
1272 @Override
1273 public ByteBuffer nioBuffer(int index, int length) {
1274 checkIndex(index, length);
1275
1276 switch (components.size()) {
1277 case 0:
1278 return EMPTY_NIO_BUFFER;
1279 case 1:
1280 ByteBuf buf = components.get(0).buf;
1281 if (buf.nioBufferCount() == 1) {
1282 return components.get(0).buf.nioBuffer(index, length);
1283 }
1284 }
1285
1286 ByteBuffer merged = ByteBuffer.allocate(length).order(order());
1287 ByteBuffer[] buffers = nioBuffers(index, length);
1288
1289 for (ByteBuffer buf: buffers) {
1290 merged.put(buf);
1291 }
1292
1293 merged.flip();
1294 return merged;
1295 }
1296
1297 @Override
1298 public ByteBuffer[] nioBuffers(int index, int length) {
1299 checkIndex(index, length);
1300 if (length == 0) {
1301 return new ByteBuffer[] { EMPTY_NIO_BUFFER };
1302 }
1303
1304 List<ByteBuffer> buffers = new ArrayList<ByteBuffer>(components.size());
1305 int i = toComponentIndex(index);
1306 while (length > 0) {
1307 Component c = components.get(i);
1308 ByteBuf s = c.buf;
1309 int adjustment = c.offset;
1310 int localLength = Math.min(length, s.capacity() - (index - adjustment));
1311 switch (s.nioBufferCount()) {
1312 case 0:
1313 throw new UnsupportedOperationException();
1314 case 1:
1315 buffers.add(s.nioBuffer(index - adjustment, localLength));
1316 break;
1317 default:
1318 Collections.addAll(buffers, s.nioBuffers(index - adjustment, localLength));
1319 }
1320
1321 index += localLength;
1322 length -= localLength;
1323 i ++;
1324 }
1325
1326 return buffers.toArray(new ByteBuffer[buffers.size()]);
1327 }
1328
1329
1330
1331
1332 public CompositeByteBuf consolidate() {
1333 ensureAccessible();
1334 final int numComponents = numComponents();
1335 if (numComponents <= 1) {
1336 return this;
1337 }
1338
1339 final Component last = components.get(numComponents - 1);
1340 final int capacity = last.endOffset;
1341 final ByteBuf consolidated = allocBuffer(capacity);
1342
1343 for (int i = 0; i < numComponents; i ++) {
1344 Component c = components.get(i);
1345 ByteBuf b = c.buf;
1346 consolidated.writeBytes(b);
1347 c.freeIfNecessary();
1348 }
1349
1350 components.clear();
1351 components.add(new Component(consolidated));
1352 updateComponentOffsets(0);
1353 return this;
1354 }
1355
1356
1357
1358
1359
1360
1361
1362 public CompositeByteBuf consolidate(int cIndex, int numComponents) {
1363 checkComponentIndex(cIndex, numComponents);
1364 if (numComponents <= 1) {
1365 return this;
1366 }
1367
1368 final int endCIndex = cIndex + numComponents;
1369 final Component last = components.get(endCIndex - 1);
1370 final int capacity = last.endOffset - components.get(cIndex).offset;
1371 final ByteBuf consolidated = allocBuffer(capacity);
1372
1373 for (int i = cIndex; i < endCIndex; i ++) {
1374 Component c = components.get(i);
1375 ByteBuf b = c.buf;
1376 consolidated.writeBytes(b);
1377 c.freeIfNecessary();
1378 }
1379
1380 components.removeRange(cIndex + 1, endCIndex);
1381 components.set(cIndex, new Component(consolidated));
1382 updateComponentOffsets(cIndex);
1383 return this;
1384 }
1385
1386
1387
1388
1389 public CompositeByteBuf discardReadComponents() {
1390 ensureAccessible();
1391 final int readerIndex = readerIndex();
1392 if (readerIndex == 0) {
1393 return this;
1394 }
1395
1396
1397 int writerIndex = writerIndex();
1398 if (readerIndex == writerIndex && writerIndex == capacity()) {
1399 int size = components.size();
1400 for (int i = 0; i < size; i++) {
1401 components.get(i).freeIfNecessary();
1402 }
1403 components.clear();
1404 setIndex(0, 0);
1405 adjustMarkers(readerIndex);
1406 return this;
1407 }
1408
1409
1410 int firstComponentId = toComponentIndex(readerIndex);
1411 for (int i = 0; i < firstComponentId; i ++) {
1412 components.get(i).freeIfNecessary();
1413 }
1414 components.removeRange(0, firstComponentId);
1415
1416
1417 Component first = components.get(0);
1418 int offset = first.offset;
1419 updateComponentOffsets(0);
1420 setIndex(readerIndex - offset, writerIndex - offset);
1421 adjustMarkers(offset);
1422 return this;
1423 }
1424
1425 @Override
1426 public CompositeByteBuf discardReadBytes() {
1427 ensureAccessible();
1428 final int readerIndex = readerIndex();
1429 if (readerIndex == 0) {
1430 return this;
1431 }
1432
1433
1434 int writerIndex = writerIndex();
1435 if (readerIndex == writerIndex && writerIndex == capacity()) {
1436 int size = components.size();
1437 for (int i = 0; i < size; i++) {
1438 components.get(i).freeIfNecessary();
1439 }
1440 components.clear();
1441 setIndex(0, 0);
1442 adjustMarkers(readerIndex);
1443 return this;
1444 }
1445
1446
1447 int firstComponentId = toComponentIndex(readerIndex);
1448 for (int i = 0; i < firstComponentId; i ++) {
1449 components.get(i).freeIfNecessary();
1450 }
1451
1452
1453 Component c = components.get(firstComponentId);
1454 int adjustment = readerIndex - c.offset;
1455 if (adjustment == c.length) {
1456
1457 firstComponentId++;
1458 } else {
1459 Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment));
1460 components.set(firstComponentId, newC);
1461 }
1462
1463 components.removeRange(0, firstComponentId);
1464
1465
1466 updateComponentOffsets(0);
1467 setIndex(0, writerIndex - readerIndex);
1468 adjustMarkers(readerIndex);
1469 return this;
1470 }
1471
1472 private ByteBuf allocBuffer(int capacity) {
1473 return direct ? alloc().directBuffer(capacity) : alloc().heapBuffer(capacity);
1474 }
1475
1476 @Override
1477 public String toString() {
1478 String result = super.toString();
1479 result = result.substring(0, result.length() - 1);
1480 return result + ", components=" + components.size() + ')';
1481 }
1482
1483 private static final class Component {
1484 final ByteBuf buf;
1485 final int length;
1486 int offset;
1487 int endOffset;
1488
1489 Component(ByteBuf buf) {
1490 this.buf = buf;
1491 length = buf.readableBytes();
1492 }
1493
1494 void freeIfNecessary() {
1495 buf.release();
1496 }
1497 }
1498
1499 @Override
1500 public CompositeByteBuf readerIndex(int readerIndex) {
1501 return (CompositeByteBuf) super.readerIndex(readerIndex);
1502 }
1503
1504 @Override
1505 public CompositeByteBuf writerIndex(int writerIndex) {
1506 return (CompositeByteBuf) super.writerIndex(writerIndex);
1507 }
1508
1509 @Override
1510 public CompositeByteBuf setIndex(int readerIndex, int writerIndex) {
1511 return (CompositeByteBuf) super.setIndex(readerIndex, writerIndex);
1512 }
1513
1514 @Override
1515 public CompositeByteBuf clear() {
1516 return (CompositeByteBuf) super.clear();
1517 }
1518
1519 @Override
1520 public CompositeByteBuf markReaderIndex() {
1521 return (CompositeByteBuf) super.markReaderIndex();
1522 }
1523
1524 @Override
1525 public CompositeByteBuf resetReaderIndex() {
1526 return (CompositeByteBuf) super.resetReaderIndex();
1527 }
1528
1529 @Override
1530 public CompositeByteBuf markWriterIndex() {
1531 return (CompositeByteBuf) super.markWriterIndex();
1532 }
1533
1534 @Override
1535 public CompositeByteBuf resetWriterIndex() {
1536 return (CompositeByteBuf) super.resetWriterIndex();
1537 }
1538
1539 @Override
1540 public CompositeByteBuf ensureWritable(int minWritableBytes) {
1541 return (CompositeByteBuf) super.ensureWritable(minWritableBytes);
1542 }
1543
1544 @Override
1545 public CompositeByteBuf getBytes(int index, ByteBuf dst) {
1546 return (CompositeByteBuf) super.getBytes(index, dst);
1547 }
1548
1549 @Override
1550 public CompositeByteBuf getBytes(int index, ByteBuf dst, int length) {
1551 return (CompositeByteBuf) super.getBytes(index, dst, length);
1552 }
1553
1554 @Override
1555 public CompositeByteBuf getBytes(int index, byte[] dst) {
1556 return (CompositeByteBuf) super.getBytes(index, dst);
1557 }
1558
1559 @Override
1560 public CompositeByteBuf setBoolean(int index, boolean value) {
1561 return (CompositeByteBuf) super.setBoolean(index, value);
1562 }
1563
1564 @Override
1565 public CompositeByteBuf setChar(int index, int value) {
1566 return (CompositeByteBuf) super.setChar(index, value);
1567 }
1568
1569 @Override
1570 public CompositeByteBuf setFloat(int index, float value) {
1571 return (CompositeByteBuf) super.setFloat(index, value);
1572 }
1573
1574 @Override
1575 public CompositeByteBuf setDouble(int index, double value) {
1576 return (CompositeByteBuf) super.setDouble(index, value);
1577 }
1578
1579 @Override
1580 public CompositeByteBuf setBytes(int index, ByteBuf src) {
1581 return (CompositeByteBuf) super.setBytes(index, src);
1582 }
1583
1584 @Override
1585 public CompositeByteBuf setBytes(int index, ByteBuf src, int length) {
1586 return (CompositeByteBuf) super.setBytes(index, src, length);
1587 }
1588
1589 @Override
1590 public CompositeByteBuf setBytes(int index, byte[] src) {
1591 return (CompositeByteBuf) super.setBytes(index, src);
1592 }
1593
1594 @Override
1595 public CompositeByteBuf setZero(int index, int length) {
1596 return (CompositeByteBuf) super.setZero(index, length);
1597 }
1598
1599 @Override
1600 public CompositeByteBuf readBytes(ByteBuf dst) {
1601 return (CompositeByteBuf) super.readBytes(dst);
1602 }
1603
1604 @Override
1605 public CompositeByteBuf readBytes(ByteBuf dst, int length) {
1606 return (CompositeByteBuf) super.readBytes(dst, length);
1607 }
1608
1609 @Override
1610 public CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
1611 return (CompositeByteBuf) super.readBytes(dst, dstIndex, length);
1612 }
1613
1614 @Override
1615 public CompositeByteBuf readBytes(byte[] dst) {
1616 return (CompositeByteBuf) super.readBytes(dst);
1617 }
1618
1619 @Override
1620 public CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) {
1621 return (CompositeByteBuf) super.readBytes(dst, dstIndex, length);
1622 }
1623
1624 @Override
1625 public CompositeByteBuf readBytes(ByteBuffer dst) {
1626 return (CompositeByteBuf) super.readBytes(dst);
1627 }
1628
1629 @Override
1630 public CompositeByteBuf readBytes(OutputStream out, int length) throws IOException {
1631 return (CompositeByteBuf) super.readBytes(out, length);
1632 }
1633
1634 @Override
1635 public CompositeByteBuf skipBytes(int length) {
1636 return (CompositeByteBuf) super.skipBytes(length);
1637 }
1638
1639 @Override
1640 public CompositeByteBuf writeBoolean(boolean value) {
1641 return (CompositeByteBuf) super.writeBoolean(value);
1642 }
1643
1644 @Override
1645 public CompositeByteBuf writeByte(int value) {
1646 return (CompositeByteBuf) super.writeByte(value);
1647 }
1648
1649 @Override
1650 public CompositeByteBuf writeShort(int value) {
1651 return (CompositeByteBuf) super.writeShort(value);
1652 }
1653
1654 @Override
1655 public CompositeByteBuf writeMedium(int value) {
1656 return (CompositeByteBuf) super.writeMedium(value);
1657 }
1658
1659 @Override
1660 public CompositeByteBuf writeInt(int value) {
1661 return (CompositeByteBuf) super.writeInt(value);
1662 }
1663
1664 @Override
1665 public CompositeByteBuf writeLong(long value) {
1666 return (CompositeByteBuf) super.writeLong(value);
1667 }
1668
1669 @Override
1670 public CompositeByteBuf writeChar(int value) {
1671 return (CompositeByteBuf) super.writeChar(value);
1672 }
1673
1674 @Override
1675 public CompositeByteBuf writeFloat(float value) {
1676 return (CompositeByteBuf) super.writeFloat(value);
1677 }
1678
1679 @Override
1680 public CompositeByteBuf writeDouble(double value) {
1681 return (CompositeByteBuf) super.writeDouble(value);
1682 }
1683
1684 @Override
1685 public CompositeByteBuf writeBytes(ByteBuf src) {
1686 return (CompositeByteBuf) super.writeBytes(src);
1687 }
1688
1689 @Override
1690 public CompositeByteBuf writeBytes(ByteBuf src, int length) {
1691 return (CompositeByteBuf) super.writeBytes(src, length);
1692 }
1693
1694 @Override
1695 public CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
1696 return (CompositeByteBuf) super.writeBytes(src, srcIndex, length);
1697 }
1698
1699 @Override
1700 public CompositeByteBuf writeBytes(byte[] src) {
1701 return (CompositeByteBuf) super.writeBytes(src);
1702 }
1703
1704 @Override
1705 public CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) {
1706 return (CompositeByteBuf) super.writeBytes(src, srcIndex, length);
1707 }
1708
1709 @Override
1710 public CompositeByteBuf writeBytes(ByteBuffer src) {
1711 return (CompositeByteBuf) super.writeBytes(src);
1712 }
1713
1714 @Override
1715 public CompositeByteBuf writeZero(int length) {
1716 return (CompositeByteBuf) super.writeZero(length);
1717 }
1718
1719 @Override
1720 public CompositeByteBuf retain(int increment) {
1721 return (CompositeByteBuf) super.retain(increment);
1722 }
1723
1724 @Override
1725 public CompositeByteBuf retain() {
1726 return (CompositeByteBuf) super.retain();
1727 }
1728
1729 @Override
1730 public ByteBuffer[] nioBuffers() {
1731 return nioBuffers(readerIndex(), readableBytes());
1732 }
1733
1734 @Override
1735 public CompositeByteBuf discardSomeReadBytes() {
1736 return discardReadComponents();
1737 }
1738
1739 @Override
1740 protected void deallocate() {
1741 if (freed) {
1742 return;
1743 }
1744
1745 freed = true;
1746 int size = components.size();
1747
1748
1749 for (int i = 0; i < size; i++) {
1750 components.get(i).freeIfNecessary();
1751 }
1752 }
1753
1754 @Override
1755 public ByteBuf unwrap() {
1756 return null;
1757 }
1758
1759 private final class CompositeByteBufIterator implements Iterator<ByteBuf> {
1760 private final int size = components.size();
1761 private int index;
1762
1763 @Override
1764 public boolean hasNext() {
1765 return size > index;
1766 }
1767
1768 @Override
1769 public ByteBuf next() {
1770 if (size != components.size()) {
1771 throw new ConcurrentModificationException();
1772 }
1773 if (!hasNext()) {
1774 throw new NoSuchElementException();
1775 }
1776 try {
1777 return components.get(index++).buf;
1778 } catch (IndexOutOfBoundsException e) {
1779 throw new ConcurrentModificationException();
1780 }
1781 }
1782
1783 @Override
1784 public void remove() {
1785 throw new UnsupportedOperationException("Read-Only");
1786 }
1787 }
1788
1789 private static final class ComponentList extends ArrayList<Component> {
1790
1791 ComponentList(int initialCapacity) {
1792 super(initialCapacity);
1793 }
1794
1795
1796 @Override
1797 public void removeRange(int fromIndex, int toIndex) {
1798 super.removeRange(fromIndex, toIndex);
1799 }
1800 }
1801 }