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.ByteOrder;
    23  import java.nio.channels.GatheringByteChannel;
    24  import java.nio.channels.ScatteringByteChannel;
    25
    26
    27  /**
    28   * A dynamic capacity buffer which increases its capacity as needed.  It is
    29   * recommended to use {@link ChannelBuffers#dynamicBuffer(int)} instead of
    30   * calling the constructor explicitly.
    31   *
    32   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
    33   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
    34   *
    35   * @version $Rev: 2206 $, $Date: 2010-03-03 14:35:01 +0900 (Wed, 03 Mar 2010) $
    36   *
    37   */
    38  public class DynamicChannelBuffer extends AbstractChannelBuffer {
    39
    40      private final ChannelBufferFactory factory;
    41      private final ByteOrder endianness;
    42      private ChannelBuffer buffer;
    43
    44      public DynamicChannelBuffer(int estimatedLength) {
    45          this(ByteOrder.BIG_ENDIAN, estimatedLength);
    46      }
    47
    48      public DynamicChannelBuffer(ByteOrder endianness, int estimatedLength) {
    49          this(endianness, estimatedLength, HeapChannelBufferFactory.getInstance(endianness));
    50      }
    51
    52      public DynamicChannelBuffer(ByteOrder endianness, int estimatedLength, ChannelBufferFactory factory) {
    53          if (estimatedLength < 0) {
    54              throw new IllegalArgumentException("estimatedLength: " + estimatedLength);
    55          }
    56          if (endianness == null) {
    57              throw new NullPointerException("endianness");
    58          }
    59          if (factory == null) {
    60              throw new NullPointerException("factory");
    61          }
    62          this.factory = factory;
    63          this.endianness = endianness;
    64          buffer = factory.getBuffer(order(), estimatedLength);
    65      }
    66
    67      @Override
    68      public void ensureWritableBytes(int minWritableBytes) {
    69          if (minWritableBytes <= writableBytes()) {
    70              return;
    71          }
    72
    73          int newCapacity;
    74          if (capacity() == 0) {
    75              newCapacity = 1;
    76          } else {
    77              newCapacity = capacity();
    78          }
    79          int minNewCapacity = writerIndex() + minWritableBytes;
    80          while (newCapacity < minNewCapacity) {
    81              newCapacity <<= 1;
    82          }
    83
    84          ChannelBuffer newBuffer = factory().getBuffer(order(), newCapacity);
    85          newBuffer.writeBytes(buffer, 0, writerIndex());
    86          buffer = newBuffer;
    87      }
    88
    89      public ChannelBufferFactory factory() {
    90          return factory;
    91      }
    92
    93      public ByteOrder order() {
    94          return endianness;
    95      }
    96
    97      public boolean isDirect() {
    98          return buffer.isDirect();
    99      }
    100
    101     public int capacity() {
    102         return buffer.capacity();
    103     }
    104
    105     public boolean hasArray() {
    106         return buffer.hasArray();
    107     }
    108
    109     public byte[] array() {
    110         return buffer.array();
    111     }
    112
    113     public int arrayOffset() {
    114         return buffer.arrayOffset();
    115     }
    116
    117     public byte getByte(int index) {
    118         return buffer.getByte(index);
    119     }
    120
    121     public short getShort(int index) {
    122         return buffer.getShort(index);
    123     }
    124
    125     public int getUnsignedMedium(int index) {
    126         return buffer.getUnsignedMedium(index);
    127     }
    128
    129     public int getInt(int index) {
    130         return buffer.getInt(index);
    131     }
    132
    133     public long getLong(int index) {
    134         return buffer.getLong(index);
    135     }
    136
    137     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
    138         buffer.getBytes(index, dst, dstIndex, length);
    139     }
    140
    141     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
    142         buffer.getBytes(index, dst, dstIndex, length);
    143     }
    144
    145     public void getBytes(int index, ByteBuffer dst) {
    146         buffer.getBytes(index, dst);
    147     }
    148
    149     public int getBytes(int index, GatheringByteChannel out, int length)
    150             throws IOException {
    151         return buffer.getBytes(index, out, length);
    152     }
    153
    154     public void getBytes(int index, OutputStream out, int length)
    155             throws IOException {
    156         buffer.getBytes(index, out, length);
    157     }
    158
    159     public void setByte(int index, int value) {
    160         buffer.setByte(index, value);
    161     }
    162
    163     public void setShort(int index, int value) {
    164         buffer.setShort(index, value);
    165     }
    166
    167     public void setMedium(int index, int value) {
    168         buffer.setMedium(index, value);
    169     }
    170
    171     public void setInt(int index, int value) {
    172         buffer.setInt(index, value);
    173     }
    174
    175     public void setLong(int index, long value) {
    176         buffer.setLong(index, value);
    177     }
    178
    179     public void setBytes(int index, byte[] src, int srcIndex, int length) {
    180         buffer.setBytes(index, src, srcIndex, length);
    181     }
    182
    183     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
    184         buffer.setBytes(index, src, srcIndex, length);
    185     }
    186
    187     public void setBytes(int index, ByteBuffer src) {
    188         buffer.setBytes(index, src);
    189     }
    190
    191     public int setBytes(int index, InputStream in, int length)
    192             throws IOException {
    193         return buffer.setBytes(index, in, length);
    194     }
    195
    196     public int setBytes(int index, ScatteringByteChannel in, int length)
    197             throws IOException {
    198         return buffer.setBytes(index, in, length);
    199     }
    200
    201     @Override
    202     public void writeByte(int value) {
    203         ensureWritableBytes(1);
    204         super.writeByte(value);
    205     }
    206
    207     @Override
    208     public void writeShort(int value) {
    209         ensureWritableBytes(2);
    210         super.writeShort(value);
    211     }
    212
    213     @Override
    214     public void writeMedium(int value) {
    215         ensureWritableBytes(3);
    216         super.writeMedium(value);
    217     }
    218
    219     @Override
    220     public void writeInt(int value) {
    221         ensureWritableBytes(4);
    222         super.writeInt(value);
    223     }
    224
    225     @Override
    226     public void writeLong(long value) {
    227         ensureWritableBytes(8);
    228         super.writeLong(value);
    229     }
    230
    231     @Override
    232     public void writeBytes(byte[] src, int srcIndex, int length) {
    233         ensureWritableBytes(length);
    234         super.writeBytes(src, srcIndex, length);
    235     }
    236
    237     @Override
    238     public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
    239         ensureWritableBytes(length);
    240         super.writeBytes(src, srcIndex, length);
    241     }
    242
    243     @Override
    244     public void writeBytes(ByteBuffer src) {
    245         ensureWritableBytes(src.remaining());
    246         super.writeBytes(src);
    247     }
    248
    249     @Override
    250     public int writeBytes(InputStream in, int length) throws IOException {
    251         ensureWritableBytes(length);
    252         return super.writeBytes(in, length);
    253     }
    254
    255     @Override
    256     public int writeBytes(ScatteringByteChannel in, int length)
    257             throws IOException {
    258         ensureWritableBytes(length);
    259         return super.writeBytes(in, length);
    260     }
    261
    262     @Override
    263     public void writeZero(int length) {
    264         ensureWritableBytes(length);
    265         super.writeZero(length);
    266     }
    267
    268     public ChannelBuffer duplicate() {
    269         return new DuplicatedChannelBuffer(this);
    270     }
    271
    272     public ChannelBuffer copy(int index, int length) {
    273         DynamicChannelBuffer copiedBuffer = new DynamicChannelBuffer(order(), Math.max(length, 64), factory());
    274         copiedBuffer.buffer = buffer.copy(index, length);
    275         copiedBuffer.setIndex(0, length);
    276         return copiedBuffer;
    277     }
    278
    279     public ChannelBuffer slice(int index, int length) {
    280         if (index == 0) {
    281             if (length == 0) {
    282                 return ChannelBuffers.EMPTY_BUFFER;
    283             }
    284             return new TruncatedChannelBuffer(this, length);
    285         } else {
    286             if (length == 0) {
    287                 return ChannelBuffers.EMPTY_BUFFER;
    288             }
    289             return new SlicedChannelBuffer(this, index, length);
    290         }
    291     }
    292
    293     public ByteBuffer toByteBuffer(int index, int length) {
    294         return buffer.toByteBuffer(index, length);
    295     }
    296 }