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.IllegalReferenceCountException;
19  import io.netty.util.ResourceLeakDetector;
20  import io.netty.util.internal.PlatformDependent;
21  import io.netty.util.internal.StringUtil;
22  
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.nio.ByteBuffer;
27  import java.nio.ByteOrder;
28  import java.nio.channels.GatheringByteChannel;
29  import java.nio.channels.ScatteringByteChannel;
30  import java.nio.charset.Charset;
31  
32  
33  /**
34   * A skeletal implementation of a buffer.
35   */
36  public abstract class AbstractByteBuf extends ByteBuf {
37  
38      static final ResourceLeakDetector<ByteBuf> leakDetector = new ResourceLeakDetector<ByteBuf>(ByteBuf.class);
39  
40      int readerIndex;
41      int writerIndex;
42      private int markedReaderIndex;
43      private int markedWriterIndex;
44  
45      private int maxCapacity;
46  
47      private SwappedByteBuf swappedBuf;
48  
49      protected AbstractByteBuf(int maxCapacity) {
50          if (maxCapacity < 0) {
51              throw new IllegalArgumentException("maxCapacity: " + maxCapacity + " (expected: >= 0)");
52          }
53          this.maxCapacity = maxCapacity;
54      }
55  
56      @Override
57      public int maxCapacity() {
58          return maxCapacity;
59      }
60  
61      protected final void maxCapacity(int maxCapacity) {
62          this.maxCapacity = maxCapacity;
63      }
64  
65      @Override
66      public int readerIndex() {
67          return readerIndex;
68      }
69  
70      @Override
71      public ByteBuf readerIndex(int readerIndex) {
72          if (readerIndex < 0 || readerIndex > writerIndex) {
73              throw new IndexOutOfBoundsException(String.format(
74                      "readerIndex: %d (expected: 0 <= readerIndex <= writerIndex(%d))", readerIndex, writerIndex));
75          }
76          this.readerIndex = readerIndex;
77          return this;
78      }
79  
80      @Override
81      public int writerIndex() {
82          return writerIndex;
83      }
84  
85      @Override
86      public ByteBuf writerIndex(int writerIndex) {
87          if (writerIndex < readerIndex || writerIndex > capacity()) {
88              throw new IndexOutOfBoundsException(String.format(
89                      "writerIndex: %d (expected: readerIndex(%d) <= writerIndex <= capacity(%d))",
90                      writerIndex, readerIndex, capacity()));
91          }
92          this.writerIndex = writerIndex;
93          return this;
94      }
95  
96      @Override
97      public ByteBuf setIndex(int readerIndex, int writerIndex) {
98          if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) {
99              throw new IndexOutOfBoundsException(String.format(
100                     "readerIndex: %d, writerIndex: %d (expected: 0 <= readerIndex <= writerIndex <= capacity(%d))",
101                     readerIndex, writerIndex, capacity()));
102         }
103         this.readerIndex = readerIndex;
104         this.writerIndex = writerIndex;
105         return this;
106     }
107 
108     @Override
109     public ByteBuf clear() {
110         readerIndex = writerIndex = 0;
111         return this;
112     }
113 
114     @Override
115     public boolean isReadable() {
116         return writerIndex > readerIndex;
117     }
118 
119     @Override
120     public boolean isReadable(int numBytes) {
121         return writerIndex - readerIndex >= numBytes;
122     }
123 
124     @Override
125     public boolean isWritable() {
126         return capacity() > writerIndex;
127     }
128 
129     @Override
130     public boolean isWritable(int numBytes) {
131         return capacity() - writerIndex >= numBytes;
132     }
133 
134     @Override
135     public int readableBytes() {
136         return writerIndex - readerIndex;
137     }
138 
139     @Override
140     public int writableBytes() {
141         return capacity() - writerIndex;
142     }
143 
144     @Override
145     public int maxWritableBytes() {
146         return maxCapacity() - writerIndex;
147     }
148 
149     @Override
150     public ByteBuf markReaderIndex() {
151         markedReaderIndex = readerIndex;
152         return this;
153     }
154 
155     @Override
156     public ByteBuf resetReaderIndex() {
157         readerIndex(markedReaderIndex);
158         return this;
159     }
160 
161     @Override
162     public ByteBuf markWriterIndex() {
163         markedWriterIndex = writerIndex;
164         return this;
165     }
166 
167     @Override
168     public ByteBuf resetWriterIndex() {
169         writerIndex = markedWriterIndex;
170         return this;
171     }
172 
173     @Override
174     public ByteBuf discardReadBytes() {
175         ensureAccessible();
176         if (readerIndex == 0) {
177             return this;
178         }
179 
180         if (readerIndex != writerIndex) {
181             setBytes(0, this, readerIndex, writerIndex - readerIndex);
182             writerIndex -= readerIndex;
183             adjustMarkers(readerIndex);
184             readerIndex = 0;
185         } else {
186             adjustMarkers(readerIndex);
187             writerIndex = readerIndex = 0;
188         }
189         return this;
190     }
191 
192     @Override
193     public ByteBuf discardSomeReadBytes() {
194         ensureAccessible();
195         if (readerIndex == 0) {
196             return this;
197         }
198 
199         if (readerIndex == writerIndex) {
200             adjustMarkers(readerIndex);
201             writerIndex = readerIndex = 0;
202             return this;
203         }
204 
205         if (readerIndex >= capacity() >>> 1) {
206             setBytes(0, this, readerIndex, writerIndex - readerIndex);
207             writerIndex -= readerIndex;
208             adjustMarkers(readerIndex);
209             readerIndex = 0;
210         }
211         return this;
212     }
213 
214     protected final void adjustMarkers(int decrement) {
215         int markedReaderIndex = this.markedReaderIndex;
216         if (markedReaderIndex <= decrement) {
217             this.markedReaderIndex = 0;
218             int markedWriterIndex = this.markedWriterIndex;
219             if (markedWriterIndex <= decrement) {
220                 this.markedWriterIndex = 0;
221             } else {
222                 this.markedWriterIndex = markedWriterIndex - decrement;
223             }
224         } else {
225             this.markedReaderIndex = markedReaderIndex - decrement;
226             markedWriterIndex -= decrement;
227         }
228     }
229 
230     @Override
231     public ByteBuf ensureWritable(int minWritableBytes) {
232         if (minWritableBytes < 0) {
233             throw new IllegalArgumentException(String.format(
234                     "minWritableBytes: %d (expected: >= 0)", minWritableBytes));
235         }
236 
237         if (minWritableBytes <= writableBytes()) {
238             return this;
239         }
240 
241         if (minWritableBytes > maxCapacity - writerIndex) {
242             throw new IndexOutOfBoundsException(String.format(
243                     "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
244                     writerIndex, minWritableBytes, maxCapacity, this));
245         }
246 
247         // Normalize the current capacity to the power of 2.
248         int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);
249 
250         // Adjust to the new capacity.
251         capacity(newCapacity);
252         return this;
253     }
254 
255     @Override
256     public int ensureWritable(int minWritableBytes, boolean force) {
257         if (minWritableBytes < 0) {
258             throw new IllegalArgumentException(String.format(
259                     "minWritableBytes: %d (expected: >= 0)", minWritableBytes));
260         }
261 
262         if (minWritableBytes <= writableBytes()) {
263             return 0;
264         }
265 
266         if (minWritableBytes > maxCapacity - writerIndex) {
267             if (force) {
268                 if (capacity() == maxCapacity()) {
269                     return 1;
270                 }
271 
272                 capacity(maxCapacity());
273                 return 3;
274             }
275         }
276 
277         // Normalize the current capacity to the power of 2.
278         int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);
279 
280         // Adjust to the new capacity.
281         capacity(newCapacity);
282         return 2;
283     }
284 
285     @Override
286     public ByteBuf order(ByteOrder endianness) {
287         if (endianness == null) {
288             throw new NullPointerException("endianness");
289         }
290         if (endianness == order()) {
291             return this;
292         }
293 
294         SwappedByteBuf swappedBuf = this.swappedBuf;
295         if (swappedBuf == null) {
296             this.swappedBuf = swappedBuf = newSwappedByteBuf();
297         }
298         return swappedBuf;
299     }
300 
301     /**
302      * Creates a new {@link SwappedByteBuf} for this {@link ByteBuf} instance.
303      */
304     protected SwappedByteBuf newSwappedByteBuf() {
305         return new SwappedByteBuf(this);
306     }
307 
308     @Override
309     public byte getByte(int index) {
310         checkIndex(index);
311         return _getByte(index);
312     }
313 
314     protected abstract byte _getByte(int index);
315 
316     @Override
317     public boolean getBoolean(int index) {
318         return getByte(index) != 0;
319     }
320 
321     @Override
322     public short getUnsignedByte(int index) {
323         return (short) (getByte(index) & 0xFF);
324     }
325 
326     @Override
327     public short getShort(int index) {
328         checkIndex(index, 2);
329         return _getShort(index);
330     }
331 
332     protected abstract short _getShort(int index);
333 
334     @Override
335     public int getUnsignedShort(int index) {
336         return getShort(index) & 0xFFFF;
337     }
338 
339     @Override
340     public int getUnsignedMedium(int index) {
341         checkIndex(index, 3);
342         return _getUnsignedMedium(index);
343     }
344 
345     protected abstract int _getUnsignedMedium(int index);
346 
347     @Override
348     public int getMedium(int index) {
349         int value = getUnsignedMedium(index);
350         if ((value & 0x800000) != 0) {
351             value |= 0xff000000;
352         }
353         return value;
354     }
355 
356     @Override
357     public int getInt(int index) {
358         checkIndex(index, 4);
359         return _getInt(index);
360     }
361 
362     protected abstract int _getInt(int index);
363 
364     @Override
365     public long getUnsignedInt(int index) {
366         return getInt(index) & 0xFFFFFFFFL;
367     }
368 
369     @Override
370     public long getLong(int index) {
371         checkIndex(index, 8);
372         return _getLong(index);
373     }
374 
375     protected abstract long _getLong(int index);
376 
377     @Override
378     public char getChar(int index) {
379         return (char) getShort(index);
380     }
381 
382     @Override
383     public float getFloat(int index) {
384         return Float.intBitsToFloat(getInt(index));
385     }
386 
387     @Override
388     public double getDouble(int index) {
389         return Double.longBitsToDouble(getLong(index));
390     }
391 
392     @Override
393     public ByteBuf getBytes(int index, byte[] dst) {
394         getBytes(index, dst, 0, dst.length);
395         return this;
396     }
397 
398     @Override
399     public ByteBuf getBytes(int index, ByteBuf dst) {
400         getBytes(index, dst, dst.writableBytes());
401         return this;
402     }
403 
404     @Override
405     public ByteBuf getBytes(int index, ByteBuf dst, int length) {
406         getBytes(index, dst, dst.writerIndex(), length);
407         dst.writerIndex(dst.writerIndex() + length);
408         return this;
409     }
410 
411     @Override
412     public ByteBuf setByte(int index, int value) {
413         checkIndex(index);
414         _setByte(index, value);
415         return this;
416     }
417 
418     protected abstract void _setByte(int index, int value);
419 
420     @Override
421     public ByteBuf setBoolean(int index, boolean value) {
422         setByte(index, value ? 1 : 0);
423         return this;
424     }
425 
426     @Override
427     public ByteBuf setShort(int index, int value) {
428         checkIndex(index, 2);
429         _setShort(index, value);
430         return this;
431     }
432 
433     protected abstract void _setShort(int index, int value);
434 
435     @Override
436     public ByteBuf setChar(int index, int value) {
437         setShort(index, value);
438         return this;
439     }
440 
441     @Override
442     public ByteBuf setMedium(int index, int value) {
443         checkIndex(index, 3);
444         _setMedium(index, value);
445         return this;
446     }
447 
448     protected abstract void _setMedium(int index, int value);
449 
450     @Override
451     public ByteBuf setInt(int index, int value) {
452         checkIndex(index, 4);
453         _setInt(index, value);
454         return this;
455     }
456 
457     protected abstract void _setInt(int index, int value);
458 
459     @Override
460     public ByteBuf setFloat(int index, float value) {
461         setInt(index, Float.floatToRawIntBits(value));
462         return this;
463     }
464 
465     @Override
466     public ByteBuf setLong(int index, long value) {
467         checkIndex(index, 8);
468         _setLong(index, value);
469         return this;
470     }
471 
472     protected abstract void _setLong(int index, long value);
473 
474     @Override
475     public ByteBuf setDouble(int index, double value) {
476         setLong(index, Double.doubleToRawLongBits(value));
477         return this;
478     }
479 
480     @Override
481     public ByteBuf setBytes(int index, byte[] src) {
482         setBytes(index, src, 0, src.length);
483         return this;
484     }
485 
486     @Override
487     public ByteBuf setBytes(int index, ByteBuf src) {
488         setBytes(index, src, src.readableBytes());
489         return this;
490     }
491 
492     @Override
493     public ByteBuf setBytes(int index, ByteBuf src, int length) {
494         checkIndex(index, length);
495         if (src == null) {
496             throw new NullPointerException("src");
497         }
498         if (length > src.readableBytes()) {
499             throw new IndexOutOfBoundsException(String.format(
500                     "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src));
501         }
502 
503         setBytes(index, src, src.readerIndex(), length);
504         src.readerIndex(src.readerIndex() + length);
505         return this;
506     }
507 
508     @Override
509     public ByteBuf setZero(int index, int length) {
510         if (length == 0) {
511             return this;
512         }
513 
514         checkIndex(index, length);
515 
516         int nLong = length >>> 3;
517         int nBytes = length & 7;
518         for (int i = nLong; i > 0; i --) {
519             setLong(index, 0);
520             index += 8;
521         }
522         if (nBytes == 4) {
523             setInt(index, 0);
524         } else if (nBytes < 4) {
525             for (int i = nBytes; i > 0; i --) {
526                 setByte(index, (byte) 0);
527                 index ++;
528             }
529         } else {
530             setInt(index, 0);
531             index += 4;
532             for (int i = nBytes - 4; i > 0; i --) {
533                 setByte(index, (byte) 0);
534                 index ++;
535             }
536         }
537         return this;
538     }
539 
540     @Override
541     public byte readByte() {
542         checkReadableBytes(1);
543         int i = readerIndex;
544         byte b = getByte(i);
545         readerIndex = i + 1;
546         return b;
547     }
548 
549     @Override
550     public boolean readBoolean() {
551         return readByte() != 0;
552     }
553 
554     @Override
555     public short readUnsignedByte() {
556         return (short) (readByte() & 0xFF);
557     }
558 
559     @Override
560     public short readShort() {
561         checkReadableBytes(2);
562         short v = _getShort(readerIndex);
563         readerIndex += 2;
564         return v;
565     }
566 
567     @Override
568     public int readUnsignedShort() {
569         return readShort() & 0xFFFF;
570     }
571 
572     @Override
573     public int readMedium() {
574         int value = readUnsignedMedium();
575         if ((value & 0x800000) != 0) {
576             value |= 0xff000000;
577         }
578         return value;
579     }
580 
581     @Override
582     public int readUnsignedMedium() {
583         checkReadableBytes(3);
584         int v = _getUnsignedMedium(readerIndex);
585         readerIndex += 3;
586         return v;
587     }
588 
589     @Override
590     public int readInt() {
591         checkReadableBytes(4);
592         int v = _getInt(readerIndex);
593         readerIndex += 4;
594         return v;
595     }
596 
597     @Override
598     public long readUnsignedInt() {
599         return readInt() & 0xFFFFFFFFL;
600     }
601 
602     @Override
603     public long readLong() {
604         checkReadableBytes(8);
605         long v = _getLong(readerIndex);
606         readerIndex += 8;
607         return v;
608     }
609 
610     @Override
611     public char readChar() {
612         return (char) readShort();
613     }
614 
615     @Override
616     public float readFloat() {
617         return Float.intBitsToFloat(readInt());
618     }
619 
620     @Override
621     public double readDouble() {
622         return Double.longBitsToDouble(readLong());
623     }
624 
625     @Override
626     public ByteBuf readBytes(int length) {
627         checkReadableBytes(length);
628         if (length == 0) {
629             return Unpooled.EMPTY_BUFFER;
630         }
631 
632         // Use an unpooled heap buffer because there's no way to mandate a user to free the returned buffer.
633         ByteBuf buf = Unpooled.buffer(length, maxCapacity);
634         buf.writeBytes(this, readerIndex, length);
635         readerIndex += length;
636         return buf;
637     }
638 
639     @Override
640     public ByteBuf readSlice(int length) {
641         ByteBuf slice = slice(readerIndex, length);
642         readerIndex += length;
643         return slice;
644     }
645 
646     @Override
647     public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
648         checkReadableBytes(length);
649         getBytes(readerIndex, dst, dstIndex, length);
650         readerIndex += length;
651         return this;
652     }
653 
654     @Override
655     public ByteBuf readBytes(byte[] dst) {
656         readBytes(dst, 0, dst.length);
657         return this;
658     }
659 
660     @Override
661     public ByteBuf readBytes(ByteBuf dst) {
662         readBytes(dst, dst.writableBytes());
663         return this;
664     }
665 
666     @Override
667     public ByteBuf readBytes(ByteBuf dst, int length) {
668         if (length > dst.writableBytes()) {
669             throw new IndexOutOfBoundsException(String.format(
670                     "length(%d) exceeds dst.writableBytes(%d) where dst is: %s", length, dst.writableBytes(), dst));
671         }
672         readBytes(dst, dst.writerIndex(), length);
673         dst.writerIndex(dst.writerIndex() + length);
674         return this;
675     }
676 
677     @Override
678     public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
679         checkReadableBytes(length);
680         getBytes(readerIndex, dst, dstIndex, length);
681         readerIndex += length;
682         return this;
683     }
684 
685     @Override
686     public ByteBuf readBytes(ByteBuffer dst) {
687         int length = dst.remaining();
688         checkReadableBytes(length);
689         getBytes(readerIndex, dst);
690         readerIndex += length;
691         return this;
692     }
693 
694     @Override
695     public int readBytes(GatheringByteChannel out, int length)
696             throws IOException {
697         checkReadableBytes(length);
698         int readBytes = getBytes(readerIndex, out, length);
699         readerIndex += readBytes;
700         return readBytes;
701     }
702 
703     @Override
704     public ByteBuf readBytes(OutputStream out, int length) throws IOException {
705         checkReadableBytes(length);
706         getBytes(readerIndex, out, length);
707         readerIndex += length;
708         return this;
709     }
710 
711     @Override
712     public ByteBuf skipBytes(int length) {
713         checkReadableBytes(length);
714         readerIndex += length;
715         return this;
716     }
717 
718     @Override
719     public ByteBuf writeBoolean(boolean value) {
720         writeByte(value ? 1 : 0);
721         return this;
722     }
723 
724     @Override
725     public ByteBuf writeByte(int value) {
726         ensureAccessible();
727         ensureWritable(1);
728         _setByte(writerIndex++, value);
729         return this;
730     }
731 
732     @Override
733     public ByteBuf writeShort(int value) {
734         ensureAccessible();
735         ensureWritable(2);
736         _setShort(writerIndex, value);
737         writerIndex += 2;
738         return this;
739     }
740 
741     @Override
742     public ByteBuf writeMedium(int value) {
743         ensureAccessible();
744         ensureWritable(3);
745         _setMedium(writerIndex, value);
746         writerIndex += 3;
747         return this;
748     }
749 
750     @Override
751     public ByteBuf writeInt(int value) {
752         ensureAccessible();
753         ensureWritable(4);
754         _setInt(writerIndex, value);
755         writerIndex += 4;
756         return this;
757     }
758 
759     @Override
760     public ByteBuf writeLong(long value) {
761         ensureAccessible();
762         ensureWritable(8);
763         _setLong(writerIndex, value);
764         writerIndex += 8;
765         return this;
766     }
767 
768     @Override
769     public ByteBuf writeChar(int value) {
770         writeShort(value);
771         return this;
772     }
773 
774     @Override
775     public ByteBuf writeFloat(float value) {
776         writeInt(Float.floatToRawIntBits(value));
777         return this;
778     }
779 
780     @Override
781     public ByteBuf writeDouble(double value) {
782         writeLong(Double.doubleToRawLongBits(value));
783         return this;
784     }
785 
786     @Override
787     public ByteBuf writeBytes(byte[] src, int srcIndex, int length) {
788         ensureAccessible();
789         ensureWritable(length);
790         setBytes(writerIndex, src, srcIndex, length);
791         writerIndex += length;
792         return this;
793     }
794 
795     @Override
796     public ByteBuf writeBytes(byte[] src) {
797         writeBytes(src, 0, src.length);
798         return this;
799     }
800 
801     @Override
802     public ByteBuf writeBytes(ByteBuf src) {
803         writeBytes(src, src.readableBytes());
804         return this;
805     }
806 
807     @Override
808     public ByteBuf writeBytes(ByteBuf src, int length) {
809         if (length > src.readableBytes()) {
810             throw new IndexOutOfBoundsException(String.format(
811                     "length(%d) exceeds src.readableBytes(%d) where src is: %s", length, src.readableBytes(), src));
812         }
813         writeBytes(src, src.readerIndex(), length);
814         src.readerIndex(src.readerIndex() + length);
815         return this;
816     }
817 
818     @Override
819     public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
820         ensureAccessible();
821         ensureWritable(length);
822         setBytes(writerIndex, src, srcIndex, length);
823         writerIndex += length;
824         return this;
825     }
826 
827     @Override
828     public ByteBuf writeBytes(ByteBuffer src) {
829         ensureAccessible();
830         int length = src.remaining();
831         ensureWritable(length);
832         setBytes(writerIndex, src);
833         writerIndex += length;
834         return this;
835     }
836 
837     @Override
838     public int writeBytes(InputStream in, int length)
839             throws IOException {
840         ensureAccessible();
841         ensureWritable(length);
842         int writtenBytes = setBytes(writerIndex, in, length);
843         if (writtenBytes > 0) {
844             writerIndex += writtenBytes;
845         }
846         return writtenBytes;
847     }
848 
849     @Override
850     public int writeBytes(ScatteringByteChannel in, int length) throws IOException {
851         ensureAccessible();
852         ensureWritable(length);
853         int writtenBytes = setBytes(writerIndex, in, length);
854         if (writtenBytes > 0) {
855             writerIndex += writtenBytes;
856         }
857         return writtenBytes;
858     }
859 
860     @Override
861     public ByteBuf writeZero(int length) {
862         if (length == 0) {
863             return this;
864         }
865 
866         ensureWritable(length);
867         checkIndex(writerIndex, length);
868 
869         int nLong = length >>> 3;
870         int nBytes = length & 7;
871         for (int i = nLong; i > 0; i --) {
872             writeLong(0);
873         }
874         if (nBytes == 4) {
875             writeInt(0);
876         } else if (nBytes < 4) {
877             for (int i = nBytes; i > 0; i --) {
878                 writeByte((byte) 0);
879             }
880         } else {
881             writeInt(0);
882             for (int i = nBytes - 4; i > 0; i --) {
883                 writeByte((byte) 0);
884             }
885         }
886         return this;
887     }
888 
889     @Override
890     public ByteBuf copy() {
891         return copy(readerIndex, readableBytes());
892     }
893 
894     @Override
895     public ByteBuf duplicate() {
896         return new DuplicatedByteBuf(this);
897     }
898 
899     @Override
900     public ByteBuf slice() {
901         return slice(readerIndex, readableBytes());
902     }
903 
904     @Override
905     public ByteBuf slice(int index, int length) {
906         return new SlicedByteBuf(this, index, length);
907     }
908 
909     @Override
910     public ByteBuffer nioBuffer() {
911         return nioBuffer(readerIndex, readableBytes());
912     }
913 
914     @Override
915     public ByteBuffer[] nioBuffers() {
916         return nioBuffers(readerIndex, readableBytes());
917     }
918 
919     @Override
920     public String toString(Charset charset) {
921         return toString(readerIndex, readableBytes(), charset);
922     }
923 
924     @Override
925     public String toString(int index, int length, Charset charset) {
926         if (length == 0) {
927             return "";
928         }
929 
930         ByteBuffer nioBuffer;
931         if (nioBufferCount() == 1) {
932             nioBuffer = nioBuffer(index, length);
933         } else {
934             nioBuffer = ByteBuffer.allocate(length);
935             getBytes(index, nioBuffer);
936             nioBuffer.flip();
937         }
938 
939         return ByteBufUtil.decodeString(nioBuffer, charset);
940     }
941 
942     @Override
943     public int indexOf(int fromIndex, int toIndex, byte value) {
944         return ByteBufUtil.indexOf(this, fromIndex, toIndex, value);
945     }
946 
947     @Override
948     public int bytesBefore(byte value) {
949         return bytesBefore(readerIndex(), readableBytes(), value);
950     }
951 
952     @Override
953     public int bytesBefore(int length, byte value) {
954         checkReadableBytes(length);
955         return bytesBefore(readerIndex(), length, value);
956     }
957 
958     @Override
959     public int bytesBefore(int index, int length, byte value) {
960         int endIndex = indexOf(index, index + length, value);
961         if (endIndex < 0) {
962             return -1;
963         }
964         return endIndex - index;
965     }
966 
967     @Override
968     public int forEachByte(ByteBufProcessor processor) {
969         int index = readerIndex;
970         int length = writerIndex - index;
971         ensureAccessible();
972         return forEachByteAsc0(index, length, processor);
973     }
974 
975     @Override
976     public int forEachByte(int index, int length, ByteBufProcessor processor) {
977         checkIndex(index, length);
978         return forEachByteAsc0(index, length, processor);
979     }
980 
981     private int forEachByteAsc0(int index, int length, ByteBufProcessor processor) {
982         if (processor == null) {
983             throw new NullPointerException("processor");
984         }
985 
986         if (length == 0) {
987             return -1;
988         }
989 
990         final int endIndex = index + length;
991         int i = index;
992         try {
993             do {
994                 if (processor.process(_getByte(i))) {
995                     i ++;
996                 } else {
997                     return i;
998                 }
999             } while (i < endIndex);
1000         } catch (Exception e) {
1001             PlatformDependent.throwException(e);
1002         }
1003 
1004         return -1;
1005     }
1006 
1007     @Override
1008     public int forEachByteDesc(ByteBufProcessor processor) {
1009         int index = readerIndex;
1010         int length = writerIndex - index;
1011         ensureAccessible();
1012         return forEachByteDesc0(index, length, processor);
1013     }
1014 
1015     @Override
1016     public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
1017         checkIndex(index, length);
1018 
1019         return forEachByteDesc0(index, length, processor);
1020     }
1021 
1022     private int forEachByteDesc0(int index, int length, ByteBufProcessor processor) {
1023 
1024         if (processor == null) {
1025             throw new NullPointerException("processor");
1026         }
1027 
1028         if (length == 0) {
1029             return -1;
1030         }
1031 
1032         int i = index + length - 1;
1033         try {
1034             do {
1035                 if (processor.process(_getByte(i))) {
1036                     i --;
1037                 } else {
1038                     return i;
1039                 }
1040             } while (i >= index);
1041         } catch (Exception e) {
1042             PlatformDependent.throwException(e);
1043         }
1044 
1045         return -1;
1046     }
1047 
1048     @Override
1049     public int hashCode() {
1050         return ByteBufUtil.hashCode(this);
1051     }
1052 
1053     @Override
1054     public boolean equals(Object o) {
1055         if (this == o) {
1056             return true;
1057         }
1058         if (o instanceof ByteBuf) {
1059             return ByteBufUtil.equals(this, (ByteBuf) o);
1060         }
1061         return false;
1062     }
1063 
1064     @Override
1065     public int compareTo(ByteBuf that) {
1066         return ByteBufUtil.compare(this, that);
1067     }
1068 
1069     @Override
1070     public String toString() {
1071         if (refCnt() == 0) {
1072             return StringUtil.simpleClassName(this) + "(freed)";
1073         }
1074 
1075         StringBuilder buf = new StringBuilder()
1076             .append(StringUtil.simpleClassName(this))
1077             .append("(ridx: ").append(readerIndex)
1078             .append(", widx: ").append(writerIndex)
1079             .append(", cap: ").append(capacity());
1080         if (maxCapacity != Integer.MAX_VALUE) {
1081             buf.append('/').append(maxCapacity);
1082         }
1083 
1084         ByteBuf unwrapped = unwrap();
1085         if (unwrapped != null) {
1086             buf.append(", unwrapped: ").append(unwrapped);
1087         }
1088         buf.append(')');
1089         return buf.toString();
1090     }
1091 
1092     protected final void checkIndex(int index) {
1093         ensureAccessible();
1094         if (index < 0 || index >= capacity()) {
1095             throw new IndexOutOfBoundsException(String.format(
1096                     "index: %d (expected: range(0, %d))", index, capacity()));
1097         }
1098     }
1099 
1100     protected final void checkIndex(int index, int fieldLength) {
1101         ensureAccessible();
1102         if (fieldLength < 0) {
1103             throw new IllegalArgumentException("length: " + fieldLength + " (expected: >= 0)");
1104         }
1105         if (index < 0 || index > capacity() - fieldLength) {
1106             throw new IndexOutOfBoundsException(String.format(
1107                     "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity()));
1108         }
1109     }
1110 
1111     protected final void checkSrcIndex(int index, int length, int srcIndex, int srcCapacity) {
1112         checkIndex(index, length);
1113         if (srcIndex < 0 || srcIndex > srcCapacity - length) {
1114             throw new IndexOutOfBoundsException(String.format(
1115                     "srcIndex: %d, length: %d (expected: range(0, %d))", srcIndex, length, srcCapacity));
1116         }
1117     }
1118 
1119     protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) {
1120         checkIndex(index, length);
1121         if (dstIndex < 0 || dstIndex > dstCapacity - length) {
1122             throw new IndexOutOfBoundsException(String.format(
1123                     "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity));
1124         }
1125     }
1126 
1127     /**
1128      * Throws an {@link IndexOutOfBoundsException} if the current
1129      * {@linkplain #readableBytes() readable bytes} of this buffer is less
1130      * than the specified value.
1131      */
1132     protected final void checkReadableBytes(int minimumReadableBytes) {
1133         ensureAccessible();
1134         if (minimumReadableBytes < 0) {
1135             throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)");
1136         }
1137         if (readerIndex > writerIndex - minimumReadableBytes) {
1138             throw new IndexOutOfBoundsException(String.format(
1139                     "readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s",
1140                     readerIndex, minimumReadableBytes, writerIndex, this));
1141         }
1142     }
1143 
1144     /**
1145      * Should be called by every method that tries to access the buffers content to check
1146      * if the buffer was released before.
1147      */
1148     protected final void ensureAccessible() {
1149         if (refCnt() == 0) {
1150             throw new IllegalReferenceCountException(0);
1151         }
1152     }
1153 }