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