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 io.netty.buffer;
17  
18  import io.netty.util.internal.PlatformDependent;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.nio.ByteBuffer;
24  import java.nio.ByteOrder;
25  import java.nio.channels.ClosedChannelException;
26  import java.nio.channels.GatheringByteChannel;
27  import java.nio.channels.ScatteringByteChannel;
28  
29  /**
30   * Big endian Java heap buffer implementation.
31   */
32  public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
33  
34      private final ByteBufAllocator alloc;
35      private byte[] array;
36      private ByteBuffer tmpNioBuf;
37  
38      /**
39       * Creates a new heap buffer with a newly allocated byte array.
40       *
41       * @param initialCapacity the initial capacity of the underlying byte array
42       * @param maxCapacity the max capacity of the underlying byte array
43       */
44      protected UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
45          this(alloc, new byte[initialCapacity], 0, 0, maxCapacity);
46      }
47  
48      /**
49       * Creates a new heap buffer with an existing byte array.
50       *
51       * @param initialArray the initial underlying byte array
52       * @param maxCapacity the max capacity of the underlying byte array
53       */
54      protected UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) {
55          this(alloc, initialArray, 0, initialArray.length, maxCapacity);
56      }
57  
58      private UnpooledHeapByteBuf(
59              ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {
60  
61          super(maxCapacity);
62  
63          if (alloc == null) {
64              throw new NullPointerException("alloc");
65          }
66          if (initialArray == null) {
67              throw new NullPointerException("initialArray");
68          }
69          if (initialArray.length > maxCapacity) {
70              throw new IllegalArgumentException(String.format(
71                      "initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity));
72          }
73  
74          this.alloc = alloc;
75          setArray(initialArray);
76          setIndex(readerIndex, writerIndex);
77      }
78  
79      private void setArray(byte[] initialArray) {
80          array = initialArray;
81          tmpNioBuf = null;
82      }
83  
84      @Override
85      public ByteBufAllocator alloc() {
86          return alloc;
87      }
88  
89      @Override
90      public ByteOrder order() {
91          return ByteOrder.BIG_ENDIAN;
92      }
93  
94      @Override
95      public boolean isDirect() {
96          return false;
97      }
98  
99      @Override
100     public int capacity() {
101         ensureAccessible();
102         return array.length;
103     }
104 
105     @Override
106     public ByteBuf capacity(int newCapacity) {
107         ensureAccessible();
108         if (newCapacity < 0 || newCapacity > maxCapacity()) {
109             throw new IllegalArgumentException("newCapacity: " + newCapacity);
110         }
111 
112         int oldCapacity = array.length;
113         if (newCapacity > oldCapacity) {
114             byte[] newArray = new byte[newCapacity];
115             System.arraycopy(array, 0, newArray, 0, array.length);
116             setArray(newArray);
117         } else if (newCapacity < oldCapacity) {
118             byte[] newArray = new byte[newCapacity];
119             int readerIndex = readerIndex();
120             if (readerIndex < newCapacity) {
121                 int writerIndex = writerIndex();
122                 if (writerIndex > newCapacity) {
123                     writerIndex(writerIndex = newCapacity);
124                 }
125                 System.arraycopy(array, readerIndex, newArray, readerIndex, writerIndex - readerIndex);
126             } else {
127                 setIndex(newCapacity, newCapacity);
128             }
129             setArray(newArray);
130         }
131         return this;
132     }
133 
134     @Override
135     public boolean hasArray() {
136         return true;
137     }
138 
139     @Override
140     public byte[] array() {
141         ensureAccessible();
142         return array;
143     }
144 
145     @Override
146     public int arrayOffset() {
147         return 0;
148     }
149 
150     @Override
151     public boolean hasMemoryAddress() {
152         return false;
153     }
154 
155     @Override
156     public long memoryAddress() {
157         throw new UnsupportedOperationException();
158     }
159 
160     @Override
161     public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
162         checkDstIndex(index, length, dstIndex, dst.capacity());
163         if (dst.hasMemoryAddress()) {
164             PlatformDependent.copyMemory(array, index, dst.memoryAddress() + dstIndex, length);
165         } else if (dst.hasArray()) {
166             getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
167         } else {
168             dst.setBytes(dstIndex, array, index, length);
169         }
170         return this;
171     }
172 
173     @Override
174     public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
175         checkDstIndex(index, length, dstIndex, dst.length);
176         System.arraycopy(array, index, dst, dstIndex, length);
177         return this;
178     }
179 
180     @Override
181     public ByteBuf getBytes(int index, ByteBuffer dst) {
182         ensureAccessible();
183         dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
184         return this;
185     }
186 
187     @Override
188     public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
189         ensureAccessible();
190         out.write(array, index, length);
191         return this;
192     }
193 
194     @Override
195     public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
196         ensureAccessible();
197         return getBytes(index, out, length, false);
198     }
199 
200     private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
201         ensureAccessible();
202         ByteBuffer tmpBuf;
203         if (internal) {
204             tmpBuf = internalNioBuffer();
205         } else {
206             tmpBuf = ByteBuffer.wrap(array);
207         }
208         return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length));
209     }
210 
211     @Override
212     public int readBytes(GatheringByteChannel out, int length) throws IOException {
213         checkReadableBytes(length);
214         int readBytes = getBytes(readerIndex, out, length, true);
215         readerIndex += readBytes;
216         return readBytes;
217     }
218 
219     @Override
220     public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
221         checkSrcIndex(index, length, srcIndex, src.capacity());
222         if (src.hasMemoryAddress()) {
223             PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, array, index, length);
224         } else  if (src.hasArray()) {
225             setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);
226         } else {
227             src.getBytes(srcIndex, array, index, length);
228         }
229         return this;
230     }
231 
232     @Override
233     public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
234         checkSrcIndex(index, length, srcIndex, src.length);
235         System.arraycopy(src, srcIndex, array, index, length);
236         return this;
237     }
238 
239     @Override
240     public ByteBuf setBytes(int index, ByteBuffer src) {
241         ensureAccessible();
242         src.get(array, index, src.remaining());
243         return this;
244     }
245 
246     @Override
247     public int setBytes(int index, InputStream in, int length) throws IOException {
248         ensureAccessible();
249         return in.read(array, index, length);
250     }
251 
252     @Override
253     public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
254         ensureAccessible();
255         try {
256             return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length));
257         } catch (ClosedChannelException ignored) {
258             return -1;
259         }
260     }
261 
262     @Override
263     public int nioBufferCount() {
264         return 1;
265     }
266 
267     @Override
268     public ByteBuffer nioBuffer(int index, int length) {
269         ensureAccessible();
270         return ByteBuffer.wrap(array, index, length).slice();
271     }
272 
273     @Override
274     public ByteBuffer[] nioBuffers(int index, int length) {
275         return new ByteBuffer[] { nioBuffer(index, length) };
276     }
277 
278     @Override
279     public ByteBuffer internalNioBuffer(int index, int length) {
280         checkIndex(index, length);
281         return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
282     }
283 
284     @Override
285     public byte getByte(int index) {
286         ensureAccessible();
287         return _getByte(index);
288     }
289 
290     @Override
291     protected byte _getByte(int index) {
292         return array[index];
293     }
294 
295     @Override
296     public short getShort(int index) {
297         ensureAccessible();
298         return _getShort(index);
299     }
300 
301     @Override
302     protected short _getShort(int index) {
303         return (short) (array[index] << 8 | array[index + 1] & 0xFF);
304     }
305 
306     @Override
307     public int getUnsignedMedium(int index) {
308         ensureAccessible();
309         return _getUnsignedMedium(index);
310     }
311 
312     @Override
313     protected int _getUnsignedMedium(int index) {
314         return  (array[index]     & 0xff) << 16 |
315                 (array[index + 1] & 0xff) <<  8 |
316                  array[index + 2] & 0xff;
317     }
318 
319     @Override
320     public int getInt(int index) {
321         ensureAccessible();
322         return _getInt(index);
323     }
324 
325     @Override
326     protected int _getInt(int index) {
327         return  (array[index]     & 0xff) << 24 |
328                 (array[index + 1] & 0xff) << 16 |
329                 (array[index + 2] & 0xff) <<  8 |
330                  array[index + 3] & 0xff;
331     }
332 
333     @Override
334     public long getLong(int index) {
335         ensureAccessible();
336         return _getLong(index);
337     }
338 
339     @Override
340     protected long _getLong(int index) {
341         return  ((long) array[index]     & 0xff) << 56 |
342                 ((long) array[index + 1] & 0xff) << 48 |
343                 ((long) array[index + 2] & 0xff) << 40 |
344                 ((long) array[index + 3] & 0xff) << 32 |
345                 ((long) array[index + 4] & 0xff) << 24 |
346                 ((long) array[index + 5] & 0xff) << 16 |
347                 ((long) array[index + 6] & 0xff) <<  8 |
348                  (long) array[index + 7] & 0xff;
349     }
350 
351     @Override
352     public ByteBuf setByte(int index, int value) {
353         ensureAccessible();
354         _setByte(index, value);
355         return this;
356     }
357 
358     @Override
359     protected void _setByte(int index, int value) {
360         array[index] = (byte) value;
361     }
362 
363     @Override
364     public ByteBuf setShort(int index, int value) {
365         ensureAccessible();
366         _setShort(index, value);
367         return this;
368     }
369 
370     @Override
371     protected void _setShort(int index, int value) {
372         array[index]     = (byte) (value >>> 8);
373         array[index + 1] = (byte) value;
374     }
375 
376     @Override
377     public ByteBuf setMedium(int index, int   value) {
378         ensureAccessible();
379         _setMedium(index, value);
380         return this;
381     }
382 
383     @Override
384     protected void _setMedium(int index, int value) {
385         array[index]     = (byte) (value >>> 16);
386         array[index + 1] = (byte) (value >>> 8);
387         array[index + 2] = (byte) value;
388     }
389 
390     @Override
391     public ByteBuf setInt(int index, int   value) {
392         ensureAccessible();
393         _setInt(index, value);
394         return this;
395     }
396 
397     @Override
398     protected void _setInt(int index, int value) {
399         array[index]     = (byte) (value >>> 24);
400         array[index + 1] = (byte) (value >>> 16);
401         array[index + 2] = (byte) (value >>> 8);
402         array[index + 3] = (byte) value;
403     }
404 
405     @Override
406     public ByteBuf setLong(int index, long  value) {
407         ensureAccessible();
408         _setLong(index, value);
409         return this;
410     }
411 
412     @Override
413     protected void _setLong(int index, long value) {
414         array[index]     = (byte) (value >>> 56);
415         array[index + 1] = (byte) (value >>> 48);
416         array[index + 2] = (byte) (value >>> 40);
417         array[index + 3] = (byte) (value >>> 32);
418         array[index + 4] = (byte) (value >>> 24);
419         array[index + 5] = (byte) (value >>> 16);
420         array[index + 6] = (byte) (value >>> 8);
421         array[index + 7] = (byte) value;
422     }
423 
424     @Override
425     public ByteBuf copy(int index, int length) {
426         checkIndex(index, length);
427         byte[] copiedArray = new byte[length];
428         System.arraycopy(array, index, copiedArray, 0, length);
429         return new UnpooledHeapByteBuf(alloc(), copiedArray, maxCapacity());
430     }
431 
432     private ByteBuffer internalNioBuffer() {
433         ByteBuffer tmpNioBuf = this.tmpNioBuf;
434         if (tmpNioBuf == null) {
435             this.tmpNioBuf = tmpNioBuf = ByteBuffer.wrap(array);
436         }
437         return tmpNioBuf;
438     }
439 
440     @Override
441     protected void deallocate() {
442         array = null;
443     }
444 
445     @Override
446     public ByteBuf unwrap() {
447         return null;
448     }
449 }