1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import io.netty.util.internal.CleanableDirectBuffer;
19 import io.netty.util.internal.ObjectUtil;
20 import io.netty.util.internal.PlatformDependent;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.lang.invoke.VarHandle;
26 import java.nio.ByteBuffer;
27 import java.nio.ByteOrder;
28 import java.nio.channels.ClosedChannelException;
29 import java.nio.channels.FileChannel;
30 import java.nio.channels.GatheringByteChannel;
31 import java.nio.channels.ScatteringByteChannel;
32
33 import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
34
35
36
37
38
39
40 public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
41
42 private final ByteBufAllocator alloc;
43
44 CleanableDirectBuffer cleanable;
45 ByteBuffer buffer;
46 private ByteBuffer tmpNioBuf;
47 private int capacity;
48 private boolean doNotFree;
49
50
51
52
53
54
55
56 public UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
57 super(maxCapacity);
58 ObjectUtil.checkNotNull(alloc, "alloc");
59 checkPositiveOrZero(initialCapacity, "initialCapacity");
60 checkPositiveOrZero(maxCapacity, "maxCapacity");
61 if (initialCapacity > maxCapacity) {
62 throw new IllegalArgumentException(String.format(
63 "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
64 }
65
66 this.alloc = alloc;
67 setByteBuffer(allocateDirectBuffer(initialCapacity), false);
68 }
69
70
71
72
73
74
75 protected UnpooledDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer, int maxCapacity) {
76 this(alloc, initialBuffer, maxCapacity, false, true);
77 }
78
79 UnpooledDirectByteBuf(ByteBufAllocator alloc, ByteBuffer initialBuffer,
80 int maxCapacity, boolean doFree, boolean slice) {
81 super(maxCapacity);
82 ObjectUtil.checkNotNull(alloc, "alloc");
83 ObjectUtil.checkNotNull(initialBuffer, "initialBuffer");
84 if (!initialBuffer.isDirect()) {
85 throw new IllegalArgumentException("initialBuffer is not a direct buffer.");
86 }
87 if (initialBuffer.isReadOnly()) {
88 throw new IllegalArgumentException("initialBuffer is a read-only buffer.");
89 }
90
91 int initialCapacity = initialBuffer.remaining();
92 if (initialCapacity > maxCapacity) {
93 throw new IllegalArgumentException(String.format(
94 "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
95 }
96
97 this.alloc = alloc;
98 doNotFree = !doFree;
99 setByteBuffer((slice ? initialBuffer.slice() : initialBuffer).order(ByteOrder.BIG_ENDIAN), false);
100 writerIndex(initialCapacity);
101 }
102
103
104
105
106
107 @Deprecated
108 protected ByteBuffer allocateDirect(int initialCapacity) {
109 return ByteBuffer.allocateDirect(initialCapacity);
110 }
111
112
113
114
115
116 @Deprecated
117 protected void freeDirect(ByteBuffer buffer) {
118 PlatformDependent.freeDirectBuffer(buffer);
119 }
120
121 protected CleanableDirectBuffer allocateDirectBuffer(int capacity) {
122 return PlatformDependent.allocateDirect(capacity);
123 }
124
125 void setByteBuffer(CleanableDirectBuffer cleanableDirectBuffer, boolean tryFree) {
126 if (tryFree) {
127 CleanableDirectBuffer oldCleanable = cleanable;
128 ByteBuffer oldBuffer = buffer;
129 if (oldBuffer != null) {
130 if (doNotFree) {
131 doNotFree = false;
132 } else {
133 if (oldCleanable != null) {
134 oldCleanable.clean();
135 } else {
136 freeDirect(oldBuffer);
137 }
138 }
139 }
140 }
141
142 cleanable = cleanableDirectBuffer;
143 buffer = cleanableDirectBuffer.buffer();
144 tmpNioBuf = null;
145 capacity = buffer.remaining();
146 }
147
148 void setByteBuffer(ByteBuffer buffer, boolean tryFree) {
149 if (tryFree) {
150 ByteBuffer oldBuffer = this.buffer;
151 if (oldBuffer != null) {
152 if (doNotFree) {
153 doNotFree = false;
154 } else {
155 freeDirect(oldBuffer);
156 }
157 }
158 }
159
160 this.buffer = buffer;
161 tmpNioBuf = null;
162 capacity = buffer.remaining();
163 }
164
165 @Override
166 public boolean isDirect() {
167 return true;
168 }
169
170 @Override
171 public int capacity() {
172 return capacity;
173 }
174
175 @Override
176 public ByteBuf capacity(int newCapacity) {
177 checkNewCapacity(newCapacity);
178 int oldCapacity = capacity;
179 if (newCapacity == oldCapacity) {
180 return this;
181 }
182 int bytesToCopy;
183 if (newCapacity > oldCapacity) {
184 bytesToCopy = oldCapacity;
185 } else {
186 trimIndicesToCapacity(newCapacity);
187 bytesToCopy = newCapacity;
188 }
189 ByteBuffer oldBuffer = buffer;
190 CleanableDirectBuffer newBuffer = allocateDirectBuffer(newCapacity);
191 oldBuffer.position(0).limit(bytesToCopy);
192 newBuffer.buffer().position(0).limit(bytesToCopy);
193 newBuffer.buffer().put(oldBuffer).clear();
194 setByteBuffer(newBuffer, true);
195 return this;
196 }
197
198 @Override
199 public ByteBufAllocator alloc() {
200 return alloc;
201 }
202
203 @Override
204 public ByteOrder order() {
205 return ByteOrder.BIG_ENDIAN;
206 }
207
208 @Override
209 public boolean hasArray() {
210 return false;
211 }
212
213 @Override
214 public byte[] array() {
215 throw new UnsupportedOperationException("direct buffer");
216 }
217
218 @Override
219 public int arrayOffset() {
220 throw new UnsupportedOperationException("direct buffer");
221 }
222
223 @Override
224 public boolean hasMemoryAddress() {
225 CleanableDirectBuffer cleanable = this.cleanable;
226 return cleanable != null && cleanable.hasMemoryAddress();
227 }
228
229 @Override
230 public long memoryAddress() {
231 ensureAccessible();
232 if (!hasMemoryAddress()) {
233 throw new UnsupportedOperationException();
234 }
235 return cleanable.memoryAddress();
236 }
237
238 @Override
239 public byte getByte(int index) {
240 ensureAccessible();
241 return _getByte(index);
242 }
243
244 @Override
245 protected byte _getByte(int index) {
246 return buffer.get(index);
247 }
248
249 @Override
250 public short getShortLE(int index) {
251 ensureAccessible();
252 return _getShortLE(index);
253 }
254
255 @Override
256 public short getShort(int index) {
257 ensureAccessible();
258 return _getShort(index);
259 }
260
261 @Override
262 protected short _getShort(int index) {
263 VarHandle varHandle = PlatformDependent.shortBeByteBufferView();
264 if (varHandle != null) {
265 return (short) varHandle.get(buffer, index);
266 }
267 return buffer.getShort(index);
268 }
269
270 @Override
271 protected short _getShortLE(int index) {
272 VarHandle varHandle = PlatformDependent.shortLeByteBufferView();
273 if (varHandle != null) {
274 return (short) varHandle.get(buffer, index);
275 }
276 return ByteBufUtil.swapShort(buffer.getShort(index));
277 }
278
279 @Override
280 public int getUnsignedMedium(int index) {
281 ensureAccessible();
282 return _getUnsignedMedium(index);
283 }
284
285 @Override
286 protected int _getUnsignedMedium(int index) {
287 return (getByte(index) & 0xff) << 16 |
288 (getByte(index + 1) & 0xff) << 8 |
289 getByte(index + 2) & 0xff;
290 }
291
292 @Override
293 protected int _getUnsignedMediumLE(int index) {
294 return getByte(index) & 0xff |
295 (getByte(index + 1) & 0xff) << 8 |
296 (getByte(index + 2) & 0xff) << 16;
297 }
298
299 @Override
300 public int getIntLE(int index) {
301 ensureAccessible();
302 return _getIntLE(index);
303 }
304
305 @Override
306 public int getInt(int index) {
307 ensureAccessible();
308 return _getInt(index);
309 }
310
311 @Override
312 protected int _getInt(int index) {
313 VarHandle varHandle = PlatformDependent.intBeByteBufferView();
314 if (varHandle != null) {
315 return (int) varHandle.get(buffer, index);
316 }
317 return buffer.getInt(index);
318 }
319
320 @Override
321 protected int _getIntLE(int index) {
322 VarHandle varHandle = PlatformDependent.intLeByteBufferView();
323 if (varHandle != null) {
324 return (int) varHandle.get(buffer, index);
325 }
326 return ByteBufUtil.swapInt(buffer.getInt(index));
327 }
328
329 @Override
330 public long getLongLE(int index) {
331 ensureAccessible();
332 return _getLongLE(index);
333 }
334
335 @Override
336 public long getLong(int index) {
337 ensureAccessible();
338 return _getLong(index);
339 }
340
341 @Override
342 protected long _getLong(int index) {
343 VarHandle varHandle = PlatformDependent.longBeByteBufferView();
344 if (varHandle != null) {
345 return (long) varHandle.get(buffer, index);
346 }
347 return buffer.getLong(index);
348 }
349
350 @Override
351 protected long _getLongLE(int index) {
352 VarHandle varHandle = PlatformDependent.longLeByteBufferView();
353 if (varHandle != null) {
354 return (long) varHandle.get(buffer, index);
355 }
356 return ByteBufUtil.swapLong(buffer.getLong(index));
357 }
358
359 @Override
360 public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
361 checkDstIndex(index, length, dstIndex, dst.capacity());
362 if (dst.hasArray()) {
363 getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
364 } else if (dst.nioBufferCount() > 0) {
365 for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
366 int bbLen = bb.remaining();
367 getBytes(index, bb);
368 index += bbLen;
369 }
370 } else {
371 dst.setBytes(dstIndex, this, index, length);
372 }
373 return this;
374 }
375
376 @Override
377 public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
378 getBytes(index, dst, dstIndex, length, false);
379 return this;
380 }
381
382 void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) {
383 checkDstIndex(index, length, dstIndex, dst.length);
384
385 ByteBuffer tmpBuf;
386 if (internal) {
387 tmpBuf = internalNioBuffer();
388 } else {
389 tmpBuf = buffer.duplicate();
390 }
391 tmpBuf.clear().position(index).limit(index + length);
392 tmpBuf.get(dst, dstIndex, length);
393 }
394
395 @Override
396 public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
397 checkReadableBytes(length);
398 getBytes(readerIndex, dst, dstIndex, length, true);
399 readerIndex += length;
400 return this;
401 }
402
403 @Override
404 public ByteBuf getBytes(int index, ByteBuffer dst) {
405 getBytes(index, dst, false);
406 return this;
407 }
408
409 void getBytes(int index, ByteBuffer dst, boolean internal) {
410 checkIndex(index, dst.remaining());
411
412 ByteBuffer tmpBuf;
413 if (internal) {
414 tmpBuf = internalNioBuffer();
415 } else {
416 tmpBuf = buffer.duplicate();
417 }
418 tmpBuf.clear().position(index).limit(index + dst.remaining());
419 dst.put(tmpBuf);
420 }
421
422 @Override
423 public ByteBuf readBytes(ByteBuffer dst) {
424 int length = dst.remaining();
425 checkReadableBytes(length);
426 getBytes(readerIndex, dst, true);
427 readerIndex += length;
428 return this;
429 }
430
431 @Override
432 public ByteBuf setByte(int index, int value) {
433 ensureAccessible();
434 _setByte(index, value);
435 return this;
436 }
437
438 @Override
439 protected void _setByte(int index, int value) {
440 buffer.put(index, (byte) value);
441 }
442
443 @Override
444 public ByteBuf setShortLE(int index, int value) {
445 ensureAccessible();
446 _setShortLE(index, value);
447 return this;
448 }
449
450 @Override
451 public ByteBuf setShort(int index, int value) {
452 ensureAccessible();
453 _setShort(index, value);
454 return this;
455 }
456
457 @Override
458 protected void _setShort(int index, int value) {
459 VarHandle varHandle = PlatformDependent.shortBeByteBufferView();
460 if (varHandle != null) {
461 varHandle.set(buffer, index, (short) value);
462 return;
463 }
464 buffer.putShort(index, (short) value);
465 }
466
467 @Override
468 protected void _setShortLE(int index, int value) {
469 VarHandle varHandle = PlatformDependent.shortLeByteBufferView();
470 if (varHandle != null) {
471 varHandle.set(buffer, index, (short) value);
472 return;
473 }
474 buffer.putShort(index, ByteBufUtil.swapShort((short) value));
475 }
476
477 @Override
478 public ByteBuf setMediumLE(int index, int value) {
479 ensureAccessible();
480 _setMediumLE(index, value);
481 return this;
482 }
483
484 @Override
485 public ByteBuf setMedium(int index, int value) {
486 ensureAccessible();
487 _setMedium(index, value);
488 return this;
489 }
490
491 @Override
492 protected void _setMedium(int index, int value) {
493 setByte(index, (byte) (value >>> 16));
494 setByte(index + 1, (byte) (value >>> 8));
495 setByte(index + 2, (byte) value);
496 }
497
498 @Override
499 protected void _setMediumLE(int index, int value) {
500 setByte(index, (byte) value);
501 setByte(index + 1, (byte) (value >>> 8));
502 setByte(index + 2, (byte) (value >>> 16));
503 }
504
505 @Override
506 public ByteBuf setIntLE(int index, int value) {
507 ensureAccessible();
508 _setIntLE(index, value);
509 return this;
510 }
511
512 @Override
513 public ByteBuf setInt(int index, int value) {
514 ensureAccessible();
515 _setInt(index, value);
516 return this;
517 }
518
519 @Override
520 protected void _setInt(int index, int value) {
521 VarHandle varHandle = PlatformDependent.intBeByteBufferView();
522 if (varHandle != null) {
523 varHandle.set(buffer, index, value);
524 return;
525 }
526 buffer.putInt(index, value);
527 }
528
529 @Override
530 protected void _setIntLE(int index, int value) {
531 VarHandle varHandle = PlatformDependent.intLeByteBufferView();
532 if (varHandle != null) {
533 varHandle.set(buffer, index, value);
534 return;
535 }
536 buffer.putInt(index, ByteBufUtil.swapInt(value));
537 }
538
539 @Override
540 public ByteBuf setLong(int index, long value) {
541 ensureAccessible();
542 _setLong(index, value);
543 return this;
544 }
545
546 @Override
547 public ByteBuf setLongLE(int index, long value) {
548 ensureAccessible();
549 _setLongLE(index, value);
550 return this;
551 }
552
553 @Override
554 protected void _setLong(int index, long value) {
555 VarHandle varHandle = PlatformDependent.longBeByteBufferView();
556 if (varHandle != null) {
557 varHandle.set(buffer, index, value);
558 return;
559 }
560 buffer.putLong(index, value);
561 }
562
563 @Override
564 protected void _setLongLE(int index, long value) {
565 VarHandle varHandle = PlatformDependent.longLeByteBufferView();
566 if (varHandle != null) {
567 varHandle.set(buffer, index, value);
568 return;
569 }
570 buffer.putLong(index, ByteBufUtil.swapLong(value));
571 }
572
573 @Override
574 public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
575 checkSrcIndex(index, length, srcIndex, src.capacity());
576 if (src.nioBufferCount() > 0) {
577 for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) {
578 int bbLen = bb.remaining();
579 setBytes(index, bb);
580 index += bbLen;
581 }
582 } else {
583 src.getBytes(srcIndex, this, index, length);
584 }
585 return this;
586 }
587
588 @Override
589 public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
590 checkSrcIndex(index, length, srcIndex, src.length);
591 ByteBuffer tmpBuf = internalNioBuffer();
592 tmpBuf.clear().position(index).limit(index + length);
593 tmpBuf.put(src, srcIndex, length);
594 return this;
595 }
596
597 @Override
598 public ByteBuf setBytes(int index, ByteBuffer src) {
599 ensureAccessible();
600 ByteBuffer tmpBuf = internalNioBuffer();
601 if (src == tmpBuf) {
602 src = src.duplicate();
603 }
604
605 tmpBuf.clear().position(index).limit(index + src.remaining());
606 tmpBuf.put(src);
607 return this;
608 }
609
610 @Override
611 public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
612 getBytes(index, out, length, false);
613 return this;
614 }
615
616 void getBytes(int index, OutputStream out, int length, boolean internal) throws IOException {
617 ensureAccessible();
618 if (length == 0) {
619 return;
620 }
621 ByteBufUtil.readBytes(alloc(), internal ? internalNioBuffer() : buffer.duplicate(), index, length, out);
622 }
623
624 @Override
625 public ByteBuf readBytes(OutputStream out, int length) throws IOException {
626 checkReadableBytes(length);
627 getBytes(readerIndex, out, length, true);
628 readerIndex += length;
629 return this;
630 }
631
632 @Override
633 public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
634 return getBytes(index, out, length, false);
635 }
636
637 private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
638 ensureAccessible();
639 if (length == 0) {
640 return 0;
641 }
642
643 ByteBuffer tmpBuf;
644 if (internal) {
645 tmpBuf = internalNioBuffer();
646 } else {
647 tmpBuf = buffer.duplicate();
648 }
649 tmpBuf.clear().position(index).limit(index + length);
650 return out.write(tmpBuf);
651 }
652
653 @Override
654 public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
655 return getBytes(index, out, position, length, false);
656 }
657
658 private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
659 ensureAccessible();
660 if (length == 0) {
661 return 0;
662 }
663
664 ByteBuffer tmpBuf = internal ? internalNioBuffer() : buffer.duplicate();
665 tmpBuf.clear().position(index).limit(index + length);
666 return out.write(tmpBuf, position);
667 }
668
669 @Override
670 public int readBytes(GatheringByteChannel out, int length) throws IOException {
671 checkReadableBytes(length);
672 int readBytes = getBytes(readerIndex, out, length, true);
673 readerIndex += readBytes;
674 return readBytes;
675 }
676
677 @Override
678 public int readBytes(FileChannel out, long position, int length) throws IOException {
679 checkReadableBytes(length);
680 int readBytes = getBytes(readerIndex, out, position, length, true);
681 readerIndex += readBytes;
682 return readBytes;
683 }
684
685 @Override
686 public int setBytes(int index, InputStream in, int length) throws IOException {
687 ensureAccessible();
688 if (buffer.hasArray()) {
689 return in.read(buffer.array(), buffer.arrayOffset() + index, length);
690 } else {
691 byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
692 int readBytes = in.read(tmp, 0, length);
693 if (readBytes <= 0) {
694 return readBytes;
695 }
696 ByteBuffer tmpBuf = internalNioBuffer();
697 tmpBuf.clear().position(index);
698 tmpBuf.put(tmp, 0, readBytes);
699 return readBytes;
700 }
701 }
702
703 @Override
704 public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
705 ensureAccessible();
706 ByteBuffer tmpBuf = internalNioBuffer();
707 tmpBuf.clear().position(index).limit(index + length);
708 try {
709 return in.read(tmpBuf);
710 } catch (ClosedChannelException ignored) {
711 return -1;
712 }
713 }
714
715 @Override
716 public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
717 ensureAccessible();
718 ByteBuffer tmpBuf = internalNioBuffer();
719 tmpBuf.clear().position(index).limit(index + length);
720 try {
721 return in.read(tmpBuf, position);
722 } catch (ClosedChannelException ignored) {
723 return -1;
724 }
725 }
726
727 @Override
728 public int nioBufferCount() {
729 return 1;
730 }
731
732 @Override
733 public ByteBuffer[] nioBuffers(int index, int length) {
734 return new ByteBuffer[] { nioBuffer(index, length) };
735 }
736
737 @Override
738 public final boolean isContiguous() {
739 return true;
740 }
741
742 @Override
743 public ByteBuf copy(int index, int length) {
744 ensureAccessible();
745 ByteBuffer src;
746 try {
747 src = (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length);
748 } catch (IllegalArgumentException ignored) {
749 throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
750 }
751
752 return alloc().directBuffer(length, maxCapacity()).writeBytes(src);
753 }
754
755 @Override
756 public ByteBuffer internalNioBuffer(int index, int length) {
757 checkIndex(index, length);
758 return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
759 }
760
761 private ByteBuffer internalNioBuffer() {
762 ByteBuffer tmpNioBuf = this.tmpNioBuf;
763 if (tmpNioBuf == null) {
764 this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
765 }
766 return tmpNioBuf;
767 }
768
769 @Override
770 public ByteBuffer nioBuffer(int index, int length) {
771 checkIndex(index, length);
772 return ((ByteBuffer) buffer.duplicate().position(index).limit(index + length)).slice();
773 }
774
775 @Override
776 protected void deallocate() {
777 ByteBuffer buffer = this.buffer;
778 if (buffer == null) {
779 return;
780 }
781
782 this.buffer = null;
783
784 if (!doNotFree) {
785 if (cleanable != null) {
786 cleanable.clean();
787 cleanable = null;
788 } else {
789 freeDirect(buffer);
790 }
791 }
792 }
793
794 @Override
795 public ByteBuf unwrap() {
796 return null;
797 }
798 }