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