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: 2206M $, $Date: 2010-11-09 15:04:10 +0900 (Tue, 09 Nov 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 }