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 org.jboss.netty.buffer;
    17
    18  import java.io.IOException;
    19  import java.io.InputStream;
    20  import java.io.OutputStream;
    21  import java.nio.ByteBuffer;
    22  import java.nio.channels.GatheringByteChannel;
    23  import java.nio.channels.ScatteringByteChannel;
    24  import java.nio.charset.Charset;
    25  import java.util.NoSuchElementException;
    26
    27
    28  /**
    29   * A skeletal implementation of a buffer.
    30   */
    31  public abstract class AbstractChannelBuffer implements ChannelBuffer {
    32
    33      private int readerIndex;
    34      private int writerIndex;
    35      private int markedReaderIndex;
    36      private int markedWriterIndex;
    37
    38      public int readerIndex() {
    39          return readerIndex;
    40      }
    41
    42      public void readerIndex(int readerIndex) {
    43          if (readerIndex < 0 || readerIndex > writerIndex) {
    44              throw new IndexOutOfBoundsException();
    45          }
    46          this.readerIndex = readerIndex;
    47      }
    48
    49      public int writerIndex() {
    50          return writerIndex;
    51      }
    52
    53      public void writerIndex(int writerIndex) {
    54          if (writerIndex < readerIndex || writerIndex > capacity()) {
    55              throw new IndexOutOfBoundsException("Invalid readerIndex: "
    56                      + readerIndex + " - Maximum is " + writerIndex);
    57          }
    58          this.writerIndex = writerIndex;
    59      }
    60
    61      public void setIndex(int readerIndex, int writerIndex) {
    62          if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) {
    63              throw new IndexOutOfBoundsException("Invalid writerIndex: "
    64                      + writerIndex + " - Maximum is " + readerIndex + " or " + capacity());
    65          }
    66          this.readerIndex = readerIndex;
    67          this.writerIndex = writerIndex;
    68      }
    69
    70      public void clear() {
    71          readerIndex = writerIndex = 0;
    72      }
    73
    74      public boolean readable() {
    75          return readableBytes() > 0;
    76      }
    77
    78      public boolean writable() {
    79          return writableBytes() > 0;
    80      }
    81
    82      public int readableBytes() {
    83          return writerIndex - readerIndex;
    84      }
    85
    86      public int writableBytes() {
    87          return capacity() - writerIndex;
    88      }
    89
    90      public void markReaderIndex() {
    91          markedReaderIndex = readerIndex;
    92      }
    93
    94      public void resetReaderIndex() {
    95          readerIndex(markedReaderIndex);
    96      }
    97
    98      public void markWriterIndex() {
    99          markedWriterIndex = writerIndex;
    100     }
    101
    102     public void resetWriterIndex() {
    103         writerIndex = markedWriterIndex;
    104     }
    105
    106     public void discardReadBytes() {
    107         if (readerIndex == 0) {
    108             return;
    109         }
    110         setBytes(0, this, readerIndex, writerIndex - readerIndex);
    111         writerIndex -= readerIndex;
    112         markedReaderIndex = Math.max(markedReaderIndex - readerIndex, 0);
    113         markedWriterIndex = Math.max(markedWriterIndex - readerIndex, 0);
    114         readerIndex = 0;
    115     }
    116
    117     public void ensureWritableBytes(int writableBytes) {
    118         if (writableBytes > writableBytes()) {
    119             throw new IndexOutOfBoundsException("Writable bytes exceeded: Got "
    120                     + writableBytes + ", maximum is " + writableBytes());
    121         }
    122     }
    123
    124     public short getUnsignedByte(int index) {
    125         return (short) (getByte(index) & 0xFF);
    126     }
    127
    128     public int getUnsignedShort(int index) {
    129         return getShort(index) & 0xFFFF;
    130     }
    131
    132     public int getMedium(int index) {
    133         int value = getUnsignedMedium(index);
    134         if ((value & 0x800000) != 0) {
    135             value |= 0xff000000;
    136         }
    137         return value;
    138     }
    139
    140     public long getUnsignedInt(int index) {
    141         return getInt(index) & 0xFFFFFFFFL;
    142     }
    143
    144     public char getChar(int index) {
    145         return (char) getShort(index);
    146     }
    147
    148     public float getFloat(int index) {
    149         return Float.intBitsToFloat(getInt(index));
    150     }
    151
    152     public double getDouble(int index) {
    153         return Double.longBitsToDouble(getLong(index));
    154     }
    155
    156     public void getBytes(int index, byte[] dst) {
    157         getBytes(index, dst, 0, dst.length);
    158     }
    159
    160     public void getBytes(int index, ChannelBuffer dst) {
    161         getBytes(index, dst, dst.writableBytes());
    162     }
    163
    164     public void getBytes(int index, ChannelBuffer dst, int length) {
    165         if (length > dst.writableBytes()) {
    166             throw new IndexOutOfBoundsException("Too many bytes to be read: Need "
    167                     + length + ", maximum is " + dst.writableBytes());
    168         }
    169         getBytes(index, dst, dst.writerIndex(), length);
    170         dst.writerIndex(dst.writerIndex() + length);
    171     }
    172
    173     public void setChar(int index, int value) {
    174         setShort(index, value);
    175     }
    176
    177     public void setFloat(int index, float value) {
    178         setInt(index, Float.floatToRawIntBits(value));
    179     }
    180
    181     public void setDouble(int index, double value) {
    182         setLong(index, Double.doubleToRawLongBits(value));
    183     }
    184
    185     public void setBytes(int index, byte[] src) {
    186         setBytes(index, src, 0, src.length);
    187     }
    188
    189     public void setBytes(int index, ChannelBuffer src) {
    190         setBytes(index, src, src.readableBytes());
    191     }
    192
    193     public void setBytes(int index, ChannelBuffer src, int length) {
    194         if (length > src.readableBytes()) {
    195             throw new IndexOutOfBoundsException("Too many bytes to write: Need "
    196                     + length + ", maximum is " + src.readableBytes());
    197         }
    198         setBytes(index, src, src.readerIndex(), length);
    199         src.readerIndex(src.readerIndex() + length);
    200     }
    201
    202     public void setZero(int index, int length) {
    203         if (length == 0) {
    204             return;
    205         }
    206         if (length < 0) {
    207             throw new IllegalArgumentException(
    208                     "length must be 0 or greater than 0.");
    209         }
    210
    211         int nLong = length >>> 3;
    212         int nBytes = length & 7;
    213         for (int i = nLong; i > 0; i --) {
    214             setLong(index, 0);
    215             index += 8;
    216         }
    217         if (nBytes == 4) {
    218             setInt(index, 0);
    219         } else if (nBytes < 4) {
    220             for (int i = nBytes; i > 0; i --) {
    221                 setByte(index, (byte) 0);
    222                 index ++;
    223             }
    224         } else {
    225             setInt(index, 0);
    226             index += 4;
    227             for (int i = nBytes - 4; i > 0; i --) {
    228                 setByte(index, (byte) 0);
    229                 index ++;
    230             }
    231         }
    232     }
    233
    234     public byte readByte() {
    235         if (readerIndex == writerIndex) {
    236             throw new IndexOutOfBoundsException("Readable byte limit exceeded: "
    237                     + readerIndex);
    238         }
    239         return getByte(readerIndex ++);
    240     }
    241
    242     public short readUnsignedByte() {
    243         return (short) (readByte() & 0xFF);
    244     }
    245
    246     public short readShort() {
    247         checkReadableBytes(2);
    248         short v = getShort(readerIndex);
    249         readerIndex += 2;
    250         return v;
    251     }
    252
    253     public int readUnsignedShort() {
    254         return readShort() & 0xFFFF;
    255     }
    256
    257     public int readMedium() {
    258         int value = readUnsignedMedium();
    259         if ((value & 0x800000) != 0) {
    260             value |= 0xff000000;
    261         }
    262         return value;
    263     }
    264
    265     public int readUnsignedMedium() {
    266         checkReadableBytes(3);
    267         int v = getUnsignedMedium(readerIndex);
    268         readerIndex += 3;
    269         return v;
    270     }
    271
    272     public int readInt() {
    273         checkReadableBytes(4);
    274         int v = getInt(readerIndex);
    275         readerIndex += 4;
    276         return v;
    277     }
    278
    279     public long readUnsignedInt() {
    280         return readInt() & 0xFFFFFFFFL;
    281     }
    282
    283     public long readLong() {
    284         checkReadableBytes(8);
    285         long v = getLong(readerIndex);
    286         readerIndex += 8;
    287         return v;
    288     }
    289
    290     public char readChar() {
    291         return (char) readShort();
    292     }
    293
    294     public float readFloat() {
    295         return Float.intBitsToFloat(readInt());
    296     }
    297
    298     public double readDouble() {
    299         return Double.longBitsToDouble(readLong());
    300     }
    301
    302     public ChannelBuffer readBytes(int length) {
    303         checkReadableBytes(length);
    304         if (length == 0) {
    305             return ChannelBuffers.EMPTY_BUFFER;
    306         }
    307         ChannelBuffer buf = factory().getBuffer(order(), length);
    308         buf.writeBytes(this, readerIndex, length);
    309         readerIndex += length;
    310         return buf;
    311     }
    312
    313     @Deprecated
    314     public ChannelBuffer readBytes(ChannelBufferIndexFinder endIndexFinder) {
    315         int endIndex = indexOf(readerIndex, writerIndex, endIndexFinder);
    316         if (endIndex < 0) {
    317             throw new NoSuchElementException();
    318         }
    319         return readBytes(endIndex - readerIndex);
    320     }
    321
    322     public ChannelBuffer readSlice(int length) {
    323         ChannelBuffer slice = slice(readerIndex, length);
    324         readerIndex += length;
    325         return slice;
    326     }
    327
    328     @Deprecated
    329     public ChannelBuffer readSlice(ChannelBufferIndexFinder endIndexFinder) {
    330         int endIndex = indexOf(readerIndex, writerIndex, endIndexFinder);
    331         if (endIndex < 0) {
    332             throw new NoSuchElementException();
    333         }
    334         return readSlice(endIndex - readerIndex);
    335     }
    336
    337     public void readBytes(byte[] dst, int dstIndex, int length) {
    338         checkReadableBytes(length);
    339         getBytes(readerIndex, dst, dstIndex, length);
    340         readerIndex += length;
    341     }
    342
    343     public void readBytes(byte[] dst) {
    344         readBytes(dst, 0, dst.length);
    345     }
    346
    347     public void readBytes(ChannelBuffer dst) {
    348         readBytes(dst, dst.writableBytes());
    349     }
    350
    351     public void readBytes(ChannelBuffer dst, int length) {
    352         if (length > dst.writableBytes()) {
    353             throw new IndexOutOfBoundsException("Too many bytes to be read: Need "
    354                     + length + ", maximum is " + dst.writableBytes());
    355         }
    356         readBytes(dst, dst.writerIndex(), length);
    357         dst.writerIndex(dst.writerIndex() + length);
    358     }
    359
    360     public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
    361         checkReadableBytes(length);
    362         getBytes(readerIndex, dst, dstIndex, length);
    363         readerIndex += length;
    364     }
    365
    366     public void readBytes(ByteBuffer dst) {
    367         int length = dst.remaining();
    368         checkReadableBytes(length);
    369         getBytes(readerIndex, dst);
    370         readerIndex += length;
    371     }
    372
    373     public int readBytes(GatheringByteChannel out, int length)
    374             throws IOException {
    375         checkReadableBytes(length);
    376         int readBytes = getBytes(readerIndex, out, length);
    377         readerIndex += readBytes;
    378         return readBytes;
    379     }
    380
    381     public void readBytes(OutputStream out, int length) throws IOException {
    382         checkReadableBytes(length);
    383         getBytes(readerIndex, out, length);
    384         readerIndex += length;
    385     }
    386
    387     public void skipBytes(int length) {
    388         int newReaderIndex = readerIndex + length;
    389         if (newReaderIndex > writerIndex) {
    390             throw new IndexOutOfBoundsException("Readable bytes exceeded - Need "
    391                     + newReaderIndex + ", maximum is " + writerIndex);
    392         }
    393         readerIndex = newReaderIndex;
    394     }
    395
    396     @Deprecated
    397     public int skipBytes(ChannelBufferIndexFinder firstIndexFinder) {
    398         int oldReaderIndex = readerIndex;
    399         int newReaderIndex = indexOf(oldReaderIndex, writerIndex, firstIndexFinder);
    400         if (newReaderIndex < 0) {
    401             throw new NoSuchElementException();
    402         }
    403         readerIndex(newReaderIndex);
    404         return newReaderIndex - oldReaderIndex;
    405     }
    406
    407     public void writeByte(int value) {
    408         setByte(writerIndex ++, value);
    409     }
    410
    411     public void writeShort(int value) {
    412         setShort(writerIndex, value);
    413         writerIndex += 2;
    414     }
    415
    416     public void writeMedium(int value) {
    417         setMedium(writerIndex, value);
    418         writerIndex += 3;
    419     }
    420
    421     public void writeInt(int value) {
    422         setInt(writerIndex, value);
    423         writerIndex += 4;
    424     }
    425
    426     public void writeLong(long value) {
    427         setLong(writerIndex, value);
    428         writerIndex += 8;
    429     }
    430
    431     public void writeChar(int value) {
    432         writeShort(value);
    433     }
    434
    435     public void writeFloat(float value) {
    436         writeInt(Float.floatToRawIntBits(value));
    437     }
    438
    439     public void writeDouble(double value) {
    440         writeLong(Double.doubleToRawLongBits(value));
    441     }
    442
    443     public void writeBytes(byte[] src, int srcIndex, int length) {
    444         setBytes(writerIndex, src, srcIndex, length);
    445         writerIndex += length;
    446     }
    447
    448     public void writeBytes(byte[] src) {
    449         writeBytes(src, 0, src.length);
    450     }
    451
    452     public void writeBytes(ChannelBuffer src) {
    453         writeBytes(src, src.readableBytes());
    454     }
    455
    456     public void writeBytes(ChannelBuffer src, int length) {
    457         if (length > src.readableBytes()) {
    458             throw new IndexOutOfBoundsException("Too many bytes to write - Need "
    459                     + length + ", maximum is " + src.readableBytes());
    460         }
    461         writeBytes(src, src.readerIndex(), length);
    462         src.readerIndex(src.readerIndex() + length);
    463     }
    464
    465     public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
    466         setBytes(writerIndex, src, srcIndex, length);
    467         writerIndex += length;
    468     }
    469
    470     public void writeBytes(ByteBuffer src) {
    471         int length = src.remaining();
    472         setBytes(writerIndex, src);
    473         writerIndex += length;
    474     }
    475
    476     public int writeBytes(InputStream in, int length)
    477             throws IOException {
    478         int writtenBytes = setBytes(writerIndex, in, length);
    479         if (writtenBytes > 0) {
    480             writerIndex += writtenBytes;
    481         }
    482         return writtenBytes;
    483     }
    484
    485     public int writeBytes(ScatteringByteChannel in, int length)
    486             throws IOException {
    487         int writtenBytes = setBytes(writerIndex, in, length);
    488         if (writtenBytes > 0) {
    489             writerIndex += writtenBytes;
    490         }
    491         return writtenBytes;
    492     }
    493
    494     public void writeZero(int length) {
    495         if (length == 0) {
    496             return;
    497         }
    498         if (length < 0) {
    499             throw new IllegalArgumentException(
    500                     "length must be 0 or greater than 0.");
    501         }
    502         int nLong = length >>> 3;
    503         int nBytes = length & 7;
    504         for (int i = nLong; i > 0; i --) {
    505             writeLong(0);
    506         }
    507         if (nBytes == 4) {
    508             writeInt(0);
    509         } else if (nBytes < 4) {
    510             for (int i = nBytes; i > 0; i --) {
    511                 writeByte((byte) 0);
    512             }
    513         } else {
    514             writeInt(0);
    515             for (int i = nBytes - 4; i > 0; i --) {
    516                 writeByte((byte) 0);
    517             }
    518         }
    519     }
    520
    521     public ChannelBuffer copy() {
    522         return copy(readerIndex, readableBytes());
    523     }
    524
    525     public ChannelBuffer slice() {
    526         return slice(readerIndex, readableBytes());
    527     }
    528
    529     public ByteBuffer toByteBuffer() {
    530         return toByteBuffer(readerIndex, readableBytes());
    531     }
    532
    533     public ByteBuffer[] toByteBuffers() {
    534         return toByteBuffers(readerIndex, readableBytes());
    535     }
    536
    537     public ByteBuffer[] toByteBuffers(int index, int length) {
    538         return new ByteBuffer[] { toByteBuffer(index, length) };
    539     }
    540
    541     public String toString(Charset charset) {
    542         return toString(readerIndex, readableBytes(), charset);
    543     }
    544
    545     public String toString(int index, int length, Charset charset) {
    546         if (length == 0) {
    547             return "";
    548         }
    549
    550         return ChannelBuffers.decodeString(
    551                 toByteBuffer(index, length), charset);
    552     }
    553
    554     @Deprecated
    555     public String toString(int index, int length, String charsetName,
    556             ChannelBufferIndexFinder terminatorFinder) {
    557         if (terminatorFinder == null) {
    558             return toString(index, length, charsetName);
    559         }
    560
    561         int terminatorIndex = indexOf(index, index + length, terminatorFinder);
    562         if (terminatorIndex < 0) {
    563             return toString(index, length, charsetName);
    564         }
    565
    566         return toString(index, terminatorIndex - index, charsetName);
    567     }
    568
    569     @Deprecated
    570     public String toString(int index, int length, String charsetName) {
    571         return toString(index, length, Charset.forName(charsetName));
    572     }
    573
    574     @Deprecated
    575     public String toString(String charsetName,
    576             ChannelBufferIndexFinder terminatorFinder) {
    577         return toString(readerIndex, readableBytes(), charsetName, terminatorFinder);
    578     }
    579
    580     @Deprecated
    581     public String toString(String charsetName) {
    582         return toString(Charset.forName(charsetName));
    583     }
    584
    585     public int indexOf(int fromIndex, int toIndex, byte value) {
    586         return ChannelBuffers.indexOf(this, fromIndex, toIndex, value);
    587     }
    588
    589     public int indexOf(int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
    590         return ChannelBuffers.indexOf(this, fromIndex, toIndex, indexFinder);
    591     }
    592
    593     public int bytesBefore(byte value) {
    594         return bytesBefore(readerIndex(), readableBytes(), value);
    595     }
    596
    597     public int bytesBefore(ChannelBufferIndexFinder indexFinder) {
    598         return bytesBefore(readerIndex(), readableBytes(), indexFinder);
    599     }
    600
    601     public int bytesBefore(int length, byte value) {
    602         checkReadableBytes(length);
    603         return bytesBefore(readerIndex(), length, value);
    604     }
    605
    606     public int bytesBefore(int length, ChannelBufferIndexFinder indexFinder) {
    607         checkReadableBytes(length);
    608         return bytesBefore(readerIndex(), length, indexFinder);
    609     }
    610
    611     public int bytesBefore(int index, int length, byte value) {
    612         int endIndex = indexOf(index, index + length, value);
    613         if (endIndex < 0) {
    614             return -1;
    615         }
    616         return endIndex - index;
    617     }
    618
    619     public int bytesBefore(int index, int length,
    620             ChannelBufferIndexFinder indexFinder) {
    621         int endIndex = indexOf(index, index + length, indexFinder);
    622         if (endIndex < 0) {
    623             return -1;
    624         }
    625         return endIndex - index;
    626     }
    627
    628     @Override
    629     public int hashCode() {
    630         return ChannelBuffers.hashCode(this);
    631     }
    632
    633     @Override
    634     public boolean equals(Object o) {
    635         if (!(o instanceof ChannelBuffer)) {
    636             return false;
    637         }
    638         return ChannelBuffers.equals(this, (ChannelBuffer) o);
    639     }
    640
    641     public int compareTo(ChannelBuffer that) {
    642         return ChannelBuffers.compare(this, that);
    643     }
    644
    645     @Override
    646     public String toString() {
    647         return getClass().getSimpleName() + '(' +
    648                "ridx=" + readerIndex + ", " +
    649                "widx=" + writerIndex + ", " +
    650                "cap=" + capacity() +
    651                ')';
    652     }
    653
    654     /**
    655      * Throws an {@link IndexOutOfBoundsException} if the current
    656      * {@linkplain #readableBytes() readable bytes} of this buffer is less
    657      * than the specified value.
    658      */
    659     protected void checkReadableBytes(int minimumReadableBytes) {
    660         if (readableBytes() < minimumReadableBytes) {
    661             throw new IndexOutOfBoundsException("Not enough readable bytes - Need "
    662                     + minimumReadableBytes + ", maximum is " + readableBytes());
    663         }
    664     }
    665 }