netty5/buffer/src/main/java/io/netty/buffer/UnsafeByteBufUtil.java

599 lines
26 KiB
Java
Raw Normal View History

/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.buffer;
import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import static io.netty.util.internal.MathUtil.isOutOfBounds;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static io.netty.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER;
/**
* All operations get and set as {@link ByteOrder#BIG_ENDIAN}.
*/
final class UnsafeByteBufUtil {
private static final boolean UNALIGNED = PlatformDependent.isUnaligned();
static byte getByte(long address) {
return PlatformDependent.getByte(address);
}
static short getShort(long address) {
if (UNALIGNED) {
short v = PlatformDependent.getShort(address);
return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
}
return (short) (PlatformDependent.getByte(address) << 8 | PlatformDependent.getByte(address + 1) & 0xff);
}
static short getShortLE(long address) {
if (UNALIGNED) {
short v = PlatformDependent.getShort(address);
return BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(v) : v;
}
return (short) (PlatformDependent.getByte(address) & 0xff | PlatformDependent.getByte(address + 1) << 8);
}
static int getUnsignedMedium(long address) {
if (UNALIGNED) {
if (BIG_ENDIAN_NATIVE_ORDER) {
return (PlatformDependent.getByte(address) & 0xff) |
(PlatformDependent.getShort(address + 1) & 0xffff) << 8;
}
return (Short.reverseBytes(PlatformDependent.getShort(address)) & 0xffff) << 8 |
PlatformDependent.getByte(address + 2) & 0xff;
}
return (PlatformDependent.getByte(address) & 0xff) << 16 |
(PlatformDependent.getByte(address + 1) & 0xff) << 8 |
PlatformDependent.getByte(address + 2) & 0xff;
}
static int getUnsignedMediumLE(long address) {
if (UNALIGNED) {
if (BIG_ENDIAN_NATIVE_ORDER) {
return (Short.reverseBytes(PlatformDependent.getShort(address)) & 0xffff) << 8 |
PlatformDependent.getByte(address + 2) & 0xff;
}
return (PlatformDependent.getByte(address) & 0xff) |
(PlatformDependent.getShort(address + 1) & 0xffff) << 8;
}
return PlatformDependent.getByte(address) & 0xff |
(PlatformDependent.getByte(address + 1) & 0xff) << 8 |
(PlatformDependent.getByte(address + 1) & 0xff) << 16 ;
}
static int getInt(long address) {
if (UNALIGNED) {
int v = PlatformDependent.getInt(address);
return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
}
return PlatformDependent.getByte(address) << 24 |
(PlatformDependent.getByte(address + 1) & 0xff) << 16 |
(PlatformDependent.getByte(address + 2) & 0xff) << 8 |
PlatformDependent.getByte(address + 3) & 0xff;
}
static int getIntLE(long address) {
if (UNALIGNED) {
int v = PlatformDependent.getInt(address);
return BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(v) : v;
}
return PlatformDependent.getByte(address) & 0xff |
(PlatformDependent.getByte(address + 1) & 0xff) << 8 |
(PlatformDependent.getByte(address + 2) & 0xff) << 16 |
PlatformDependent.getByte(address + 3) << 24;
}
static long getLong(long address) {
if (UNALIGNED) {
long v = PlatformDependent.getLong(address);
return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
}
return (long) PlatformDependent.getByte(address) << 56 |
((long) PlatformDependent.getByte(address + 1) & 0xff) << 48 |
((long) PlatformDependent.getByte(address + 2) & 0xff) << 40 |
((long) PlatformDependent.getByte(address + 3) & 0xff) << 32 |
((long) PlatformDependent.getByte(address + 4) & 0xff) << 24 |
((long) PlatformDependent.getByte(address + 5) & 0xff) << 16 |
((long) PlatformDependent.getByte(address + 6) & 0xff) << 8 |
(long) PlatformDependent.getByte(address + 7) & 0xff;
}
static long getLongLE(long address) {
if (UNALIGNED) {
long v = PlatformDependent.getLong(address);
return BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(v) : v;
}
return (long) PlatformDependent.getByte(address) & 0xff |
((long) PlatformDependent.getByte(address + 1) & 0xff) << 8 |
((long) PlatformDependent.getByte(address + 2) & 0xff) << 16 |
((long) PlatformDependent.getByte(address + 3) & 0xff) << 24 |
((long) PlatformDependent.getByte(address + 4) & 0xff) << 32 |
((long) PlatformDependent.getByte(address + 5) & 0xff) << 40 |
((long) PlatformDependent.getByte(address + 6) & 0xff) << 48 |
(long) PlatformDependent.getByte(address + 7) << 56;
}
static void setByte(long address, int value) {
PlatformDependent.putByte(address, (byte) value);
}
static void setShort(long address, int value) {
if (UNALIGNED) {
PlatformDependent.putShort(
address, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
} else {
PlatformDependent.putByte(address, (byte) (value >>> 8));
PlatformDependent.putByte(address + 1, (byte) value);
}
}
static void setShortLE(long address, int value) {
if (UNALIGNED) {
PlatformDependent.putShort(
address, BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) value) : (short) value);
} else {
PlatformDependent.putByte(address, (byte) value);
PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
}
}
static void setMedium(long address, int value) {
if (UNALIGNED) {
if (BIG_ENDIAN_NATIVE_ORDER) {
PlatformDependent.putByte(address, (byte) value);
PlatformDependent.putShort(address + 1, (short) (value >>> 8));
} else {
PlatformDependent.putShort(address, Short.reverseBytes((short) (value >>> 8)));
PlatformDependent.putByte(address + 2, (byte) value);
}
} else {
PlatformDependent.putByte(address, (byte) (value >>> 16));
PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
PlatformDependent.putByte(address + 2, (byte) value);
}
}
static void setMediumLE(long address, int value) {
if (UNALIGNED) {
if (BIG_ENDIAN_NATIVE_ORDER) {
PlatformDependent.putShort(address, Short.reverseBytes((short) (value >>> 8)));
PlatformDependent.putByte(address + 2, (byte) value);
} else {
PlatformDependent.putByte(address, (byte) value);
PlatformDependent.putShort(address + 1, (short) (value >>> 8));
}
} else {
PlatformDependent.putByte(address, (byte) value);
PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
}
}
static void setInt(long address, int value) {
if (UNALIGNED) {
PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
} else {
PlatformDependent.putByte(address, (byte) (value >>> 24));
PlatformDependent.putByte(address + 1, (byte) (value >>> 16));
PlatformDependent.putByte(address + 2, (byte) (value >>> 8));
PlatformDependent.putByte(address + 3, (byte) value);
}
}
static void setIntLE(long address, int value) {
if (UNALIGNED) {
PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(value) : value);
} else {
PlatformDependent.putByte(address, (byte) value);
PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
PlatformDependent.putByte(address + 3, (byte) (value >>> 24));
}
}
static void setLong(long address, long value) {
if (UNALIGNED) {
PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
} else {
PlatformDependent.putByte(address, (byte) (value >>> 56));
PlatformDependent.putByte(address + 1, (byte) (value >>> 48));
PlatformDependent.putByte(address + 2, (byte) (value >>> 40));
PlatformDependent.putByte(address + 3, (byte) (value >>> 32));
PlatformDependent.putByte(address + 4, (byte) (value >>> 24));
PlatformDependent.putByte(address + 5, (byte) (value >>> 16));
PlatformDependent.putByte(address + 6, (byte) (value >>> 8));
PlatformDependent.putByte(address + 7, (byte) value);
}
}
static void setLongLE(long address, long value) {
if (UNALIGNED) {
PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(value) : value);
} else {
PlatformDependent.putByte(address, (byte) value);
PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
PlatformDependent.putByte(address + 3, (byte) (value >>> 24));
PlatformDependent.putByte(address + 4, (byte) (value >>> 32));
PlatformDependent.putByte(address + 5, (byte) (value >>> 40));
PlatformDependent.putByte(address + 6, (byte) (value >>> 48));
PlatformDependent.putByte(address + 7, (byte) (value >>> 56));
}
}
static byte getByte(byte[] array, int index) {
return PlatformDependent.getByte(array, index);
}
static short getShort(byte[] array, int index) {
if (UNALIGNED) {
short v = PlatformDependent.getShort(array, index);
return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
}
return (short) (PlatformDependent.getByte(index) << 8 | PlatformDependent.getByte(index + 1) & 0xff);
}
static short getShortLE(byte[] array, int index) {
if (UNALIGNED) {
short v = PlatformDependent.getShort(array, index);
return BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(v) : v;
}
return (short) (PlatformDependent.getByte(index) & 0xff | PlatformDependent.getByte(index + 1) << 8);
}
static int getUnsignedMedium(byte[] array, int index) {
if (UNALIGNED) {
if (BIG_ENDIAN_NATIVE_ORDER) {
return (PlatformDependent.getByte(array, index) & 0xff) |
(PlatformDependent.getShort(array, index + 1) & 0xffff) << 8;
}
return (Short.reverseBytes(PlatformDependent.getShort(array, index)) & 0xffff) << 8 |
PlatformDependent.getByte(array, index + 2) & 0xff;
}
return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
(PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
PlatformDependent.getByte(array, index + 2) & 0xff;
}
static int getUnsignedMediumLE(byte[] array, int index) {
if (UNALIGNED) {
if (BIG_ENDIAN_NATIVE_ORDER) {
return (Short.reverseBytes(PlatformDependent.getShort(array, index)) & 0xffff) << 8 |
PlatformDependent.getByte(array, index + 2) & 0xff;
}
return (PlatformDependent.getByte(array, index) & 0xff) |
(PlatformDependent.getShort(array, index + 1) & 0xffff) << 8;
}
return PlatformDependent.getByte(array, index) & 0xff |
(PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
(PlatformDependent.getByte(array, index + 2) & 0xff) << 16;
}
static int getInt(byte[] array, int index) {
if (UNALIGNED) {
int v = PlatformDependent.getInt(array, index);
return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
}
return PlatformDependent.getByte(array, index) << 24 |
(PlatformDependent.getByte(array, index + 1) & 0xff) << 16 |
(PlatformDependent.getByte(array, index + 2) & 0xff) << 8 |
PlatformDependent.getByte(array, index + 3) & 0xff;
}
static int getIntLE(byte[] array, int index) {
if (UNALIGNED) {
int v = PlatformDependent.getInt(array, index);
return BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(v) : v;
}
return PlatformDependent.getByte(array, index) & 0xff |
(PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
(PlatformDependent.getByte(array, index + 2) & 0xff) << 16 |
PlatformDependent.getByte(array, index + 3) << 24;
}
static long getLong(byte[] array, int index) {
if (UNALIGNED) {
long v = PlatformDependent.getLong(array, index);
return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
}
return (long) PlatformDependent.getByte(array, index) << 56 |
((long) PlatformDependent.getByte(array, index + 1) & 0xff) << 48 |
((long) PlatformDependent.getByte(array, index + 2) & 0xff) << 40 |
((long) PlatformDependent.getByte(array, index + 3) & 0xff) << 32 |
((long) PlatformDependent.getByte(array, index + 4) & 0xff) << 24 |
((long) PlatformDependent.getByte(array, index + 5) & 0xff) << 16 |
((long) PlatformDependent.getByte(array, index + 6) & 0xff) << 8 |
(long) PlatformDependent.getByte(array, index + 7) & 0xff;
}
static long getLongLE(byte[] array, int index) {
if (UNALIGNED) {
long v = PlatformDependent.getLong(array, index);
return BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(v) : v;
}
return (long) PlatformDependent.getByte(array, index) & 0xff |
((long) PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
((long) PlatformDependent.getByte(array, index + 2) & 0xff) << 16 |
((long) PlatformDependent.getByte(array, index + 3) & 0xff) << 24 |
((long) PlatformDependent.getByte(array, index + 4) & 0xff) << 32 |
((long) PlatformDependent.getByte(array, index + 5) & 0xff) << 40 |
((long) PlatformDependent.getByte(array, index + 6) & 0xff) << 48 |
(long) PlatformDependent.getByte(array, index + 7) << 56;
}
static void setByte(byte[] array, int index, int value) {
PlatformDependent.putByte(array, index, (byte) value);
}
static void setShort(byte[] array, int index, int value) {
if (UNALIGNED) {
PlatformDependent.putShort(
array, index, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
} else {
PlatformDependent.putByte(array, index, (byte) (value >>> 8));
PlatformDependent.putByte(array, index + 1, (byte) value);
}
}
static void setShortLE(byte[] array, int index, int value) {
if (UNALIGNED) {
PlatformDependent.putShort(
array, index, BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) value) : (short) value);
} else {
PlatformDependent.putByte(array, index, (byte) value);
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
}
}
static void setMedium(byte[] array, int index, int value) {
if (UNALIGNED) {
if (BIG_ENDIAN_NATIVE_ORDER) {
PlatformDependent.putByte(array, index, (byte) value);
PlatformDependent.putShort(array, index + 1, (short) (value >>> 8));
} else {
PlatformDependent.putShort(array, index, Short.reverseBytes((short) (value >>> 8)));
PlatformDependent.putByte(array, index + 2, (byte) value);
}
} else {
PlatformDependent.putByte(array, index, (byte) (value >>> 16));
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
PlatformDependent.putByte(array, index + 2, (byte) value);
}
}
static void setMediumLE(byte[] array, int index, int value) {
if (UNALIGNED) {
if (BIG_ENDIAN_NATIVE_ORDER) {
PlatformDependent.putShort(array, index, Short.reverseBytes((short) (value >>> 8)));
PlatformDependent.putByte(array, index + 2, (byte) value);
} else {
PlatformDependent.putByte(array, index, (byte) value);
PlatformDependent.putShort(array, index + 1, (short) (value >>> 8));
}
} else {
PlatformDependent.putByte(array, index, (byte) value);
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
}
}
static void setInt(byte[] array, int index, int value) {
if (UNALIGNED) {
PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
} else {
PlatformDependent.putByte(array, index, (byte) (value >>> 24));
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 16));
PlatformDependent.putByte(array, index + 2, (byte) (value >>> 8));
PlatformDependent.putByte(array, index + 3, (byte) value);
}
}
static void setIntLE(byte[] array, int index, int value) {
if (UNALIGNED) {
PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(value) : value);
} else {
PlatformDependent.putByte(array, index, (byte) value);
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
PlatformDependent.putByte(array, index + 3, (byte) (value >>> 24));
}
}
static void setLong(byte[] array, int index, long value) {
if (UNALIGNED) {
PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
} else {
PlatformDependent.putByte(array, index, (byte) (value >>> 56));
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 48));
PlatformDependent.putByte(array, index + 2, (byte) (value >>> 40));
PlatformDependent.putByte(array, index + 3, (byte) (value >>> 32));
PlatformDependent.putByte(array, index + 4, (byte) (value >>> 24));
PlatformDependent.putByte(array, index + 5, (byte) (value >>> 16));
PlatformDependent.putByte(array, index + 6, (byte) (value >>> 8));
PlatformDependent.putByte(array, index + 7, (byte) value);
}
}
static void setLongLE(byte[] array, int index, long value) {
if (UNALIGNED) {
PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(value) : value);
} else {
PlatformDependent.putByte(array, index, (byte) value);
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
PlatformDependent.putByte(array, index + 3, (byte) (value >>> 24));
PlatformDependent.putByte(array, index + 4, (byte) (value >>> 32));
PlatformDependent.putByte(array, index + 5, (byte) (value >>> 40));
PlatformDependent.putByte(array, index + 6, (byte) (value >>> 48));
PlatformDependent.putByte(array, index + 7, (byte) (value >>> 56));
}
}
static ByteBuf copy(AbstractByteBuf buf, long addr, int index, int length) {
buf.checkIndex(index, length);
ByteBuf copy = buf.alloc().directBuffer(length, buf.maxCapacity());
if (length != 0) {
if (copy.hasMemoryAddress()) {
PlatformDependent.copyMemory(addr, copy.memoryAddress(), length);
copy.setIndex(0, length);
} else {
copy.writeBytes(buf, index, length);
}
}
return copy;
}
static int setBytes(AbstractByteBuf buf, long addr, int index, InputStream in, int length) throws IOException {
buf.checkIndex(index, length);
ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
try {
byte[] tmp = tmpBuf.array();
int offset = tmpBuf.arrayOffset();
int readBytes = in.read(tmp, offset, length);
if (readBytes > 0) {
PlatformDependent.copyMemory(tmp, offset, addr, readBytes);
}
return readBytes;
} finally {
tmpBuf.release();
}
}
static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuf dst, int dstIndex, int length) {
buf.checkIndex(index, length);
checkNotNull(dst, "dst");
if (isOutOfBounds(dstIndex, length, dst.capacity())) {
throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
}
if (dst.hasMemoryAddress()) {
PlatformDependent.copyMemory(addr, dst.memoryAddress() + dstIndex, length);
} else if (dst.hasArray()) {
PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dstIndex, length);
} else {
dst.setBytes(dstIndex, buf, index, length);
}
}
static void getBytes(AbstractByteBuf buf, long addr, int index, byte[] dst, int dstIndex, int length) {
buf.checkIndex(index, length);
checkNotNull(dst, "dst");
if (isOutOfBounds(dstIndex, length, dst.length)) {
throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
}
if (length != 0) {
PlatformDependent.copyMemory(addr, dst, dstIndex, length);
}
}
static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer dst) {
buf.checkIndex(index);
int bytesToCopy = Math.min(buf.capacity() - index, dst.remaining());
if (bytesToCopy == 0) {
return;
}
if (dst.isDirect()) {
// Copy to direct memory
long dstAddress = PlatformDependent.directBufferAddress(dst);
PlatformDependent.copyMemory(addr, dstAddress + dst.position(), bytesToCopy);
} else {
// Copy to array
PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dst.position(), bytesToCopy);
}
dst.position(dst.position() + bytesToCopy);
}
static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuf src, int srcIndex, int length) {
buf.checkIndex(index, length);
checkNotNull(src, "src");
if (isOutOfBounds(srcIndex, length, src.capacity())) {
throw new IndexOutOfBoundsException("srcIndex: " + srcIndex);
}
if (length != 0) {
if (src.hasMemoryAddress()) {
PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr, length);
} else if (src.hasArray()) {
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr, length);
} else {
src.getBytes(srcIndex, buf, index, length);
}
}
}
static void setBytes(AbstractByteBuf buf, long addr, int index, byte[] src, int srcIndex, int length) {
buf.checkIndex(index, length);
if (length != 0) {
PlatformDependent.copyMemory(src, srcIndex, addr, length);
}
}
static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer src) {
buf.checkIndex(index, src.remaining());
int length = src.remaining();
if (length == 0) {
return;
}
if (src.isDirect()) {
// Copy from direct memory
long srcAddress = PlatformDependent.directBufferAddress(src);
PlatformDependent.copyMemory(srcAddress + src.position(), addr, src.remaining());
src.position(src.position() + length);
} else if (src.hasArray()) {
// Copy from array
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr, length);
src.position(src.position() + length);
} else {
ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
try {
byte[] tmp = tmpBuf.array();
src.get(tmp, tmpBuf.arrayOffset(), length); // moves the src position too
PlatformDependent.copyMemory(tmp, 0, addr, length);
} finally {
tmpBuf.release();
}
}
}
static void getBytes(AbstractByteBuf buf, long addr, int index, OutputStream out, int length) throws IOException {
buf.checkIndex(index, length);
if (length != 0) {
ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
try {
byte[] tmp = tmpBuf.array();
int offset = tmpBuf.arrayOffset();
PlatformDependent.copyMemory(addr, tmp, offset, length);
out.write(tmp, offset, length);
} finally {
tmpBuf.release();
}
}
}
private UnsafeByteBufUtil() { }
}