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 return cleanable != null && cleanable.hasMemoryAddress();
234 }
235
236 @Override
237 public long memoryAddress() {
238 ensureAccessible();
239 if (!hasMemoryAddress()) {
240 throw new UnsupportedOperationException();
241 }
242 return cleanable.memoryAddress();
243 }
244
245 @Override
246 public byte getByte(int index) {
247 ensureAccessible();
248 return _getByte(index);
249 }
250
251 @Override
252 protected byte _getByte(int index) {
253 return buffer.get(index);
254 }
255
256 @Override
257 public short getShortLE(int index) {
258 ensureAccessible();
259 return _getShortLE(index);
260 }
261
262 @Override
263 public short getShort(int index) {
264 ensureAccessible();
265 return _getShort(index);
266 }
267
268 @Override
269 protected short _getShort(int index) {
270 if (PlatformDependent.hasVarHandle()) {
271 return VarHandleByteBufferAccess.getShortBE(buffer, index);
272 }
273 return buffer.getShort(index);
274 }
275
276 @Override
277 protected short _getShortLE(int index) {
278 if (PlatformDependent.hasVarHandle()) {
279 return VarHandleByteBufferAccess.getShortLE(buffer, index);
280 }
281 return ByteBufUtil.swapShort(buffer.getShort(index));
282 }
283
284 @Override
285 public int getUnsignedMedium(int index) {
286 ensureAccessible();
287 return _getUnsignedMedium(index);
288 }
289
290 @Override
291 protected int _getUnsignedMedium(int index) {
292 return (getByte(index) & 0xff) << 16 |
293 (getByte(index + 1) & 0xff) << 8 |
294 getByte(index + 2) & 0xff;
295 }
296
297 @Override
298 protected int _getUnsignedMediumLE(int index) {
299 return getByte(index) & 0xff |
300 (getByte(index + 1) & 0xff) << 8 |
301 (getByte(index + 2) & 0xff) << 16;
302 }
303
304 @Override
305 public int getIntLE(int index) {
306 ensureAccessible();
307 return _getIntLE(index);
308 }
309
310 @Override
311 public int getInt(int index) {
312 ensureAccessible();
313 return _getInt(index);
314 }
315
316 @Override
317 protected int _getInt(int index) {
318 if (PlatformDependent.hasVarHandle()) {
319 return VarHandleByteBufferAccess.getIntBE(buffer, index);
320 }
321 return buffer.getInt(index);
322 }
323
324 @Override
325 protected int _getIntLE(int index) {
326 if (PlatformDependent.hasVarHandle()) {
327 return VarHandleByteBufferAccess.getIntLE(buffer, index);
328 }
329 return ByteBufUtil.swapInt(buffer.getInt(index));
330 }
331
332 @Override
333 public long getLongLE(int index) {
334 ensureAccessible();
335 return _getLongLE(index);
336 }
337
338 @Override
339 public long getLong(int index) {
340 ensureAccessible();
341 return _getLong(index);
342 }
343
344 @Override
345 protected long _getLong(int index) {
346 if (PlatformDependent.hasVarHandle()) {
347 return VarHandleByteBufferAccess.getLongBE(buffer, index);
348 }
349 return buffer.getLong(index);
350 }
351
352 @Override
353 protected long _getLongLE(int index) {
354 if (PlatformDependent.hasVarHandle()) {
355 return VarHandleByteBufferAccess.getLongLE(buffer, index);
356 }
357 return ByteBufUtil.swapLong(buffer.getLong(index));
358 }
359
360 @Override
361 public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
362 checkDstIndex(index, length, dstIndex, dst.capacity());
363 if (dst.hasArray()) {
364 getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
365 } else if (dst.nioBufferCount() > 0) {
366 for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
367 int bbLen = bb.remaining();
368 getBytes(index, bb);
369 index += bbLen;
370 }
371 } else {
372 dst.setBytes(dstIndex, this, index, length);
373 }
374 return this;
375 }
376
377 @Override
378 public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
379 getBytes(index, dst, dstIndex, length, false);
380 return this;
381 }
382
383 void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) {
384 checkDstIndex(index, length, dstIndex, dst.length);
385
386 ByteBuffer tmpBuf;
387 if (internal) {
388 tmpBuf = internalNioBuffer(index, length);
389 } else {
390 tmpBuf = (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length);
391 }
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(index, dst.remaining());
415 } else {
416 tmpBuf = (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + dst.remaining());
417 }
418 dst.put(tmpBuf);
419 }
420
421 @Override
422 public ByteBuf readBytes(ByteBuffer dst) {
423 int length = dst.remaining();
424 checkReadableBytes(length);
425 getBytes(readerIndex, dst, true);
426 readerIndex += length;
427 return this;
428 }
429
430 @Override
431 public ByteBuf setByte(int index, int value) {
432 ensureAccessible();
433 _setByte(index, value);
434 return this;
435 }
436
437 @Override
438 protected void _setByte(int index, int value) {
439 buffer.put(index, (byte) (value & 0xFF));
440 }
441
442 @Override
443 public ByteBuf setShortLE(int index, int value) {
444 ensureAccessible();
445 _setShortLE(index, value);
446 return this;
447 }
448
449 @Override
450 public ByteBuf setShort(int index, int value) {
451 ensureAccessible();
452 _setShort(index, value);
453 return this;
454 }
455
456 @Override
457 protected void _setShort(int index, int value) {
458 if (PlatformDependent.hasVarHandle()) {
459 VarHandleByteBufferAccess.setShortBE(buffer, index, value);
460 return;
461 }
462 buffer.putShort(index, (short) (value & 0xFFFF));
463 }
464
465 @Override
466 protected void _setShortLE(int index, int value) {
467 if (PlatformDependent.hasVarHandle()) {
468 VarHandleByteBufferAccess.setShortLE(buffer, index, value);
469 return;
470 }
471 buffer.putShort(index, ByteBufUtil.swapShort((short) value));
472 }
473
474 @Override
475 public ByteBuf setMediumLE(int index, int value) {
476 ensureAccessible();
477 _setMediumLE(index, value);
478 return this;
479 }
480
481 @Override
482 public ByteBuf setMedium(int index, int value) {
483 ensureAccessible();
484 _setMedium(index, value);
485 return this;
486 }
487
488 @Override
489 protected void _setMedium(int index, int value) {
490 setByte(index, (byte) (value >>> 16));
491 setByte(index + 1, (byte) (value >>> 8));
492 setByte(index + 2, (byte) value);
493 }
494
495 @Override
496 protected void _setMediumLE(int index, int value) {
497 setByte(index, (byte) value);
498 setByte(index + 1, (byte) (value >>> 8));
499 setByte(index + 2, (byte) (value >>> 16));
500 }
501
502 @Override
503 public ByteBuf setIntLE(int index, int value) {
504 ensureAccessible();
505 _setIntLE(index, value);
506 return this;
507 }
508
509 @Override
510 public 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 if (PlatformDependent.hasVarHandle()) {
519 VarHandleByteBufferAccess.setIntBE(buffer, index, value);
520 return;
521 }
522 buffer.putInt(index, value);
523 }
524
525 @Override
526 protected void _setIntLE(int index, int value) {
527 if (PlatformDependent.hasVarHandle()) {
528 VarHandleByteBufferAccess.setIntLE(buffer, index, value);
529 return;
530 }
531 buffer.putInt(index, ByteBufUtil.swapInt(value));
532 }
533
534 @Override
535 public ByteBuf setLong(int index, long value) {
536 ensureAccessible();
537 _setLong(index, value);
538 return this;
539 }
540
541 @Override
542 public ByteBuf setLongLE(int index, long value) {
543 ensureAccessible();
544 _setLongLE(index, value);
545 return this;
546 }
547
548 @Override
549 protected void _setLong(int index, long value) {
550 if (PlatformDependent.hasVarHandle()) {
551 VarHandleByteBufferAccess.setLongBE(buffer, index, value);
552 return;
553 }
554 buffer.putLong(index, value);
555 }
556
557 @Override
558 protected void _setLongLE(int index, long value) {
559 if (PlatformDependent.hasVarHandle()) {
560 VarHandleByteBufferAccess.setLongLE(buffer, index, value);
561 return;
562 }
563 buffer.putLong(index, ByteBufUtil.swapLong(value));
564 }
565
566 @Override
567 public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
568 checkSrcIndex(index, length, srcIndex, src.capacity());
569 if (src.nioBufferCount() > 0) {
570 for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) {
571 int bbLen = bb.remaining();
572 setBytes(index, bb);
573 index += bbLen;
574 }
575 } else {
576 src.getBytes(srcIndex, this, index, length);
577 }
578 return this;
579 }
580
581 @Override
582 public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
583 checkSrcIndex(index, length, srcIndex, src.length);
584 ByteBuffer tmpBuf = internalNioBuffer(index, length);
585 tmpBuf.put(src, srcIndex, length);
586 return this;
587 }
588
589 @Override
590 public ByteBuf setBytes(int index, ByteBuffer src) {
591 ensureAccessible();
592 if (src == tmpNioBuf) {
593 src = src.duplicate();
594 }
595 ByteBuffer tmpBuf = internalNioBuffer(index, src.remaining());
596 tmpBuf.put(src);
597 return this;
598 }
599
600 @Override
601 public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
602 getBytes(index, out, length, false);
603 return this;
604 }
605
606 void getBytes(int index, OutputStream out, int length, boolean internal) throws IOException {
607 ensureAccessible();
608 if (length == 0) {
609 return;
610 }
611 ByteBufUtil.readBytes(alloc(), internal ? _internalNioBuffer() : buffer.duplicate(), index, length, out);
612 }
613
614 @Override
615 public ByteBuf readBytes(OutputStream out, int length) throws IOException {
616 checkReadableBytes(length);
617 getBytes(readerIndex, out, length, true);
618 readerIndex += length;
619 return this;
620 }
621
622 @Override
623 public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
624 return getBytes(index, out, length, false);
625 }
626
627 private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
628 ensureAccessible();
629 if (length == 0) {
630 return 0;
631 }
632
633 ByteBuffer tmpBuf;
634 if (internal) {
635 tmpBuf = internalNioBuffer(index, length);
636 } else {
637 tmpBuf = (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length);
638 }
639 return out.write(tmpBuf);
640 }
641
642 @Override
643 public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
644 return getBytes(index, out, position, length, false);
645 }
646
647 private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
648 ensureAccessible();
649 if (length == 0) {
650 return 0;
651 }
652
653 ByteBuffer tmpBuf = internal ? internalNioBuffer(index, length) :
654 (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length);
655 return out.write(tmpBuf, position);
656 }
657
658 @Override
659 public int readBytes(GatheringByteChannel out, int length) throws IOException {
660 checkReadableBytes(length);
661 int readBytes = getBytes(readerIndex, out, length, true);
662 readerIndex += readBytes;
663 return readBytes;
664 }
665
666 @Override
667 public int readBytes(FileChannel out, long position, int length) throws IOException {
668 checkReadableBytes(length);
669 int readBytes = getBytes(readerIndex, out, position, length, true);
670 readerIndex += readBytes;
671 return readBytes;
672 }
673
674 @Override
675 public int setBytes(int index, InputStream in, int length) throws IOException {
676 ensureAccessible();
677 if (buffer.hasArray()) {
678 return in.read(buffer.array(), buffer.arrayOffset() + index, length);
679 } else {
680 byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
681 int readBytes = in.read(tmp, 0, length);
682 if (readBytes <= 0) {
683 return readBytes;
684 }
685 ByteBuffer tmpBuf = internalNioBuffer(index, readBytes);
686 tmpBuf.put(tmp, 0, readBytes);
687 return readBytes;
688 }
689 }
690
691 @Override
692 public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
693 ensureAccessible();
694 ByteBuffer tmpBuf = internalNioBuffer(index, length);
695 try {
696 return in.read(tmpBuf);
697 } catch (ClosedChannelException ignored) {
698 return -1;
699 }
700 }
701
702 @Override
703 public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
704 ensureAccessible();
705 ByteBuffer tmpBuf = internalNioBuffer(index, length);
706 try {
707 return in.read(tmpBuf, position);
708 } catch (ClosedChannelException ignored) {
709 return -1;
710 }
711 }
712
713 @Override
714 public int nioBufferCount() {
715 return 1;
716 }
717
718 @Override
719 public ByteBuffer[] nioBuffers(int index, int length) {
720 return new ByteBuffer[] { nioBuffer(index, length) };
721 }
722
723 @Override
724 public final boolean isContiguous() {
725 return true;
726 }
727
728 @Override
729 public ByteBuf copy(int index, int length) {
730 ensureAccessible();
731 ByteBuffer src;
732 try {
733 src = (ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length);
734 } catch (IllegalArgumentException ignored) {
735 throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
736 }
737
738 return alloc().directBuffer(length, maxCapacity()).writeBytes(src);
739 }
740
741 @Override
742 public ByteBuffer internalNioBuffer(int index, int length) {
743 checkIndex(index, length);
744 return (ByteBuffer) _internalNioBuffer().clear().position(index).limit(index + length);
745 }
746
747 @Override
748 ByteBuffer _internalNioBuffer() {
749 ByteBuffer tmpNioBuf = this.tmpNioBuf;
750 if (tmpNioBuf == null) {
751 this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
752 }
753 return tmpNioBuf;
754 }
755
756 @Override
757 public ByteBuffer nioBuffer(int index, int length) {
758 checkIndex(index, length);
759 return PlatformDependent.offsetSlice(buffer, index, length);
760 }
761
762 @Override
763 protected void deallocate() {
764 ByteBuffer buffer = this.buffer;
765 if (buffer == null) {
766 return;
767 }
768
769 this.buffer = null;
770
771 if (!doNotFree) {
772 if (cleanable != null) {
773 cleanable.clean();
774 cleanable = null;
775 } else {
776 freeDirect(buffer);
777 }
778 }
779 }
780
781 @Override
782 public ByteBuf unwrap() {
783 return null;
784 }
785 }