retainSlice() unwrap ByteBuf
Motivation: retainSlice() currently does not unwrap the ByteBuf when creating the ByteBuf wrapper. This effectivley forms a linked list of ByteBuf when it is only necessary to maintain a reference to the unwrapped ByteBuf. Modifications: - retainSlice() and retainDuplicate() variants should only maintain a reference to the unwrapped ByteBuf - create new unit tests which generally verify the retainSlice() behavior - Remove unecessary generic arguments from AbstractPooledDerivedByteBuf - Remove unecessary int length member variable from the unpooled sliced ByteBuf implementation - Rename the unpooled sliced/derived ByteBuf to include Unpooled in their name to be more consistent with the Pooled variants Result: Fixes https://github.com/netty/netty/issues/5582
This commit is contained in:
parent
d92c5f5f5b
commit
82b617dfe9
@ -1165,7 +1165,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
return new DuplicatedAbstractByteBuf(this);
|
||||
return new UnpooledDuplicatedByteBuf(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1185,7 +1185,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return new SlicedAbstractByteBuf(this, index, length);
|
||||
return new UnpooledSlicedByteBuf(this, index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,15 +24,15 @@ import java.nio.ByteOrder;
|
||||
/**
|
||||
* Abstract base class for derived {@link ByteBuf} implementations.
|
||||
*/
|
||||
abstract class AbstractPooledDerivedByteBuf<T> extends AbstractReferenceCountedByteBuf {
|
||||
abstract class AbstractPooledDerivedByteBuf extends AbstractReferenceCountedByteBuf {
|
||||
|
||||
private final Handle<AbstractPooledDerivedByteBuf<T>> recyclerHandle;
|
||||
private final Handle<AbstractPooledDerivedByteBuf> recyclerHandle;
|
||||
private AbstractByteBuf buffer;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
AbstractPooledDerivedByteBuf(Handle<? extends AbstractPooledDerivedByteBuf<T>> recyclerHandle) {
|
||||
AbstractPooledDerivedByteBuf(Handle<? extends AbstractPooledDerivedByteBuf> recyclerHandle) {
|
||||
super(0);
|
||||
this.recyclerHandle = (Handle<AbstractPooledDerivedByteBuf<T>>) recyclerHandle;
|
||||
this.recyclerHandle = (Handle<AbstractPooledDerivedByteBuf>) recyclerHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -40,26 +40,25 @@ abstract class AbstractPooledDerivedByteBuf<T> extends AbstractReferenceCountedB
|
||||
return buffer;
|
||||
}
|
||||
|
||||
final <U extends AbstractPooledDerivedByteBuf<T>> U init(
|
||||
AbstractByteBuf buffer, int readerIndex, int writerIndex, int maxCapacity) {
|
||||
final <U extends AbstractPooledDerivedByteBuf> U init(
|
||||
AbstractByteBuf unwrapped, ByteBuf wrapped, int readerIndex, int writerIndex, int maxCapacity) {
|
||||
|
||||
buffer.retain();
|
||||
this.buffer = buffer;
|
||||
wrapped.retain(); // Retain up front to ensure the wrapped buffer is accessible before doing more work.
|
||||
this.buffer = unwrapped;
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
maxCapacity(maxCapacity);
|
||||
setIndex(readerIndex, writerIndex);
|
||||
setIndex0(readerIndex, writerIndex); // It is assumed the bounds checking is done by the caller.
|
||||
setRefCnt(1);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final U castThis = (U) this;
|
||||
success = true;
|
||||
wrapped = null;
|
||||
return castThis;
|
||||
} finally {
|
||||
if (!success) {
|
||||
if (wrapped != null) {
|
||||
this.buffer = null;
|
||||
buffer.release();
|
||||
wrapped.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -120,19 +119,9 @@ abstract class AbstractPooledDerivedByteBuf<T> extends AbstractReferenceCountedB
|
||||
return nioBuffer(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedDuplicate() {
|
||||
return PooledDuplicatedByteBuf.newInstance(this, readerIndex(), writerIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedSlice() {
|
||||
final int index = readerIndex();
|
||||
return retainedSlice(index, writerIndex() - index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedSlice(int index, int length) {
|
||||
return PooledSlicedByteBuf.newInstance(this, index, length, index);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Copyright 2016 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.ByteProcessor;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import static io.netty.util.internal.MathUtil.isOutOfBounds;
|
||||
|
||||
abstract class AbstractUnpooledSlicedByteBuf extends AbstractDerivedByteBuf {
|
||||
private final ByteBuf buffer;
|
||||
private final int adjustment;
|
||||
|
||||
AbstractUnpooledSlicedByteBuf(ByteBuf buffer, int index, int length) {
|
||||
super(length);
|
||||
checkSliceOutOfBounds(index, length, buffer);
|
||||
|
||||
if (buffer instanceof AbstractUnpooledSlicedByteBuf) {
|
||||
this.buffer = ((AbstractUnpooledSlicedByteBuf) buffer).buffer;
|
||||
adjustment = ((AbstractUnpooledSlicedByteBuf) buffer).adjustment + index;
|
||||
} else if (buffer instanceof DuplicatedByteBuf) {
|
||||
this.buffer = buffer.unwrap();
|
||||
adjustment = index;
|
||||
} else {
|
||||
this.buffer = buffer;
|
||||
adjustment = index;
|
||||
}
|
||||
|
||||
initLength(length);
|
||||
writerIndex(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the constructor before {@link #writerIndex(int)}.
|
||||
* @param length the {@code length} argument from the constructor.
|
||||
*/
|
||||
void initLength(int length) {
|
||||
}
|
||||
|
||||
int length() {
|
||||
return capacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf unwrap() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return unwrap().alloc();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public ByteOrder order() {
|
||||
return unwrap().order();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirect() {
|
||||
return unwrap().isDirect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
throw new UnsupportedOperationException("sliced buffer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasArray() {
|
||||
return unwrap().hasArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] array() {
|
||||
return unwrap().array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int arrayOffset() {
|
||||
return idx(unwrap().arrayOffset());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMemoryAddress() {
|
||||
return unwrap().hasMemoryAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long memoryAddress() {
|
||||
return unwrap().memoryAddress() + adjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
checkIndex0(index, 1);
|
||||
return unwrap().getByte(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte _getByte(int index) {
|
||||
return unwrap().getByte(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
checkIndex0(index, 2);
|
||||
return unwrap().getShort(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected short _getShort(int index) {
|
||||
return unwrap().getShort(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShortLE(int index) {
|
||||
checkIndex0(index, 2);
|
||||
return unwrap().getShortLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected short _getShortLE(int index) {
|
||||
return unwrap().getShortLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMedium(int index) {
|
||||
checkIndex0(index, 3);
|
||||
return unwrap().getUnsignedMedium(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getUnsignedMedium(int index) {
|
||||
return unwrap().getUnsignedMedium(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMediumLE(int index) {
|
||||
checkIndex0(index, 3);
|
||||
return unwrap().getUnsignedMediumLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getUnsignedMediumLE(int index) {
|
||||
return unwrap().getUnsignedMediumLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
checkIndex0(index, 4);
|
||||
return unwrap().getInt(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getInt(int index) {
|
||||
return unwrap().getInt(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntLE(int index) {
|
||||
checkIndex0(index, 4);
|
||||
return unwrap().getIntLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getIntLE(int index) {
|
||||
return unwrap().getIntLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
checkIndex0(index, 8);
|
||||
return unwrap().getLong(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long _getLong(int index) {
|
||||
return unwrap().getLong(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongLE(int index) {
|
||||
checkIndex0(index, 8);
|
||||
return unwrap().getLongLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long _getLongLE(int index) {
|
||||
return unwrap().getLongLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
final ByteBuf duplicate = unwrap().slice(adjustment, length());
|
||||
duplicate.setIndex(readerIndex(), writerIndex());
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf copy(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().copy(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().slice(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
checkIndex0(index, dst.remaining());
|
||||
unwrap().getBytes(idx(index), dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
checkIndex0(index, 1);
|
||||
unwrap().setByte(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharSequence(int index, int length, Charset charset) {
|
||||
checkIndex0(index, length);
|
||||
return buffer.getCharSequence(idx(index), length, charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setByte(int index, int value) {
|
||||
unwrap().setByte(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
checkIndex0(index, 2);
|
||||
unwrap().setShort(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setShort(int index, int value) {
|
||||
unwrap().setShort(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShortLE(int index, int value) {
|
||||
checkIndex0(index, 2);
|
||||
unwrap().setShortLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setShortLE(int index, int value) {
|
||||
unwrap().setShortLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
checkIndex0(index, 3);
|
||||
unwrap().setMedium(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setMedium(int index, int value) {
|
||||
unwrap().setMedium(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMediumLE(int index, int value) {
|
||||
checkIndex0(index, 3);
|
||||
unwrap().setMediumLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setMediumLE(int index, int value) {
|
||||
unwrap().setMediumLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
checkIndex0(index, 4);
|
||||
unwrap().setInt(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setInt(int index, int value) {
|
||||
unwrap().setInt(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setIntLE(int index, int value) {
|
||||
checkIndex0(index, 4);
|
||||
unwrap().setIntLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setIntLE(int index, int value) {
|
||||
unwrap().setIntLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
checkIndex0(index, 8);
|
||||
unwrap().setLong(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setLong(int index, long value) {
|
||||
unwrap().setLong(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLongLE(int index, long value) {
|
||||
checkIndex0(index, 8);
|
||||
unwrap().setLongLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setLongLE(int index, long value) {
|
||||
unwrap().setLongLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().setBytes(idx(index), src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().setBytes(idx(index), src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
checkIndex0(index, src.remaining());
|
||||
unwrap().setBytes(idx(index), src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setCharSequence(int index, CharSequence sequence, Charset charset) {
|
||||
if (charset.equals(CharsetUtil.UTF_8)) {
|
||||
checkIndex0(index, ByteBufUtil.utf8MaxBytes(sequence));
|
||||
return ByteBufUtil.writeUtf8(this, idx(index), sequence, sequence.length());
|
||||
}
|
||||
if (charset.equals(CharsetUtil.US_ASCII)) {
|
||||
int len = sequence.length();
|
||||
checkIndex0(index, len);
|
||||
return ByteBufUtil.writeAscii(this, idx(index), sequence, len);
|
||||
}
|
||||
byte[] bytes = sequence.toString().getBytes(charset);
|
||||
checkIndex0(index, bytes.length);
|
||||
buffer.setBytes(idx(index), bytes);
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), out, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().getBytes(idx(index), out, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().getBytes(idx(index), out, position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, InputStream in, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nioBufferCount() {
|
||||
return unwrap().nioBufferCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().nioBuffer(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().nioBuffers(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByte(int index, int length, ByteProcessor processor) {
|
||||
checkIndex0(index, length);
|
||||
int ret = unwrap().forEachByte(idx(index), length, processor);
|
||||
if (ret >= adjustment) {
|
||||
return ret - adjustment;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int index, int length, ByteProcessor processor) {
|
||||
checkIndex0(index, length);
|
||||
int ret = unwrap().forEachByteDesc(idx(index), length, processor);
|
||||
if (ret >= adjustment) {
|
||||
return ret - adjustment;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index with the needed adjustment.
|
||||
*/
|
||||
final int idx(int index) {
|
||||
return index + adjustment;
|
||||
}
|
||||
|
||||
static void checkSliceOutOfBounds(int index, int length, ByteBuf buffer) {
|
||||
if (isOutOfBounds(index, length, buffer.capacity())) {
|
||||
throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')');
|
||||
}
|
||||
}
|
||||
}
|
@ -47,6 +47,8 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
|
||||
|
||||
if (buffer instanceof DuplicatedByteBuf) {
|
||||
this.buffer = ((DuplicatedByteBuf) buffer).buffer;
|
||||
} else if (buffer instanceof AbstractPooledDerivedByteBuf) {
|
||||
this.buffer = buffer.unwrap();
|
||||
} else {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedDuplicate() {
|
||||
return PooledDuplicatedByteBuf.newInstance(this, readerIndex(), writerIndex());
|
||||
return PooledDuplicatedByteBuf.newInstance(this, this, readerIndex(), writerIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,7 +149,7 @@ abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
|
||||
|
||||
@Override
|
||||
public final ByteBuf retainedSlice(int index, int length) {
|
||||
return PooledSlicedByteBuf.newInstance(this, index, length, index);
|
||||
return PooledSlicedByteBuf.newInstance(this, this, index, length);
|
||||
}
|
||||
|
||||
protected final ByteBuffer internalNioBuffer() {
|
||||
|
@ -28,7 +28,7 @@ import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
final class PooledDuplicatedByteBuf extends AbstractPooledDerivedByteBuf<PooledDuplicatedByteBuf> {
|
||||
final class PooledDuplicatedByteBuf extends AbstractPooledDerivedByteBuf {
|
||||
|
||||
private static final Recycler<PooledDuplicatedByteBuf> RECYCLER = new Recycler<PooledDuplicatedByteBuf>() {
|
||||
@Override
|
||||
@ -37,9 +37,10 @@ final class PooledDuplicatedByteBuf extends AbstractPooledDerivedByteBuf<PooledD
|
||||
}
|
||||
};
|
||||
|
||||
static PooledDuplicatedByteBuf newInstance(AbstractByteBuf buffer, int readerIndex, int writerIndex) {
|
||||
static PooledDuplicatedByteBuf newInstance(AbstractByteBuf unwrapped, ByteBuf wrapped,
|
||||
int readerIndex, int writerIndex) {
|
||||
final PooledDuplicatedByteBuf duplicate = RECYCLER.get();
|
||||
duplicate.init(buffer, readerIndex, writerIndex, buffer.maxCapacity());
|
||||
duplicate.init(unwrapped, wrapped, readerIndex, writerIndex, wrapped.maxCapacity());
|
||||
duplicate.markReaderIndex();
|
||||
duplicate.markWriterIndex();
|
||||
|
||||
@ -86,6 +87,21 @@ final class PooledDuplicatedByteBuf extends AbstractPooledDerivedByteBuf<PooledD
|
||||
return unwrap().copy(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
return unwrap().slice(index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
return PooledSlicedByteBuf.newInstance(unwrap(), this, index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
return PooledDuplicatedByteBuf.newInstance(unwrap(), this, readerIndex(), writerIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
return unwrap().getByte(index);
|
||||
|
@ -28,9 +28,9 @@ import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
|
||||
import static io.netty.util.internal.MathUtil.isOutOfBounds;
|
||||
import static io.netty.buffer.AbstractUnpooledSlicedByteBuf.checkSliceOutOfBounds;
|
||||
|
||||
final class PooledSlicedByteBuf extends AbstractPooledDerivedByteBuf<PooledSlicedByteBuf> {
|
||||
final class PooledSlicedByteBuf extends AbstractPooledDerivedByteBuf {
|
||||
|
||||
private static final Recycler<PooledSlicedByteBuf> RECYCLER = new Recycler<PooledSlicedByteBuf>() {
|
||||
@Override
|
||||
@ -39,20 +39,23 @@ final class PooledSlicedByteBuf extends AbstractPooledDerivedByteBuf<PooledSlice
|
||||
}
|
||||
};
|
||||
|
||||
static PooledSlicedByteBuf newInstance(AbstractByteBuf buffer, int index, int length, int adjustment) {
|
||||
if (isOutOfBounds(index, length, buffer.capacity())) {
|
||||
throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')');
|
||||
}
|
||||
static PooledSlicedByteBuf newInstance(AbstractByteBuf unwrapped, ByteBuf wrapped,
|
||||
int index, int length) {
|
||||
checkSliceOutOfBounds(index, length, unwrapped);
|
||||
return newInstance0(unwrapped, wrapped, index, length);
|
||||
}
|
||||
|
||||
private static PooledSlicedByteBuf newInstance0(AbstractByteBuf unwrapped, ByteBuf wrapped,
|
||||
int adjustment, int length) {
|
||||
final PooledSlicedByteBuf slice = RECYCLER.get();
|
||||
slice.init(buffer, 0, length, length);
|
||||
slice.init(unwrapped, wrapped, 0, length, length);
|
||||
slice.discardMarks();
|
||||
slice.adjustment = adjustment;
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
||||
private int adjustment;
|
||||
int adjustment;
|
||||
|
||||
private PooledSlicedByteBuf(Handle<PooledSlicedByteBuf> handle) {
|
||||
super(handle);
|
||||
@ -65,7 +68,7 @@ final class PooledSlicedByteBuf extends AbstractPooledDerivedByteBuf<PooledSlice
|
||||
|
||||
@Override
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
return reject();
|
||||
throw new UnsupportedOperationException("sliced buffer");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,6 +99,34 @@ final class PooledSlicedByteBuf extends AbstractPooledDerivedByteBuf<PooledSlice
|
||||
return unwrap().copy(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().slice(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedSlice(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return PooledSlicedByteBuf.newInstance0(unwrap(), this, idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
// Capacity is not allowed to change for a sliced ByteBuf, so length == capacity()
|
||||
final ByteBuf duplicate = unwrap().slice(adjustment, capacity());
|
||||
duplicate.setIndex(readerIndex(), writerIndex());
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf retainedDuplicate() {
|
||||
// Capacity is not allowed to change for a sliced ByteBuf, so length == capacity()
|
||||
final ByteBuf duplicate = retainedSlice(0, capacity());
|
||||
duplicate.setIndex(readerIndex(), writerIndex());
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
checkIndex0(index, 1);
|
||||
@ -411,8 +442,4 @@ final class PooledSlicedByteBuf extends AbstractPooledDerivedByteBuf<PooledSlice
|
||||
private int idx(int index) {
|
||||
return index + adjustment;
|
||||
}
|
||||
|
||||
private static ByteBuf reject() {
|
||||
throw new UnsupportedOperationException("sliced buffer");
|
||||
}
|
||||
}
|
||||
|
@ -15,21 +15,6 @@
|
||||
*/
|
||||
package io.netty.buffer;
|
||||
|
||||
import io.netty.util.ByteProcessor;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import static io.netty.util.internal.MathUtil.isOutOfBounds;
|
||||
|
||||
/**
|
||||
* A derived buffer which exposes its parent's sub-region only. It is
|
||||
* recommended to use {@link ByteBuf#slice()} and
|
||||
@ -39,464 +24,26 @@ import static io.netty.util.internal.MathUtil.isOutOfBounds;
|
||||
* @deprecated Do not use.
|
||||
*/
|
||||
@Deprecated
|
||||
public class SlicedByteBuf extends AbstractDerivedByteBuf {
|
||||
public class SlicedByteBuf extends AbstractUnpooledSlicedByteBuf {
|
||||
|
||||
private final ByteBuf buffer;
|
||||
private final int adjustment;
|
||||
private final int length;
|
||||
private int length;
|
||||
|
||||
public SlicedByteBuf(ByteBuf buffer, int index, int length) {
|
||||
super(length);
|
||||
if (isOutOfBounds(index, length, buffer.capacity())) {
|
||||
throw new IndexOutOfBoundsException(buffer + ".slice(" + index + ", " + length + ')');
|
||||
}
|
||||
super(buffer, index, length);
|
||||
}
|
||||
|
||||
if (buffer instanceof SlicedByteBuf) {
|
||||
this.buffer = ((SlicedByteBuf) buffer).buffer;
|
||||
adjustment = ((SlicedByteBuf) buffer).adjustment + index;
|
||||
} else if (buffer instanceof DuplicatedByteBuf) {
|
||||
this.buffer = buffer.unwrap();
|
||||
adjustment = index;
|
||||
} else {
|
||||
this.buffer = buffer;
|
||||
adjustment = index;
|
||||
}
|
||||
@Override
|
||||
final void initLength(int length) {
|
||||
this.length = length;
|
||||
|
||||
writerIndex(length);
|
||||
}
|
||||
|
||||
final int adjustment() {
|
||||
return adjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf unwrap() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return unwrap().alloc();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public ByteOrder order() {
|
||||
return unwrap().order();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirect() {
|
||||
return unwrap().isDirect();
|
||||
final int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int capacity() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf capacity(int newCapacity) {
|
||||
throw new UnsupportedOperationException("sliced buffer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasArray() {
|
||||
return unwrap().hasArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] array() {
|
||||
return unwrap().array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int arrayOffset() {
|
||||
return idx(unwrap().arrayOffset());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMemoryAddress() {
|
||||
return unwrap().hasMemoryAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long memoryAddress() {
|
||||
return unwrap().memoryAddress() + adjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(int index) {
|
||||
checkIndex0(index, 1);
|
||||
return unwrap().getByte(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte _getByte(int index) {
|
||||
return unwrap().getByte(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
checkIndex0(index, 2);
|
||||
return unwrap().getShort(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected short _getShort(int index) {
|
||||
return unwrap().getShort(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShortLE(int index) {
|
||||
checkIndex0(index, 2);
|
||||
return unwrap().getShortLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected short _getShortLE(int index) {
|
||||
return unwrap().getShortLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMedium(int index) {
|
||||
checkIndex0(index, 3);
|
||||
return unwrap().getUnsignedMedium(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getUnsignedMedium(int index) {
|
||||
return unwrap().getUnsignedMedium(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnsignedMediumLE(int index) {
|
||||
checkIndex0(index, 3);
|
||||
return unwrap().getUnsignedMediumLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getUnsignedMediumLE(int index) {
|
||||
return unwrap().getUnsignedMediumLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
checkIndex0(index, 4);
|
||||
return unwrap().getInt(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getInt(int index) {
|
||||
return unwrap().getInt(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntLE(int index) {
|
||||
checkIndex0(index, 4);
|
||||
return unwrap().getIntLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int _getIntLE(int index) {
|
||||
return unwrap().getIntLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
checkIndex0(index, 8);
|
||||
return unwrap().getLong(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long _getLong(int index) {
|
||||
return unwrap().getLong(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongLE(int index) {
|
||||
checkIndex0(index, 8);
|
||||
return unwrap().getLongLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long _getLongLE(int index) {
|
||||
return unwrap().getLongLE(idx(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf duplicate() {
|
||||
final ByteBuf duplicate = unwrap().slice(adjustment, length);
|
||||
duplicate.setIndex(readerIndex(), writerIndex());
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf copy(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().copy(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf slice(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().slice(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), dst, dstIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||
checkIndex0(index, dst.remaining());
|
||||
unwrap().getBytes(idx(index), dst);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setByte(int index, int value) {
|
||||
checkIndex0(index, 1);
|
||||
unwrap().setByte(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharSequence(int index, int length, Charset charset) {
|
||||
checkIndex0(index, length);
|
||||
return buffer.getCharSequence(idx(index), length, charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setByte(int index, int value) {
|
||||
unwrap().setByte(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShort(int index, int value) {
|
||||
checkIndex0(index, 2);
|
||||
unwrap().setShort(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setShort(int index, int value) {
|
||||
unwrap().setShort(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setShortLE(int index, int value) {
|
||||
checkIndex0(index, 2);
|
||||
unwrap().setShortLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setShortLE(int index, int value) {
|
||||
unwrap().setShortLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMedium(int index, int value) {
|
||||
checkIndex0(index, 3);
|
||||
unwrap().setMedium(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setMedium(int index, int value) {
|
||||
unwrap().setMedium(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setMediumLE(int index, int value) {
|
||||
checkIndex0(index, 3);
|
||||
unwrap().setMediumLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setMediumLE(int index, int value) {
|
||||
unwrap().setMediumLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setInt(int index, int value) {
|
||||
checkIndex0(index, 4);
|
||||
unwrap().setInt(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setInt(int index, int value) {
|
||||
unwrap().setInt(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setIntLE(int index, int value) {
|
||||
checkIndex0(index, 4);
|
||||
unwrap().setIntLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setIntLE(int index, int value) {
|
||||
unwrap().setIntLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLong(int index, long value) {
|
||||
checkIndex0(index, 8);
|
||||
unwrap().setLong(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setLong(int index, long value) {
|
||||
unwrap().setLong(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setLongLE(int index, long value) {
|
||||
checkIndex0(index, 8);
|
||||
unwrap().setLongLE(idx(index), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _setLongLE(int index, long value) {
|
||||
unwrap().setLongLE(idx(index), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().setBytes(idx(index), src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||
checkIndex0(index, length);
|
||||
unwrap().setBytes(idx(index), src, srcIndex, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||
checkIndex0(index, src.remaining());
|
||||
unwrap().setBytes(idx(index), src);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setCharSequence(int index, CharSequence sequence, Charset charset) {
|
||||
if (charset.equals(CharsetUtil.UTF_8)) {
|
||||
checkIndex0(index, ByteBufUtil.utf8MaxBytes(sequence));
|
||||
return ByteBufUtil.writeUtf8(this, idx(index), sequence, sequence.length());
|
||||
}
|
||||
if (charset.equals(CharsetUtil.US_ASCII)) {
|
||||
int len = sequence.length();
|
||||
checkIndex0(index, len);
|
||||
return ByteBufUtil.writeAscii(this, idx(index), sequence, len);
|
||||
}
|
||||
byte[] bytes = sequence.toString().getBytes(charset);
|
||||
checkIndex0(index, bytes.length);
|
||||
buffer.setBytes(idx(index), bytes);
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
unwrap().getBytes(idx(index), out, length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().getBytes(idx(index), out, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().getBytes(idx(index), out, position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, InputStream in, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().setBytes(idx(index), in, position, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nioBufferCount() {
|
||||
return unwrap().nioBufferCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer nioBuffer(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().nioBuffer(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer[] nioBuffers(int index, int length) {
|
||||
checkIndex0(index, length);
|
||||
return unwrap().nioBuffers(idx(index), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByte(int index, int length, ByteProcessor processor) {
|
||||
checkIndex0(index, length);
|
||||
int ret = unwrap().forEachByte(idx(index), length, processor);
|
||||
if (ret >= adjustment) {
|
||||
return ret - adjustment;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int forEachByteDesc(int index, int length, ByteProcessor processor) {
|
||||
checkIndex0(index, length);
|
||||
int ret = unwrap().forEachByteDesc(idx(index), length, processor);
|
||||
if (ret >= adjustment) {
|
||||
return ret - adjustment;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index with the needed adjustment.
|
||||
*/
|
||||
final int idx(int index) {
|
||||
return index + adjustment;
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ package io.netty.buffer;
|
||||
* {@link DuplicatedByteBuf} implementation that can do optimizations because it knows the duplicated buffer
|
||||
* is of type {@link AbstractByteBuf}.
|
||||
*/
|
||||
final class DuplicatedAbstractByteBuf extends DuplicatedByteBuf {
|
||||
DuplicatedAbstractByteBuf(AbstractByteBuf buffer) {
|
||||
final class UnpooledDuplicatedByteBuf extends DuplicatedByteBuf {
|
||||
UnpooledDuplicatedByteBuf(AbstractByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
@ -16,15 +16,20 @@
|
||||
package io.netty.buffer;
|
||||
|
||||
/**
|
||||
* A special {@link SlicedByteBuf} that can make optimizations because it knows the sliced buffer is of type
|
||||
* {@link AbstractByteBuf}.
|
||||
* A special {@link AbstractUnpooledSlicedByteBuf} that can make optimizations because it knows the sliced buffer is of
|
||||
* type {@link AbstractByteBuf}.
|
||||
*/
|
||||
final class SlicedAbstractByteBuf extends SlicedByteBuf {
|
||||
final class UnpooledSlicedByteBuf extends AbstractUnpooledSlicedByteBuf {
|
||||
|
||||
SlicedAbstractByteBuf(AbstractByteBuf buffer, int index, int length) {
|
||||
UnpooledSlicedByteBuf(AbstractByteBuf buffer, int index, int length) {
|
||||
super(buffer, index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int capacity() {
|
||||
return maxCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractByteBuf unwrap() {
|
||||
return (AbstractByteBuf) super.unwrap();
|
@ -2918,6 +2918,54 @@ public abstract class AbstractByteBufTest {
|
||||
testDuplicateContents(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateCapacityChange() {
|
||||
testDuplicateCapacityChange(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetainedDuplicateCapacityChange() {
|
||||
testDuplicateCapacityChange(true);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testSliceCapacityChange() {
|
||||
testSliceCapacityChange(false);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testRetainedSliceCapacityChange() {
|
||||
testSliceCapacityChange(true);
|
||||
}
|
||||
|
||||
private void testDuplicateCapacityChange(boolean retainedDuplicate) {
|
||||
ByteBuf buf = releaseLater(newBuffer(8));
|
||||
ByteBuf dup = retainedDuplicate ? buf.retainedDuplicate() : buf.duplicate();
|
||||
try {
|
||||
dup.capacity(10);
|
||||
assertEquals(buf.capacity(), dup.capacity());
|
||||
dup.capacity(5);
|
||||
assertEquals(buf.capacity(), dup.capacity());
|
||||
} finally {
|
||||
if (retainedDuplicate) {
|
||||
dup.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void testSliceCapacityChange(boolean retainedSlice) {
|
||||
ByteBuf buf = releaseLater(newBuffer(8));
|
||||
ByteBuf slice = retainedSlice ? buf.retainedSlice(buf.readerIndex() + 1, 3)
|
||||
: buf.slice(buf.readerIndex() + 1, 3);
|
||||
try {
|
||||
slice.capacity(10);
|
||||
} finally {
|
||||
if (retainedSlice) {
|
||||
slice.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void testSliceOutOfBounds(boolean initRetainedSlice, boolean finalRetainedSlice, boolean indexOutOfBounds) {
|
||||
ByteBuf buf = releaseLater(newBuffer(8));
|
||||
ByteBuf slice = initRetainedSlice ? buf.retainedSlice(buf.readerIndex() + 1, 2)
|
||||
|
@ -457,7 +457,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest {
|
||||
public void testComponentMustBeSlice() {
|
||||
CompositeByteBuf buf = releaseLater(compositeBuffer());
|
||||
buf.addComponent(buffer(4).setIndex(1, 3));
|
||||
assertThat(buf.component(0), is(instanceOf(SlicedByteBuf.class)));
|
||||
assertThat(buf.component(0), is(instanceOf(AbstractUnpooledSlicedByteBuf.class)));
|
||||
assertThat(buf.component(0).capacity(), is(2));
|
||||
assertThat(buf.component(0).maxCapacity(), is(2));
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public class ByteBufDerivationTest {
|
||||
ByteBuf buf = Unpooled.buffer(8).setIndex(1, 7);
|
||||
ByteBuf slice = buf.slice(1, 7);
|
||||
|
||||
assertThat(slice, instanceOf(SlicedByteBuf.class));
|
||||
assertThat(slice, instanceOf(AbstractUnpooledSlicedByteBuf.class));
|
||||
assertThat(slice.unwrap(), sameInstance(buf));
|
||||
assertThat(slice.readerIndex(), is(0));
|
||||
assertThat(slice.writerIndex(), is(7));
|
||||
@ -53,7 +53,7 @@ public class ByteBufDerivationTest {
|
||||
ByteBuf slice2 = slice.slice(0, 6);
|
||||
|
||||
assertThat(slice2, not(sameInstance(slice)));
|
||||
assertThat(slice2, instanceOf(SlicedByteBuf.class));
|
||||
assertThat(slice2, instanceOf(AbstractUnpooledSlicedByteBuf.class));
|
||||
assertThat(slice2.unwrap(), sameInstance(buf));
|
||||
assertThat(slice2.writerIndex(), is(6));
|
||||
assertThat(slice2.capacity(), is(6));
|
||||
|
@ -126,6 +126,18 @@ public class SlicedByteBufTest extends AbstractByteBufTest {
|
||||
// ignore for SlicedByteBuf
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
@Override
|
||||
public void testDuplicateCapacityChange() {
|
||||
super.testDuplicateCapacityChange();
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
@Override
|
||||
public void testRetainedDuplicateCapacityChange() {
|
||||
super.testRetainedDuplicateCapacityChange();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReaderIndexAndMarks() {
|
||||
ByteBuf wrapped = Unpooled.buffer(16);
|
||||
@ -134,7 +146,7 @@ public class SlicedByteBufTest extends AbstractByteBufTest {
|
||||
wrapped.readerIndex(2);
|
||||
wrapped.markWriterIndex();
|
||||
wrapped.markReaderIndex();
|
||||
ByteBuf slice = new SlicedByteBuf(wrapped, 4, 4);
|
||||
ByteBuf slice = wrapped.slice(4, 4);
|
||||
assertEquals(0, slice.readerIndex());
|
||||
assertEquals(4, slice.writerIndex());
|
||||
|
||||
|
@ -17,7 +17,6 @@ package io.netty.handler.codec.http.multipart;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.SlicedByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpContent;
|
||||
@ -37,6 +36,7 @@ import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
|
||||
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TRANSFER_ENCODING;
|
||||
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/** {@link HttpPostRequestEncoder} test case. */
|
||||
public class HttpPostRequestEncoderTest {
|
||||
@ -225,11 +225,11 @@ public class HttpPostRequestEncoderTest {
|
||||
encoder.finalizeRequest();
|
||||
while (! encoder.isEndOfInput()) {
|
||||
HttpContent httpContent = encoder.readChunk((ByteBufAllocator) null);
|
||||
if (httpContent.content() instanceof SlicedByteBuf) {
|
||||
assertEquals(2, httpContent.content().refCnt());
|
||||
} else {
|
||||
assertEquals(1, httpContent.content().refCnt());
|
||||
}
|
||||
ByteBuf content = httpContent.content();
|
||||
int refCnt = content.refCnt();
|
||||
assertTrue("content: " + content + " content.unwrap(): " + content.unwrap() + " refCnt: " + refCnt,
|
||||
(content.unwrap() == content || content.unwrap() == null) && refCnt == 1 ||
|
||||
content.unwrap() != content && refCnt == 2);
|
||||
httpContent.release();
|
||||
}
|
||||
encoder.cleanFiles();
|
||||
|
@ -17,7 +17,6 @@ package io.netty.microbench.buffer;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.SlicedByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.microbench.util.AbstractMicrobenchmark;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
@ -42,7 +41,7 @@ public class SlicedByteBufBenchmark extends AbstractMicrobenchmark {
|
||||
public void setup() {
|
||||
// Use buffer sizes that will also allow to write UTF-8 without grow the buffer
|
||||
ByteBuf buffer = Unpooled.buffer(512).retain();
|
||||
slicedByteBuf = new SlicedByteBuf(buffer, 0, 256);
|
||||
slicedByteBuf = buffer.slice(0, 256);
|
||||
slicedAbstractByteBuf = buffer.slice(0, 256);
|
||||
|
||||
if (slicedByteBuf.getClass() == slicedAbstractByteBuf.getClass()) {
|
||||
|
Loading…
Reference in New Issue
Block a user