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