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