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    *   https://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.EmptyArrays;
19  import io.netty.util.internal.PlatformDependent;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.OutputStream;
24  import java.nio.ByteBuffer;
25  import java.nio.ByteOrder;
26  import java.nio.channels.ClosedChannelException;
27  import java.nio.channels.FileChannel;
28  import java.nio.channels.GatheringByteChannel;
29  import java.nio.channels.ScatteringByteChannel;
30  
31  import static io.netty.util.internal.ObjectUtil.checkNotNull;
32  
33  /**
34   * Big endian Java heap buffer implementation. It is recommended to use
35   * {@link UnpooledByteBufAllocator#heapBuffer(int, int)}, {@link Unpooled#buffer(int)} and
36   * {@link Unpooled#wrappedBuffer(byte[])} instead of calling the constructor explicitly.
37   */
38  public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
39  
40      private final ByteBufAllocator alloc;
41      byte[] array;
42      private ByteBuffer tmpNioBuf;
43  
44      /**
45       * Creates a new heap buffer with a newly allocated byte array.
46       *
47       * @param initialCapacity the initial capacity of the underlying byte array
48       * @param maxCapacity the max capacity of the underlying byte array
49       */
50      public UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
51          super(maxCapacity);
52  
53          if (initialCapacity > maxCapacity) {
54              throw new IllegalArgumentException(String.format(
55                      "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
56          }
57  
58          this.alloc = checkNotNull(alloc, "alloc");
59          setArray(allocateArray(initialCapacity));
60          setIndex(0, 0);
61      }
62  
63      /**
64       * Creates a new heap buffer with an existing byte array.
65       *
66       * @param initialArray the initial underlying byte array
67       * @param maxCapacity the max capacity of the underlying byte array
68       */
69      protected UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) {
70          super(maxCapacity);
71  
72          checkNotNull(alloc, "alloc");
73          checkNotNull(initialArray, "initialArray");
74          if (initialArray.length > maxCapacity) {
75              throw new IllegalArgumentException(String.format(
76                      "initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity));
77          }
78  
79          this.alloc = alloc;
80          setArray(initialArray);
81          setIndex(0, initialArray.length);
82      }
83  
84      protected byte[] allocateArray(int initialCapacity) {
85          return new byte[initialCapacity];
86      }
87  
88      protected void freeArray(byte[] array) {
89          // NOOP
90      }
91  
92      private void setArray(byte[] initialArray) {
93          array = initialArray;
94          tmpNioBuf = null;
95      }
96  
97      @Override
98      public ByteBufAllocator alloc() {
99          return alloc;
100     }
101 
102     @Override
103     public ByteOrder order() {
104         return ByteOrder.BIG_ENDIAN;
105     }
106 
107     @Override
108     public boolean isDirect() {
109         return false;
110     }
111 
112     @Override
113     public int capacity() {
114         return array.length;
115     }
116 
117     @Override
118     public ByteBuf capacity(int newCapacity) {
119         checkNewCapacity(newCapacity);
120         byte[] oldArray = array;
121         int oldCapacity = oldArray.length;
122         if (newCapacity == oldCapacity) {
123             return this;
124         }
125 
126         int bytesToCopy;
127         if (newCapacity > oldCapacity) {
128             bytesToCopy = oldCapacity;
129         } else {
130             trimIndicesToCapacity(newCapacity);
131             bytesToCopy = newCapacity;
132         }
133         byte[] newArray = allocateArray(newCapacity);
134         System.arraycopy(oldArray, 0, newArray, 0, bytesToCopy);
135         setArray(newArray);
136         freeArray(oldArray);
137         return this;
138     }
139 
140     @Override
141     public boolean hasArray() {
142         return true;
143     }
144 
145     @Override
146     public byte[] array() {
147         ensureAccessible();
148         return array;
149     }
150 
151     @Override
152     public int arrayOffset() {
153         return 0;
154     }
155 
156     @Override
157     public boolean hasMemoryAddress() {
158         return false;
159     }
160 
161     @Override
162     public long memoryAddress() {
163         throw new UnsupportedOperationException();
164     }
165 
166     @Override
167     public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
168         checkDstIndex(index, length, dstIndex, dst.capacity());
169         if (dst.hasMemoryAddress()) {
170             PlatformDependent.copyMemory(array, index, dst.memoryAddress() + dstIndex, length);
171         } else if (dst.hasArray()) {
172             getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
173         } else {
174             dst.setBytes(dstIndex, array, index, length);
175         }
176         return this;
177     }
178 
179     @Override
180     public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
181         checkDstIndex(index, length, dstIndex, dst.length);
182         System.arraycopy(array, index, dst, dstIndex, length);
183         return this;
184     }
185 
186     @Override
187     public ByteBuf getBytes(int index, ByteBuffer dst) {
188         ensureAccessible();
189         dst.put(array, index, dst.remaining());
190         return this;
191     }
192 
193     @Override
194     public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
195         ensureAccessible();
196         out.write(array, index, length);
197         return this;
198     }
199 
200     @Override
201     public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
202         ensureAccessible();
203         return getBytes(index, out, length, false);
204     }
205 
206     @Override
207     public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
208         ensureAccessible();
209         return getBytes(index, out, position, length, false);
210     }
211 
212     private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
213         ensureAccessible();
214         ByteBuffer tmpBuf;
215         if (internal) {
216             tmpBuf = internalNioBuffer();
217         } else {
218             tmpBuf = ByteBuffer.wrap(array);
219         }
220         return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length));
221     }
222 
223     private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
224         ensureAccessible();
225         ByteBuffer tmpBuf = internal ? internalNioBuffer() : ByteBuffer.wrap(array);
226         return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length), position);
227     }
228 
229     @Override
230     public int readBytes(GatheringByteChannel out, int length) throws IOException {
231         checkReadableBytes(length);
232         int readBytes = getBytes(readerIndex, out, length, true);
233         readerIndex += readBytes;
234         return readBytes;
235     }
236 
237     @Override
238     public int readBytes(FileChannel out, long position, int length) throws IOException {
239         checkReadableBytes(length);
240         int readBytes = getBytes(readerIndex, out, position, length, true);
241         readerIndex += readBytes;
242         return readBytes;
243     }
244 
245     @Override
246     public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
247         checkSrcIndex(index, length, srcIndex, src.capacity());
248         if (src.hasMemoryAddress()) {
249             PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, array, index, length);
250         } else  if (src.hasArray()) {
251             setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);
252         } else {
253             src.getBytes(srcIndex, array, index, length);
254         }
255         return this;
256     }
257 
258     @Override
259     public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
260         checkSrcIndex(index, length, srcIndex, src.length);
261         System.arraycopy(src, srcIndex, array, index, length);
262         return this;
263     }
264 
265     @Override
266     public ByteBuf setBytes(int index, ByteBuffer src) {
267         ensureAccessible();
268         src.get(array, index, src.remaining());
269         return this;
270     }
271 
272     @Override
273     public int setBytes(int index, InputStream in, int length) throws IOException {
274         ensureAccessible();
275         return in.read(array, index, length);
276     }
277 
278     @Override
279     public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
280         ensureAccessible();
281         try {
282             return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length));
283         } catch (ClosedChannelException ignored) {
284             return -1;
285         }
286     }
287 
288     @Override
289     public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
290         ensureAccessible();
291         try {
292             return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length), position);
293         } catch (ClosedChannelException ignored) {
294             return -1;
295         }
296     }
297 
298     @Override
299     public int nioBufferCount() {
300         return 1;
301     }
302 
303     @Override
304     public ByteBuffer nioBuffer(int index, int length) {
305         ensureAccessible();
306         return ByteBuffer.wrap(array, index, length).slice();
307     }
308 
309     @Override
310     public ByteBuffer[] nioBuffers(int index, int length) {
311         return new ByteBuffer[] { nioBuffer(index, length) };
312     }
313 
314     @Override
315     public ByteBuffer internalNioBuffer(int index, int length) {
316         checkIndex(index, length);
317         return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
318     }
319 
320     @Override
321     public final boolean isContiguous() {
322         return true;
323     }
324 
325     @Override
326     public byte getByte(int index) {
327         ensureAccessible();
328         return _getByte(index);
329     }
330 
331     @Override
332     protected byte _getByte(int index) {
333         return HeapByteBufUtil.getByte(array, index);
334     }
335 
336     @Override
337     public short getShort(int index) {
338         ensureAccessible();
339         return _getShort(index);
340     }
341 
342     @Override
343     protected short _getShort(int index) {
344         return HeapByteBufUtil.getShort(array, index);
345     }
346 
347     @Override
348     public short getShortLE(int index) {
349         ensureAccessible();
350         return _getShortLE(index);
351     }
352 
353     @Override
354     protected short _getShortLE(int index) {
355         return HeapByteBufUtil.getShortLE(array, index);
356     }
357 
358     @Override
359     public int getUnsignedMedium(int index) {
360         ensureAccessible();
361         return _getUnsignedMedium(index);
362     }
363 
364     @Override
365     protected int _getUnsignedMedium(int index) {
366         return HeapByteBufUtil.getUnsignedMedium(array, index);
367     }
368 
369     @Override
370     public int getUnsignedMediumLE(int index) {
371         ensureAccessible();
372         return _getUnsignedMediumLE(index);
373     }
374 
375     @Override
376     protected int _getUnsignedMediumLE(int index) {
377         return HeapByteBufUtil.getUnsignedMediumLE(array, index);
378     }
379 
380     @Override
381     public int getInt(int index) {
382         ensureAccessible();
383         return _getInt(index);
384     }
385 
386     @Override
387     protected int _getInt(int index) {
388         return HeapByteBufUtil.getInt(array, index);
389     }
390 
391     @Override
392     public int getIntLE(int index) {
393         ensureAccessible();
394         return _getIntLE(index);
395     }
396 
397     @Override
398     protected int _getIntLE(int index) {
399         return HeapByteBufUtil.getIntLE(array, index);
400     }
401 
402     @Override
403     public long getLong(int index) {
404         ensureAccessible();
405         return _getLong(index);
406     }
407 
408     @Override
409     protected long _getLong(int index) {
410         return HeapByteBufUtil.getLong(array, index);
411     }
412 
413     @Override
414     public long getLongLE(int index) {
415         ensureAccessible();
416         return _getLongLE(index);
417     }
418 
419     @Override
420     protected long _getLongLE(int index) {
421         return HeapByteBufUtil.getLongLE(array, index);
422     }
423 
424     @Override
425     public ByteBuf setByte(int index, int value) {
426         ensureAccessible();
427         _setByte(index, value);
428         return this;
429     }
430 
431     @Override
432     protected void _setByte(int index, int value) {
433         HeapByteBufUtil.setByte(array, index, value);
434     }
435 
436     @Override
437     public ByteBuf setShort(int index, int value) {
438         ensureAccessible();
439         _setShort(index, value);
440         return this;
441     }
442 
443     @Override
444     protected void _setShort(int index, int value) {
445         HeapByteBufUtil.setShort(array, index, value);
446     }
447 
448     @Override
449     public ByteBuf setShortLE(int index, int value) {
450         ensureAccessible();
451         _setShortLE(index, value);
452         return this;
453     }
454 
455     @Override
456     protected void _setShortLE(int index, int value) {
457         HeapByteBufUtil.setShortLE(array, index, value);
458     }
459 
460     @Override
461     public ByteBuf setMedium(int index, int   value) {
462         ensureAccessible();
463         _setMedium(index, value);
464         return this;
465     }
466 
467     @Override
468     protected void _setMedium(int index, int value) {
469         HeapByteBufUtil.setMedium(array, index, value);
470     }
471 
472     @Override
473     public ByteBuf setMediumLE(int index, int   value) {
474         ensureAccessible();
475         _setMediumLE(index, value);
476         return this;
477     }
478 
479     @Override
480     protected void _setMediumLE(int index, int value) {
481         HeapByteBufUtil.setMediumLE(array, index, value);
482     }
483 
484     @Override
485     public ByteBuf setInt(int index, int   value) {
486         ensureAccessible();
487         _setInt(index, value);
488         return this;
489     }
490 
491     @Override
492     protected void _setInt(int index, int value) {
493         HeapByteBufUtil.setInt(array, index, value);
494     }
495 
496     @Override
497     public ByteBuf setIntLE(int index, int   value) {
498         ensureAccessible();
499         _setIntLE(index, value);
500         return this;
501     }
502 
503     @Override
504     protected void _setIntLE(int index, int value) {
505         HeapByteBufUtil.setIntLE(array, index, value);
506     }
507 
508     @Override
509     public ByteBuf setLong(int index, long  value) {
510         ensureAccessible();
511         _setLong(index, value);
512         return this;
513     }
514 
515     @Override
516     protected void _setLong(int index, long value) {
517         HeapByteBufUtil.setLong(array, index, value);
518     }
519 
520     @Override
521     public ByteBuf setLongLE(int index, long  value) {
522         ensureAccessible();
523         _setLongLE(index, value);
524         return this;
525     }
526 
527     @Override
528     protected void _setLongLE(int index, long value) {
529         HeapByteBufUtil.setLongLE(array, index, value);
530     }
531 
532     @Override
533     public ByteBuf copy(int index, int length) {
534         checkIndex(index, length);
535         return alloc().heapBuffer(length, maxCapacity()).writeBytes(array, index, length);
536     }
537 
538     private ByteBuffer internalNioBuffer() {
539         ByteBuffer tmpNioBuf = this.tmpNioBuf;
540         if (tmpNioBuf == null) {
541             this.tmpNioBuf = tmpNioBuf = ByteBuffer.wrap(array);
542         }
543         return tmpNioBuf;
544     }
545 
546     @Override
547     protected void deallocate() {
548         freeArray(array);
549         array = EmptyArrays.EMPTY_BYTES;
550     }
551 
552     @Override
553     public ByteBuf unwrap() {
554         return null;
555     }
556 }