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.ClosedChannelException;
    23  import java.nio.channels.GatheringByteChannel;
    24  import java.nio.channels.ScatteringByteChannel;
    25
    26  /**
    27   * A skeletal implementation for Java heap buffers.
    28   */
    29  public abstract class HeapChannelBuffer extends AbstractChannelBuffer {
    30
    31      /**
    32       * The underlying heap byte array that this buffer is wrapping.
    33       */
    34      protected final byte[] array;
    35
    36      /**
    37       * Creates a new heap buffer with a newly allocated byte array.
    38       *
    39       * @param length the length of the new byte array
    40       */
    41      public HeapChannelBuffer(int length) {
    42          this(new byte[length], 0, 0);
    43      }
    44
    45      /**
    46       * Creates a new heap buffer with an existing byte array.
    47       *
    48       * @param array the byte array to wrap
    49       */
    50      public HeapChannelBuffer(byte[] array) {
    51          this(array, 0, array.length);
    52      }
    53
    54      /**
    55       * Creates a new heap buffer with an existing byte array.
    56       *
    57       * @param array        the byte array to wrap
    58       * @param readerIndex  the initial reader index of this buffer
    59       * @param writerIndex  the initial writer index of this buffer
    60       */
    61      protected HeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
    62          if (array == null) {
    63              throw new NullPointerException("array");
    64          }
    65          this.array = array;
    66          setIndex(readerIndex, writerIndex);
    67      }
    68
    69      public boolean isDirect() {
    70          return false;
    71      }
    72
    73      public int capacity() {
    74          return array.length;
    75      }
    76
    77      public boolean hasArray() {
    78          return true;
    79      }
    80
    81      public byte[] array() {
    82          return array;
    83      }
    84
    85      public int arrayOffset() {
    86          return 0;
    87      }
    88
    89      public byte getByte(int index) {
    90          return array[index];
    91      }
    92
    93      public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
    94          if (dst instanceof HeapChannelBuffer) {
    95              getBytes(index, ((HeapChannelBuffer) dst).array, dstIndex, length);
    96          } else {
    97              dst.setBytes(dstIndex, array, index, length);
    98          }
    99      }
    100
    101     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
    102         System.arraycopy(array, index, dst, dstIndex, length);
    103     }
    104
    105     public void getBytes(int index, ByteBuffer dst) {
    106         dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
    107     }
    108
    109     public void getBytes(int index, OutputStream out, int length)
    110             throws IOException {
    111         out.write(array, index, length);
    112     }
    113
    114     public int getBytes(int index, GatheringByteChannel out, int length)
    115             throws IOException {
    116         return out.write(ByteBuffer.wrap(array, index, length));
    117     }
    118
    119     public void setByte(int index, int value) {
    120         array[index] = (byte) value;
    121     }
    122
    123     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
    124         if (src instanceof HeapChannelBuffer) {
    125             setBytes(index, ((HeapChannelBuffer) src).array, srcIndex, length);
    126         } else {
    127             src.getBytes(srcIndex, array, index, length);
    128         }
    129     }
    130
    131     public void setBytes(int index, byte[] src, int srcIndex, int length) {
    132         System.arraycopy(src, srcIndex, array, index, length);
    133     }
    134
    135     public void setBytes(int index, ByteBuffer src) {
    136         src.get(array, index, src.remaining());
    137     }
    138
    139     public int setBytes(int index, InputStream in, int length) throws IOException {
    140         int readBytes = 0;
    141         do {
    142             int localReadBytes = in.read(array, index, length);
    143             if (localReadBytes < 0) {
    144                 if (readBytes == 0) {
    145                     return -1;
    146                 } else {
    147                     break;
    148                 }
    149             }
    150             readBytes += localReadBytes;
    151             index += localReadBytes;
    152             length -= localReadBytes;
    153         } while (length > 0);
    154
    155         return readBytes;
    156     }
    157
    158     public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
    159         ByteBuffer buf = ByteBuffer.wrap(array, index, length);
    160         int readBytes = 0;
    161
    162         do {
    163             int localReadBytes;
    164             try {
    165                 localReadBytes = in.read(buf);
    166             } catch (ClosedChannelException e) {
    167                 localReadBytes = -1;
    168             }
    169             if (localReadBytes < 0) {
    170                 if (readBytes == 0) {
    171                     return -1;
    172                 } else {
    173                     break;
    174                 }
    175             } else if (localReadBytes == 0) {
    176                 break;
    177             }
    178             readBytes += localReadBytes;
    179         } while (readBytes < length);
    180
    181         return readBytes;
    182     }
    183
    184     public ChannelBuffer slice(int index, int length) {
    185         if (index == 0) {
    186             if (length == 0) {
    187                 return ChannelBuffers.EMPTY_BUFFER;
    188             }
    189             if (length == array.length) {
    190                 ChannelBuffer slice = duplicate();
    191                 slice.setIndex(0, length);
    192                 return slice;
    193             } else {
    194                 return new TruncatedChannelBuffer(this, length);
    195             }
    196         } else {
    197             if (length == 0) {
    198                 return ChannelBuffers.EMPTY_BUFFER;
    199             }
    200             return new SlicedChannelBuffer(this, index, length);
    201         }
    202     }
    203
    204     public ByteBuffer toByteBuffer(int index, int length) {
    205         return ByteBuffer.wrap(array, index, length).order(order());
    206     }
    207 }