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