Share code between Unsafe ByteBuf implementations

Motiviation:

We have a lot of duplicated code which makes it hard to maintain.

Modification:

Move shared code to UnsafeByteBufUtil and use it in the implementations.

Result:

Less duplicated code and so easier to maintain.
This commit is contained in:
Norman Maurer 2015-10-21 10:04:49 +02:00
parent 992f8db0b4
commit 2be4bb74a5
5 changed files with 160 additions and 217 deletions

View File

@ -1132,7 +1132,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
} }
} }
private static boolean isInvalid(int index, int length, int capacity) { static boolean isInvalid(int index, int length, int capacity) {
return (index | length | (index + length) | (capacity - (index + length))) < 0; return (index | length | (index + length) | (capacity - (index + length))) < 0;
} }

View File

@ -101,59 +101,19 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override @Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
checkIndex(index, length); UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
if (dst == null) {
throw new NullPointerException("dst");
}
if (dstIndex < 0 || dstIndex > dst.capacity() - length) {
throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
}
if (length != 0) {
if (dst.hasMemoryAddress()) {
PlatformDependent.copyMemory(addr(index), dst.memoryAddress() + dstIndex, length);
} else if (dst.hasArray()) {
PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dstIndex, length);
} else {
dst.setBytes(dstIndex, this, index, length);
}
}
return this; return this;
} }
@Override @Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, length); UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
if (dst == null) {
throw new NullPointerException("dst");
}
if (dstIndex < 0 || dstIndex > dst.length - length) {
throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
}
if (length != 0) {
PlatformDependent.copyMemory(addr(index), dst, dstIndex, length);
}
return this; return this;
} }
@Override @Override
public ByteBuf getBytes(int index, ByteBuffer dst) { public ByteBuf getBytes(int index, ByteBuffer dst) {
checkIndex(index); UnsafeByteBufUtil.getBytes(this, addr(index), index, dst);
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
if (bytesToCopy == 0) {
return this;
}
if (dst.isDirect()) {
// Copy to direct memory
long dstAddress = PlatformDependent.directBufferAddress(dst);
PlatformDependent.copyMemory(addr(index), dstAddress + dst.position(), bytesToCopy);
} else {
// Copy to array
PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dst.position(), bytesToCopy);
}
dst.position(dst.position() + bytesToCopy);
return this; return this;
} }
@ -168,12 +128,7 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override @Override
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
checkIndex(index, length); UnsafeByteBufUtil.getBytes(this, addr(index), index, out, length);
if (length != 0) {
byte[] tmp = new byte[length];
PlatformDependent.copyMemory(addr(index), tmp, 0, length);
out.write(tmp);
}
return this; return this;
} }
@ -235,65 +190,25 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override @Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
checkIndex(index, length); UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
if (src == null) {
throw new NullPointerException("src");
}
if (srcIndex < 0 || srcIndex > src.capacity() - length) {
throw new IndexOutOfBoundsException("srcIndex: " + srcIndex);
}
if (length != 0) {
if (src.hasMemoryAddress()) {
PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr(index), length);
} else if (src.hasArray()) {
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr(index), length);
} else {
src.getBytes(srcIndex, this, index, length);
}
}
return this; return this;
} }
@Override @Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
checkIndex(index, length); UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
if (length != 0) {
PlatformDependent.copyMemory(src, srcIndex, addr(index), length);
}
return this; return this;
} }
@Override @Override
public ByteBuf setBytes(int index, ByteBuffer src) { public ByteBuf setBytes(int index, ByteBuffer src) {
checkIndex(index, src.remaining()); UnsafeByteBufUtil.setBytes(this, addr(index), index, src);
int length = src.remaining();
if (length == 0) {
return this;
}
if (src.isDirect()) {
// Copy from direct memory
long srcAddress = PlatformDependent.directBufferAddress(src);
PlatformDependent.copyMemory(srcAddress + src.position(), addr(index), src.remaining());
} else {
// Copy from array
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr(index), length);
}
src.position(src.position() + length);
return this; return this;
} }
@Override @Override
public int setBytes(int index, InputStream in, int length) throws IOException { public int setBytes(int index, InputStream in, int length) throws IOException {
checkIndex(index, length); return UnsafeByteBufUtil.setBytes(this, addr(index), index, in, length);
byte[] tmp = new byte[length];
int readBytes = in.read(tmp);
if (readBytes > 0) {
PlatformDependent.copyMemory(tmp, 0, addr(index), readBytes);
}
return readBytes;
} }
@Override @Override
@ -311,17 +226,7 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override @Override
public ByteBuf copy(int index, int length) { public ByteBuf copy(int index, int length) {
checkIndex(index, length); return UnsafeByteBufUtil.copy(this, addr(index), index, length);
ByteBuf copy = alloc().directBuffer(length, maxCapacity());
if (length != 0) {
if (copy.hasMemoryAddress()) {
PlatformDependent.copyMemory(addr(index), copy.memoryAddress(), length);
copy.setIndex(0, length);
} else {
copy.writeBytes(this, index, length);
}
}
return copy;
} }
@Override @Override

View File

