View Javadoc

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