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