Fix infinite recursion when transferring data between different type of buffers / Add ByteBuf.hasMemoryAddress/memoryAddress()

- Fixes: #1109 and #1110
This commit is contained in:
Trustin Lee 2013-03-06 18:22:16 +09:00
parent 3d6d9f394d
commit 88df53ec1a
19 changed files with 486 additions and 192 deletions

View File

@ -440,15 +440,6 @@ public abstract class AbstractByteBuf implements ByteBuf {
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int length) {
checkIndex(index, length);
if (dst == null) {
throw new NullPointerException("dst");
}
if (length > dst.writableBytes()) {
throw new IndexOutOfBoundsException(String.format(
"length(%d) exceeds dst.writableBytes(%d) where dst is: %s", length, dst.writableBytes(), dst));
}
getBytes(index, dst, dst.writerIndex(), length);
dst.writerIndex(dst.writerIndex() + length);
return this;
@ -1102,6 +1093,22 @@ public abstract class AbstractByteBuf implements ByteBuf {
}
}
protected final void checkSrcIndex(int index, int length, int srcIndex, int srcCapacity) {
checkIndex(index, length);
if (srcIndex < 0 || srcIndex > srcCapacity - length) {
throw new IndexOutOfBoundsException(String.format(
"srcIndex: %d, length: %d (expected: range(0, %d))", srcIndex, length, srcCapacity));
}
}
protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) {
checkIndex(index, length);
if (dstIndex < 0 || dstIndex > dstCapacity - length) {
throw new IndexOutOfBoundsException(String.format(
"dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity));
}
}
/**
* Throws an {@link IndexOutOfBoundsException} if the current
* {@linkplain #readableBytes() readable bytes} of this buffer is less

View File

@ -1835,6 +1835,20 @@ public interface ByteBuf extends Buf, Comparable<ByteBuf> {
*/
int arrayOffset();
/**
* Returns {@code true} if and only if this buffer has a reference to the low-level memory address that points
* to the backing data.
*/
boolean hasMemoryAddress();
/**
* Returns the low-level memory address that point to the first byte of ths backing data.
*
* @throws UnsupportedOperationException
* if this buffer does not support accessing the low-level memory address
*/
long memoryAddress();
/**
* Decodes this buffer's readable bytes into a string with the specified
* character set name. This method is identical to

View File

@ -351,15 +351,11 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public List<ByteBuf> decompose(int offset, int length) {
checkIndex(offset, length);
if (length == 0) {
return Collections.emptyList();
}
if (offset + length > capacity()) {
throw new IndexOutOfBoundsException("Too many bytes to decompose - Need "
+ (offset + length) + ", capacity is " + capacity());
}
int componentId = toComponentIndex(offset);
List<ByteBuf> slice = new ArrayList<ByteBuf>(components.size());
@ -428,6 +424,22 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
throw new UnsupportedOperationException();
}
@Override
public boolean hasMemoryAddress() {
if (components.size() == 1) {
return components.get(0).buf.hasMemoryAddress();
}
return false;
}
@Override
public long memoryAddress() {
if (components.size() == 1) {
return components.get(0).buf.memoryAddress();
}
throw new UnsupportedOperationException();
}
@Override
public int capacity() {
if (components.isEmpty()) {
@ -510,10 +522,7 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public int toComponentIndex(int offset) {
assert !freed;
if (offset < 0 || offset >= capacity()) {
throw new IndexOutOfBoundsException(String.format(
"offset: %d (expected: >= 0 && < capacity(%d))", offset, capacity()));
}
checkIndex(offset);
Component c = lastAccessed;
if (c == null) {
@ -615,19 +624,12 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
if (index > capacity() - length || dstIndex > dst.length - length) {
throw new IndexOutOfBoundsException("Too many bytes to read - Needs "
+ (index + length) + ", maximum is " + capacity() + " or "
+ dst.length);
}
if (index < 0) {
throw new IndexOutOfBoundsException("index must be >= 0");
}
checkDstIndex(index, length, dstIndex, dst.length);
if (length == 0) {
return this;
}
int i = toComponentIndex(index);
int i = toComponentIndex(index);
while (length > 0) {
Component c = components.get(i);
ByteBuf s = c.buf;
@ -647,16 +649,11 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
int limit = dst.limit();
int length = dst.remaining();
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be read - Needs "
+ (index + length) + ", maximum is " + capacity());
}
if (index < 0) {
throw new IndexOutOfBoundsException("index must be >= 0");
}
checkIndex(index, length);
if (length == 0) {
return this;
}
int i = toComponentIndex(index);
try {
while (length > 0) {
@ -678,17 +675,7 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
if (index > capacity() - length || dstIndex > dst.capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be read - Needs "
+ (index + length) + " or " + (dstIndex + length) + ", maximum is "
+ capacity() + " or " + dst.capacity());
}
if (index < 0) {
throw new IndexOutOfBoundsException("index must be >= 0");
}
if (length == 0) {
return this;
}
checkDstIndex(index, length, dstIndex, dst.capacity());
int i = toComponentIndex(index);
while (length > 0) {
Component c = components.get(i);
@ -722,15 +709,8 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
}
@Override
public CompositeByteBuf getBytes(int index, OutputStream out, int length)
throws IOException {
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be read - needs "
+ (index + length) + ", maximum of " + capacity());
}
if (index < 0) {
throw new IndexOutOfBoundsException("index must be >= 0");
}
public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
checkIndex(index, length);
if (length == 0) {
return this;
}
@ -839,14 +819,9 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
int componentId = toComponentIndex(index);
if (index > capacity() - length || srcIndex > src.length - length) {
throw new IndexOutOfBoundsException("Too many bytes to read - needs "
+ (index + length) + " or " + (srcIndex + length) + ", maximum is "
+ capacity() + " or " + src.length);
}
checkSrcIndex(index, length, srcIndex, src.length);
int i = componentId;
int i = toComponentIndex(index);
while (length > 0) {
Component c = components.get(i);
ByteBuf s = c.buf;
@ -863,15 +838,11 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public CompositeByteBuf setBytes(int index, ByteBuffer src) {
int componentId = toComponentIndex(index);
int limit = src.limit();
int length = src.remaining();
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be written - Needs "
+ (index + length) + ", maximum is " + capacity());
}
int i = componentId;
checkIndex(index, length);
int i = toComponentIndex(index);
try {
while (length > 0) {
Component c = components.get(i);
@ -892,14 +863,9 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
int componentId = toComponentIndex(index);
if (index > capacity() - length || srcIndex > src.capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be written - Needs "
+ (index + length) + " or " + (srcIndex + length) + ", maximum is "
+ capacity() + " or " + src.capacity());
}
checkSrcIndex(index, length, srcIndex, src.capacity());
int i = componentId;
int i = toComponentIndex(index);
while (length > 0) {
Component c = components.get(i);
ByteBuf s = c.buf;
@ -915,15 +881,10 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
}
@Override
public int setBytes(int index, InputStream in, int length)
throws IOException {
int componentId = toComponentIndex(index);
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to write - Needs "
+ (index + length) + ", maximum is " + capacity());
}
public int setBytes(int index, InputStream in, int length) throws IOException {
checkIndex(index, length);
int i = componentId;
int i = toComponentIndex(index);
int readBytes = 0;
do {
@ -956,15 +917,10 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
}
@Override
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
int componentId = toComponentIndex(index);
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to write - Needs "
+ (index + length) + ", maximum is " + capacity());
}
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
checkIndex(index, length);
int i = componentId;
int i = toComponentIndex(index);
int readBytes = 0;
do {
Component c = components.get(i);
@ -1002,14 +958,9 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public ByteBuf copy(int index, int length) {
int componentId = toComponentIndex(index);
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to copy - Needs "
+ (index + length) + ", maximum is " + capacity());
}
checkIndex(index, length);
ByteBuf dst = Unpooled.buffer(length);
copyTo(index, length, componentId, dst);
copyTo(index, length, toComponentIndex(index), dst);
return dst;
}
@ -1045,10 +996,7 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
private Component findComponent(int offset) {
assert !freed;
if (offset < 0 || offset >= capacity()) {
throw new IndexOutOfBoundsException(String.format(
"offset: %d (expected: >= 0 && < capacity(%d))", offset, capacity()));
}
checkIndex(offset);
Component c = lastAccessed;
if (c == null) {
@ -1114,21 +1062,13 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf
@Override
public ByteBuffer[] nioBuffers(int index, int length) {
if (index + length > capacity()) {
throw new IndexOutOfBoundsException("Too many bytes to convert - Needs"
+ (index + length) + ", maximum is " + capacity());
}
if (index < 0) {
throw new IndexOutOfBoundsException("index must be >= 0");
}
checkIndex(index, length);
if (length == 0) {
return EMPTY_NIOBUFFERS;
}
int componentId = toComponentIndex(index);
List<ByteBuffer> buffers = new ArrayList<ByteBuffer>(components.size());
int i = componentId;
int i = toComponentIndex(index);
while (length > 0) {
Component c = components.get(i);
ByteBuf s = c.buf;

View File

@ -91,6 +91,16 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
return buffer.arrayOffset();
}
@Override
public boolean hasMemoryAddress() {
return buffer.hasMemoryAddress();
}
@Override
public long memoryAddress() {
return buffer.memoryAddress();
}
@Override
public byte getByte(int index) {
return _getByte(index);

View File

@ -16,6 +16,8 @@
package io.netty.buffer;
import io.netty.util.internal.PlatformDependent;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
@ -34,6 +36,7 @@ public final class EmptyByteBuf implements ByteBuf {
private final ByteOrder order;
private final ByteBuffer nioBuf = ByteBuffer.allocateDirect(0);
private final long memoryAddress;
private final byte[] array = EMPTY_ARRAY;
private final String str;
@ -41,6 +44,12 @@ public final class EmptyByteBuf implements ByteBuf {
this.order = order;
nioBuf.order(order);
str = getClass().getSimpleName() + (order == ByteOrder.BIG_ENDIAN? "BE" : "LE");
if (PlatformDependent.hasUnsafe()) {
memoryAddress = PlatformDependent.directBufferAddress(nioBuf);
} else {
memoryAddress = -1;
}
}
@Override
@ -745,6 +754,20 @@ public final class EmptyByteBuf implements ByteBuf {
return 0;
}
@Override
public boolean hasMemoryAddress() {
return memoryAddress != -1;
}
@Override
public long memoryAddress() {
if (hasMemoryAddress()) {
return memoryAddress;
} else {
throw new UnsupportedOperationException();
}
}
@Override
public String toString(Charset charset) {
return "";

View File

@ -68,15 +68,15 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
checkIndex(index, length);
if (dst instanceof PooledDirectByteBuf) {
PooledDirectByteBuf bbdst = (PooledDirectByteBuf) dst;
ByteBuffer data = bbdst.internalNioBuffer();
dstIndex = bbdst.idx(dstIndex);
data.clear().position(dstIndex).limit(dstIndex + length);
getBytes(index, data);
} else if (dst.hasArray()) {
checkDstIndex(index, length, dstIndex, dst.capacity());
if (dst.hasArray()) {
getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
} else if (dst.nioBufferCount() > 0) {
for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
int bbLen = bb.remaining();
getBytes(index, bb);
index += bbLen;
}
} else {
dst.setBytes(dstIndex, this, index, length);
}
@ -85,7 +85,7 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, length);
checkDstIndex(index, length, dstIndex, dst.length);
ByteBuffer tmpBuf = internalNioBuffer();
index = idx(index);
tmpBuf.clear().position(index).limit(index + length);
@ -162,15 +162,15 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
checkIndex(index, length);
if (src instanceof PooledDirectByteBuf) {
PooledDirectByteBuf bbsrc = (PooledDirectByteBuf) src;
ByteBuffer data = bbsrc.internalNioBuffer();
srcIndex = bbsrc.idx(srcIndex);
data.clear().position(srcIndex).limit(srcIndex + length);
setBytes(index, data);
} else if (src.hasArray()) {
checkSrcIndex(index, length, srcIndex, src.capacity());
if (src.hasArray()) {
setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);
} else if (src.nioBufferCount() > 0) {
for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) {
int bbLen = bb.remaining();
setBytes(index, bb);
index += bbLen;
}
} else {
src.getBytes(srcIndex, this, index, length);
}
@ -179,7 +179,7 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
checkIndex(index, length);
checkSrcIndex(index, length, srcIndex, src.length);
ByteBuffer tmpBuf = internalNioBuffer();
index = idx(index);
tmpBuf.clear().position(index).limit(index + length);
@ -231,7 +231,7 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf copy(int index, int length) {
checkIndex(index, length);
ByteBuf copy = alloc().directBuffer(capacity(), maxCapacity());
ByteBuf copy = alloc().directBuffer(length, maxCapacity());
copy.writeBytes(this, index, length);
return copy;
}
@ -267,4 +267,14 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
public int arrayOffset() {
throw new UnsupportedOperationException("direct buffer");
}
@Override
public boolean hasMemoryAddress() {
return false;
}
@Override
public long memoryAddress() {
throw new UnsupportedOperationException();
}
}

View File

@ -14,6 +14,8 @@
package io.netty.buffer;
import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -76,10 +78,12 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
if (dst.hasArray()) {
checkDstIndex(index, length, dstIndex, dst.capacity());
if (dst.hasMemoryAddress()) {
PlatformDependent.copyMemory(memory, idx(index), dst.memoryAddress() + dstIndex, length);
} if (dst.hasArray()) {
getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
} else {
checkIndex(index, length);
dst.setBytes(dstIndex, memory, idx(index), length);
}
return this;
@ -87,7 +91,7 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, length);
checkDstIndex(index, length, dstIndex, dst.length);
System.arraycopy(memory, idx(index), dst, dstIndex, length);
return this;
}
@ -157,8 +161,10 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
checkIndex(index, length);
if (src.hasArray()) {
checkSrcIndex(index, length, srcIndex, src.capacity());
if (src.hasMemoryAddress()) {
PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, memory, idx(index), length);
} else if (src.hasArray()) {
setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);
} else {
src.getBytes(srcIndex, memory, idx(index), length);
@ -168,7 +174,7 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
checkIndex(index, length);
checkSrcIndex(index, length, srcIndex, src.length);
System.arraycopy(src, srcIndex, memory, idx(index), length);
return this;
}
@ -238,6 +244,16 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
return offset;
}
@Override
public boolean hasMemoryAddress() {
return false;
}
@Override
public long memoryAddress() {
throw new UnsupportedOperationException();
}
@Override
protected ByteBuffer newInternalNioBuffer(byte[] memory) {
return ByteBuffer.wrap(memory);

View File

@ -96,10 +96,16 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
checkIndex(index, 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 instanceof PooledUnsafeDirectByteBuf) {
PooledUnsafeDirectByteBuf bbdst = (PooledUnsafeDirectByteBuf) dst;
PlatformDependent.copyMemory(addr(index), bbdst.addr(dstIndex), length);
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 {
@ -112,6 +118,12 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, 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);
}
@ -184,10 +196,16 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
checkIndex(index, 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 instanceof PooledUnsafeDirectByteBuf) {
PooledUnsafeDirectByteBuf bbsrc = (PooledUnsafeDirectByteBuf) src;
PlatformDependent.copyMemory(bbsrc.addr(srcIndex), addr(index), length);
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 {
@ -247,10 +265,10 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
@Override
public ByteBuf copy(int index, int length) {
checkIndex(index, length);
PooledUnsafeDirectByteBuf copy = (PooledUnsafeDirectByteBuf) alloc().directBuffer(capacity(), maxCapacity());
PooledUnsafeDirectByteBuf copy = (PooledUnsafeDirectByteBuf) alloc().directBuffer(length, maxCapacity());
if (length != 0) {
PlatformDependent.copyMemory(addr(index), copy.addr(index), length);
copy.setIndex(index, index + length);
PlatformDependent.copyMemory(addr(index), copy.addr(0), length);
copy.setIndex(0, length);
}
return copy;
}
@ -287,6 +305,16 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
throw new UnsupportedOperationException("direct buffer");
}
@Override
public boolean hasMemoryAddress() {
return true;
}
@Override
public long memoryAddress() {
return memoryAddress;
}
private long addr(int index) {
return memoryAddress + index;
}

View File

@ -79,6 +79,16 @@ public class ReadOnlyByteBuf extends AbstractDerivedByteBuf {
throw new ReadOnlyBufferException();
}
@Override
public boolean hasMemoryAddress() {
return false;
}
@Override
public long memoryAddress() {
throw new ReadOnlyBufferException();
}
@Override
public ByteBuf discardReadBytes() {
throw new ReadOnlyBufferException();

View File

@ -102,6 +102,16 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
return buffer.arrayOffset() + adjustment;
}
@Override
public boolean hasMemoryAddress() {
return buffer.hasMemoryAddress();
}
@Override
public long memoryAddress() {
return buffer.memoryAddress() + adjustment;
}
@Override
protected byte _getByte(int index) {
return buffer.getByte(index + adjustment);
@ -217,30 +227,26 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
}
@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);
buffer.getBytes(index + adjustment, out, length);
return this;
}
@Override
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
checkIndex(index, length);
return buffer.getBytes(index + adjustment, out, length);
}
@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 buffer.setBytes(index + adjustment, in, length);
}
@Override
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
checkIndex(index, length);
return buffer.setBytes(index + adjustment, in, length);
}

View File

@ -793,6 +793,16 @@ public final class SwappedByteBuf implements ByteBuf {
return buf.arrayOffset();
}
@Override
public boolean hasMemoryAddress() {
return buf.hasMemoryAddress();
}
@Override
public long memoryAddress() {
return buf.memoryAddress();
}
@Override
public String toString(Charset charset) {
return buf.toString(charset);

View File

@ -195,6 +195,16 @@ final class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
throw new UnsupportedOperationException("direct buffer");
}
@Override
public boolean hasMemoryAddress() {
return false;
}
@Override
public long memoryAddress() {
throw new UnsupportedOperationException();
}
@Override
public byte getByte(int index) {
ensureAccessible();
@ -252,14 +262,15 @@ final class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
ensureAccessible();
if (dst instanceof UnpooledDirectByteBuf) {
UnpooledDirectByteBuf bbdst = (UnpooledDirectByteBuf) dst;
ByteBuffer data = bbdst.internalNioBuffer();
data.clear().position(dstIndex).limit(dstIndex + length);
getBytes(index, data);
} else if (dst.hasArray()) {
checkDstIndex(index, length, dstIndex, dst.capacity());
if (dst.hasArray()) {
getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
} else if (dst.nioBufferCount() > 0) {
for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
int bbLen = bb.remaining();
getBytes(index, bb);
index += bbLen;
}
} else {
dst.setBytes(dstIndex, this, index, length);
}
@ -268,7 +279,7 @@ final class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, length);
checkDstIndex(index, length, dstIndex, dst.length);
if (dst == null) {
throw new NullPointerException("dst");
}
@ -361,15 +372,15 @@ final class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
ensureAccessible();
if (src instanceof UnpooledDirectByteBuf) {
UnpooledDirectByteBuf bbsrc = (UnpooledDirectByteBuf) src;
ByteBuffer data = bbsrc.internalNioBuffer();
data.clear().position(srcIndex).limit(srcIndex + length);
setBytes(index, data);
} else if (buffer.hasArray()) {
checkSrcIndex(index, length, srcIndex, src.capacity());
if (buffer.hasArray()) {
src.getBytes(srcIndex, buffer.array(), index + buffer.arrayOffset(), length);
} else if (src.nioBufferCount() > 0) {
for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) {
int bbLen = bb.remaining();
setBytes(index, bb);
index += bbLen;
}
} else {
src.getBytes(srcIndex, this, index, length);
}
@ -378,7 +389,7 @@ final class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
ensureAccessible();
checkSrcIndex(index, length, srcIndex, src.length);
ByteBuffer tmpBuf = internalNioBuffer();
tmpBuf.clear().position(index).limit(index + length);
tmpBuf.put(src, srcIndex, length);

View File

@ -15,6 +15,8 @@
*/
package io.netty.buffer;
import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -145,10 +147,22 @@ final class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
return 0;
}
@Override
public boolean hasMemoryAddress() {
return false;
}
@Override
public long memoryAddress() {
throw new UnsupportedOperationException();
}
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
ensureAccessible();
if (dst.hasArray()) {
checkDstIndex(index, length, dstIndex, dst.capacity());
if (dst.hasMemoryAddress()) {
PlatformDependent.copyMemory(array, index, dst.memoryAddress() + dstIndex, length);
} else if (dst.hasArray()) {
getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
} else {
dst.setBytes(dstIndex, array, index, length);
@ -158,7 +172,7 @@ final class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
ensureAccessible();
checkDstIndex(index, length, dstIndex, dst.length);
System.arraycopy(array, index, dst, dstIndex, length);
return this;
}
@ -185,8 +199,10 @@ final class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
ensureAccessible();
if (src.hasArray()) {
checkSrcIndex(index, length, srcIndex, src.capacity());
if (src.hasMemoryAddress()) {
PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, array, index, length);
} else if (src.hasArray()) {
setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);
} else {
src.getBytes(srcIndex, array, index, length);
@ -196,7 +212,7 @@ final class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
ensureAccessible();
checkSrcIndex(index, length, srcIndex, src.length);
System.arraycopy(src, srcIndex, array, index, length);
return this;
}

View File

@ -199,6 +199,16 @@ final class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
throw new UnsupportedOperationException("direct buffer");
}
@Override
public boolean hasMemoryAddress() {
return true;
}
@Override
public long memoryAddress() {
return memoryAddress;
}
@Override
protected byte _getByte(int index) {
return PlatformDependent.getByte(addr(index));
@ -232,10 +242,16 @@ final class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
ensureAccessible();
if (dst instanceof UnpooledUnsafeDirectByteBuf) {
UnpooledUnsafeDirectByteBuf bbdst = (UnpooledUnsafeDirectByteBuf) dst;
PlatformDependent.copyMemory(addr(index), bbdst.addr(dstIndex), length);
checkIndex(index, 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 {
@ -305,14 +321,22 @@ final class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
ensureAccessible();
if (src instanceof UnpooledUnsafeDirectByteBuf) {
UnpooledUnsafeDirectByteBuf bbsrc = (UnpooledUnsafeDirectByteBuf) src;
PlatformDependent.copyMemory(bbsrc.addr(srcIndex), addr(index), length);
} else if (buffer.hasArray()) {
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr(index), length);
} else {
src.getBytes(srcIndex, this, index, length);
checkIndex(index, 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 (buffer.hasArray()) {
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr(index), length);
} else {
src.getBytes(srcIndex, this, index, length);
}
}
return this;
}
@ -408,11 +432,10 @@ final class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
@Override
public ByteBuf copy(int index, int length) {
checkIndex(index, length);
UnpooledUnsafeDirectByteBuf copy =
(UnpooledUnsafeDirectByteBuf) alloc().directBuffer(capacity(), maxCapacity());
UnpooledUnsafeDirectByteBuf copy = (UnpooledUnsafeDirectByteBuf) alloc().directBuffer(length, maxCapacity());
if (length != 0) {
PlatformDependent.copyMemory(addr(index), copy.addr(index), length);
copy.setIndex(index, index + length);
PlatformDependent.copyMemory(addr(index), copy.addr(0), length);
copy.setIndex(0, length);
}
return copy;
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2012 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 java.nio.ByteOrder;
import static org.junit.Assert.*;
/**
* Tests big-endian direct channel buffers
*/
public class PooledBigEndianDirectByteBufTest extends AbstractByteBufTest {
private ByteBuf buffer;
@Override
protected ByteBuf newBuffer(int length) {
buffer = PooledByteBufAllocator.DEFAULT.directBuffer(length);
assertSame(ByteOrder.BIG_ENDIAN, buffer.order());
assertEquals(0, buffer.writerIndex());
return buffer;
}
@Override
protected ByteBuf[] components() {
return new ByteBuf[] { buffer };
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2012 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 static org.junit.Assert.*;
/**
* Tests big-endian heap channel buffers
*/
public class PooledBigEndianHeapByteBufTest extends AbstractByteBufTest {
private ByteBuf buffer;
@Override
protected ByteBuf newBuffer(int length) {
buffer = PooledByteBufAllocator.DEFAULT.heapBuffer(length);
assertEquals(0, buffer.writerIndex());
return buffer;
}
@Override
protected ByteBuf[] components() {
return new ByteBuf[] { buffer };
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2012 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 java.nio.ByteOrder;
import static org.junit.Assert.*;
/**
* Tests little-endian direct channel buffers
*/
public class PooledLittleEndianDirectByteBufTest extends AbstractByteBufTest {
private ByteBuf buffer;
@Override
protected ByteBuf newBuffer(int length) {
buffer = PooledByteBufAllocator.DEFAULT.directBuffer(length).order(ByteOrder.LITTLE_ENDIAN);
assertSame(ByteOrder.LITTLE_ENDIAN, buffer.order());
assertEquals(0, buffer.writerIndex());
return buffer;
}
@Override
protected ByteBuf[] components() {
return new ByteBuf[] { buffer };
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2012 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 java.nio.ByteOrder;
import static org.junit.Assert.*;
/**
* Tests little-endian heap channel buffers
*/
public class PooledLittleEndianHeapByteBufTest extends AbstractByteBufTest {
private ByteBuf buffer;
@Override
protected ByteBuf newBuffer(int length) {
buffer = PooledByteBufAllocator.DEFAULT.heapBuffer(length).order(ByteOrder.LITTLE_ENDIAN);
assertEquals(0, buffer.writerIndex());
return buffer;
}
@Override
protected ByteBuf[] components() {
return new ByteBuf[] { buffer };
}
}

View File

@ -106,6 +106,16 @@ final class ReplayingDecoderBuffer implements ByteBuf {
throw new UnsupportedOperationException();
}
@Override
public boolean hasMemoryAddress() {
return false;
}
@Override
public long memoryAddress() {
throw new UnsupportedOperationException();
}
@Override
public ByteBuf clear() {
throw new UnreplayableOperationException();