@ -291,11 +291,6 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
private void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) { private void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) {
checkDstIndex(index, length, dstIndex, dst.length); checkDstIndex(index, length, dstIndex, dst.length);
if (dstIndex < 0 || dstIndex > dst.length - length) {
throw new IndexOutOfBoundsException(String.format(
"dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length));
}
ByteBuffer tmpBuf; ByteBuffer tmpBuf;
if (internal) { if (internal) {
tmpBuf = internalNioBuffer(); tmpBuf = internalNioBuffer();

View File

@ -240,63 +240,19 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
@Override @Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
checkIndex(index, length); UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
if (dst == null) {
throw new NullPointerException("dst");
}
if (dstIndex < 0 || dstIndex > dst.capacity() - length) {
throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
}
if (dst.hasMemoryAddress()) {
PlatformDependent.copyMemory(addr(index), dst.memoryAddress() + dstIndex, length);
} else if (dst.hasArray()) {
PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dstIndex, length);
} else {
dst.setBytes(dstIndex, this, index, length);
}
return this; return this;
} }
@Override @Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, length); UnsafeByteBufUtil.getBytes(this, addr(index), index, dst, dstIndex, length);
if (dst == null) {
throw new NullPointerException("dst");
}
if (dstIndex < 0 || dstIndex > dst.length - length) {
throw new IndexOutOfBoundsException(String.format(
"dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length));
}
if (length != 0) {
PlatformDependent.copyMemory(addr(index), dst, dstIndex, length);
}
return this; return this;
} }
@Override @Override
public ByteBuf getBytes(int index, ByteBuffer dst) { public ByteBuf getBytes(int index, ByteBuffer dst) {
checkIndex(index); UnsafeByteBufUtil.getBytes(this, addr(index), index, dst);
if (dst == null) {
throw new NullPointerException("dst");
}
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
if (bytesToCopy == 0) {
return this;
}
if (dst.isDirect()) {
// Copy to direct memory
long dstAddress = PlatformDependent.directBufferAddress(dst);
PlatformDependent.copyMemory(addr(index), dstAddress + dst.position(), bytesToCopy);
} else {
// Copy to array
PlatformDependent.copyMemory(addr(index), dst.array(), dst.arrayOffset() + dst.position(), bytesToCopy);
}
dst.position(dst.position() + bytesToCopy);
return this; return this;
} }
@ -336,63 +292,25 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
@Override @Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
checkIndex(index, length); UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
if (src == null) {
throw new NullPointerException("src");
}
if (srcIndex < 0 || srcIndex > src.capacity() - length) {
throw new IndexOutOfBoundsException("srcIndex: " + srcIndex);
}
if (length != 0) {
if (src.hasMemoryAddress()) {
PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr(index), length);
} else if (src.hasArray()) {
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr(index), length);
} else {
src.getBytes(srcIndex, this, index, length);
}
}
return this; return this;
} }
@Override @Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
checkIndex(index, length); UnsafeByteBufUtil.setBytes(this, addr(index), index, src, srcIndex, length);
if (length != 0) {
PlatformDependent.copyMemory(src, srcIndex, addr(index), length);
}
return this; return this;
} }
@Override @Override
public ByteBuf setBytes(int index, ByteBuffer src) { public ByteBuf setBytes(int index, ByteBuffer src) {
ensureAccessible(); UnsafeByteBufUtil.setBytes(this, addr(index), index, src);
int length = src.remaining();
if (length == 0) {
return this;
}
if (src.isDirect()) {
// Copy from direct memory
long srcAddress = PlatformDependent.directBufferAddress(src);
PlatformDependent.copyMemory(srcAddress + src.position(), addr(index), src.remaining());
} else {
// Copy from array
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr(index), length);
}
src.position(src.position() + length);
return this; return this;
} }
@Override @Override
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
ensureAccessible(); UnsafeByteBufUtil.getBytes(this, addr(index), index, out, length);
if (length != 0) {
byte[] tmp = new byte[length];
PlatformDependent.copyMemory(addr(index), tmp, 0, length);
out.write(tmp);
}
return this; return this;
} }
@ -427,13 +345,7 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
@Override @Override
public int setBytes(int index, InputStream in, int length) throws IOException { public int setBytes(int index, InputStream in, int length) throws IOException {
checkIndex(index, length); return UnsafeByteBufUtil.setBytes(this, addr(index), index, in, length);
byte[] tmp = new byte[length];
int readBytes = in.read(tmp);
if (readBytes > 0) {
PlatformDependent.copyMemory(tmp, 0, addr(index), readBytes);
}
return readBytes;
} }
@Override @Override
@ -460,17 +372,7 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
@Override @Override
public ByteBuf copy(int index, int length) { public ByteBuf copy(int index, int length) {
checkIndex(index, length); return UnsafeByteBufUtil.copy(this, addr(index), index, length);
ByteBuf copy = alloc().directBuffer(length, maxCapacity());
if (length != 0) {
if (copy.hasMemoryAddress()) {
PlatformDependent.copyMemory(addr(index), copy.memoryAddress(), length);
copy.setIndex(0, length);
} else {
copy.writeBytes(this, index, length);
}
}
return copy;
} }
@Override @Override

View File

@ -17,8 +17,14 @@ package io.netty.buffer;
import io.netty.util.internal.PlatformDependent; 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 java.nio.ByteOrder;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
/** /**
* All operations get and set as {@link ByteOrder#BIG_ENDIAN}. * All operations get and set as {@link ByteOrder#BIG_ENDIAN}.
*/ */
@ -243,5 +249,140 @@ final class UnsafeByteBufUtil {
} }
} }
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 (AbstractByteBuf.isInvalid(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 (AbstractByteBuf.isInvalid(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 (AbstractByteBuf.isInvalid(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());
} else {
// Copy from array
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr, length);
}
src.position(src.position() + length);
}
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() { } private UnsafeByteBufUtil() { }
} }