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.ByteOrder;
    23  import java.nio.channels.GatheringByteChannel;
    24  import java.nio.channels.ScatteringByteChannel;
    25
    26
    27  /**
    28   * A derived buffer which exposes its parent's sub-region only.  It is
    29   * recommended to use {@link ChannelBuffer#slice()} and
    30   * {@link ChannelBuffer#slice(int, int)} instead of calling the constructor
    31   * explicitly.
    32   */
    33  public class SlicedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
    34
    35      private final ChannelBuffer buffer;
    36      private final int adjustment;
    37      private final int length;
    38
    39      public SlicedChannelBuffer(ChannelBuffer buffer, int index, int length) {
    40          if (index < 0 || index > buffer.capacity()) {
    41              throw new IndexOutOfBoundsException("Invalid index of " + index
    42                      + ", maximum is " + buffer.capacity());
    43          }
    44
    45          if (index + length > buffer.capacity()) {
    46              throw new IndexOutOfBoundsException("Invalid combined index of "
    47                      + (index + length) + ", maximum is " + buffer.capacity());
    48          }
    49
    50          this.buffer = buffer;
    51          adjustment = index;
    52          this.length = length;
    53          writerIndex(length);
    54      }
    55
    56      public ChannelBuffer unwrap() {
    57          return buffer;
    58      }
    59
    60      public ChannelBufferFactory factory() {
    61          return buffer.factory();
    62      }
    63
    64      public ByteOrder order() {
    65          return buffer.order();
    66      }
    67
    68      public boolean isDirect() {
    69          return buffer.isDirect();
    70      }
    71
    72      public int capacity() {
    73          return length;
    74      }
    75
    76      public boolean hasArray() {
    77          return buffer.hasArray();
    78      }
    79
    80      public byte[] array() {
    81          return buffer.array();
    82      }
    83
    84      public int arrayOffset() {
    85          return buffer.arrayOffset() + adjustment;
    86      }
    87
    88      public byte getByte(int index) {
    89          checkIndex(index);
    90          return buffer.getByte(index + adjustment);
    91      }
    92
    93      public short getShort(int index) {
    94          checkIndex(index, 2);
    95          return buffer.getShort(index + adjustment);
    96      }
    97
    98      public int getUnsignedMedium(int index) {
    99          checkIndex(index, 3);
    100         return buffer.getUnsignedMedium(index + adjustment);
    101     }
    102
    103     public int getInt(int index) {
    104         checkIndex(index, 4);
    105         return buffer.getInt(index + adjustment);
    106     }
    107
    108     public long getLong(int index) {
    109         checkIndex(index, 8);
    110         return buffer.getLong(index + adjustment);
    111     }
    112
    113     public ChannelBuffer duplicate() {
    114         ChannelBuffer duplicate = new SlicedChannelBuffer(buffer, adjustment, length);
    115         duplicate.setIndex(readerIndex(), writerIndex());
    116         return duplicate;
    117     }
    118
    119     public ChannelBuffer copy(int index, int length) {
    120         checkIndex(index, length);
    121         return buffer.copy(index + adjustment, length);
    122     }
    123
    124     public ChannelBuffer slice(int index, int length) {
    125         checkIndex(index, length);
    126         if (length == 0) {
    127             return ChannelBuffers.EMPTY_BUFFER;
    128         }
    129         return new SlicedChannelBuffer(buffer, index + adjustment, length);
    130     }
    131
    132     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
    133         checkIndex(index, length);
    134         buffer.getBytes(index + adjustment, dst, dstIndex, length);
    135     }
    136
    137     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
    138         checkIndex(index, length);
    139         buffer.getBytes(index + adjustment, dst, dstIndex, length);
    140     }
    141
    142     public void getBytes(int index, ByteBuffer dst) {
    143         checkIndex(index, dst.remaining());
    144         buffer.getBytes(index + adjustment, dst);
    145     }
    146
    147     public void setByte(int index, int value) {
    148         checkIndex(index);
    149         buffer.setByte(index + adjustment, value);
    150     }
    151
    152     public void setShort(int index, int value) {
    153         checkIndex(index, 2);
    154         buffer.setShort(index + adjustment, value);
    155     }
    156
    157     public void setMedium(int index, int value) {
    158         checkIndex(index, 3);
    159         buffer.setMedium(index + adjustment, value);
    160     }
    161
    162     public void setInt(int index, int value) {
    163         checkIndex(index, 4);
    164         buffer.setInt(index + adjustment, value);
    165     }
    166
    167     public void setLong(int index, long value) {
    168         checkIndex(index, 8);
    169         buffer.setLong(index + adjustment, value);
    170     }
    171
    172     public void setBytes(int index, byte[] src, int srcIndex, int length) {
    173         checkIndex(index, length);
    174         buffer.setBytes(index + adjustment, src, srcIndex, length);
    175     }
    176
    177     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
    178         checkIndex(index, length);
    179         buffer.setBytes(index + adjustment, src, srcIndex, length);
    180     }
    181
    182     public void setBytes(int index, ByteBuffer src) {
    183         checkIndex(index, src.remaining());
    184         buffer.setBytes(index + adjustment, src);
    185     }
    186
    187     public void getBytes(int index, OutputStream out, int length)
    188             throws IOException {
    189         checkIndex(index, length);
    190         buffer.getBytes(index + adjustment, out, length);
    191     }
    192
    193     public int getBytes(int index, GatheringByteChannel out, int length)
    194             throws IOException {
    195         checkIndex(index, length);
    196         return buffer.getBytes(index + adjustment, out, length);
    197     }
    198
    199     public int setBytes(int index, InputStream in, int length)
    200             throws IOException {
    201         checkIndex(index, length);
    202         return buffer.setBytes(index + adjustment, in, length);
    203     }
    204
    205     public int setBytes(int index, ScatteringByteChannel in, int length)
    206             throws IOException {
    207         checkIndex(index, length);
    208         return buffer.setBytes(index + adjustment, in, length);
    209     }
    210
    211     public ByteBuffer toByteBuffer(int index, int length) {
    212         checkIndex(index, length);
    213         return buffer.toByteBuffer(index + adjustment, length);
    214     }
    215
    216     private void checkIndex(int index) {
    217         if (index < 0 || index >= capacity()) {
    218             throw new IndexOutOfBoundsException("Invalid index: " + index
    219                     + ", maximum is " + capacity());
    220         }
    221     }
    222
    223     private void checkIndex(int startIndex, int length) {
    224         if (length < 0) {
    225             throw new IllegalArgumentException(
    226                     "length is negative: " + length);
    227         }
    228         if (startIndex < 0) {
    229             throw new IndexOutOfBoundsException("startIndex cannot be negative");
    230         }
    231         if (startIndex + length > capacity()) {
    232             throw new IndexOutOfBoundsException("Index too big - Bytes needed: "
    233                     + (startIndex + length) + ", maximum is " + capacity());
    234         }
    235     }
    236 }