From 65c2a6ed46c163081fed5307f33489a606177f33 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Mon, 8 Jul 2013 13:32:33 +0900 Subject: [PATCH] Make ByteBuf an abstract class rather than an interface - 5% improvement in throughput (HelloWorldServer example) - Made CompositeByteBuf a concrete class (renamed from DefaultCompositeByteBuf) because there's no multiple inheritance in Java Fixes #1536 --- .../java/io/netty/buffer/AbstractByteBuf.java | 2 +- .../buffer/AbstractByteBufAllocator.java | 4 +- .../main/java/io/netty/buffer/ByteBuf.java | 287 +-- .../io/netty/buffer/CompositeByteBuf.java | 1593 ++++++++++++++--- .../netty/buffer/DefaultCompositeByteBuf.java | 1489 --------------- .../java/io/netty/buffer/EmptyByteBuf.java | 2 +- .../java/io/netty/buffer/SwappedByteBuf.java | 2 +- .../main/java/io/netty/buffer/Unpooled.java | 8 +- .../io/netty/buffer/UnreleasableByteBuf.java | 2 +- .../handler/codec/ReplayingDecoderBuffer.java | 2 +- 10 files changed, 1535 insertions(+), 1856 deletions(-) delete mode 100644 buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java diff --git a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java index 79a1ed63d6..1b972e045c 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java @@ -32,7 +32,7 @@ import java.nio.charset.Charset; /** * A skeletal implementation of a buffer. */ -public abstract class AbstractByteBuf implements ByteBuf { +public abstract class AbstractByteBuf extends ByteBuf { static final ResourceLeakDetector leakDetector = new ResourceLeakDetector(ByteBuf.class); diff --git a/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java b/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java index 8c20b540f9..e8e0ee3b17 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java @@ -153,7 +153,7 @@ public abstract class AbstractByteBufAllocator implements ByteBufAllocator { @Override public CompositeByteBuf compositeHeapBuffer(int maxNumComponents) { - return new DefaultCompositeByteBuf(this, false, maxNumComponents); + return new CompositeByteBuf(this, false, maxNumComponents); } @Override @@ -163,7 +163,7 @@ public abstract class AbstractByteBufAllocator implements ByteBufAllocator { @Override public CompositeByteBuf compositeDirectBuffer(int maxNumComponents) { - return new DefaultCompositeByteBuf(this, true, maxNumComponents); + return new CompositeByteBuf(this, true, maxNumComponents); } private static void validate(int initialCapacity, int maxCapacity) { diff --git a/buffer/src/main/java/io/netty/buffer/ByteBuf.java b/buffer/src/main/java/io/netty/buffer/ByteBuf.java index 6049f5b9eb..48a0362425 100644 --- a/buffer/src/main/java/io/netty/buffer/ByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/ByteBuf.java @@ -226,12 +226,13 @@ import java.nio.charset.UnsupportedCharsetException; * Please refer to {@link ByteBufInputStream} and * {@link ByteBufOutputStream}. */ -public interface ByteBuf extends ReferenceCounted, Comparable { +@SuppressWarnings("ClassMayBeInterface") +public abstract class ByteBuf implements ReferenceCounted, Comparable { /** * Returns the number of bytes (octets) this buffer can contain. */ - int capacity(); + public abstract int capacity(); /** * Adjusts the capacity of this buffer. If the {@code newCapacity} is less than the current @@ -239,7 +240,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * than the current capacity, the buffer is appended with unspecified data whose length is * {@code (newCapacity - currentCapacity)}. */ - ByteBuf capacity(int newCapacity); + public abstract ByteBuf capacity(int newCapacity); /** * Returns the maximum allowed capacity of this buffer. If a user attempts to increase the @@ -247,18 +248,18 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@link #ensureWritable(int)}, those methods will raise an * {@link IllegalArgumentException}. */ - int maxCapacity(); + public abstract int maxCapacity(); /** * Returns the {@link ByteBufAllocator} which created this buffer. */ - ByteBufAllocator alloc(); + public abstract ByteBufAllocator alloc(); /** * Returns the endianness * of this buffer. */ - ByteOrder order(); + public abstract ByteOrder order(); /** * Returns a buffer with the specified {@code endianness} which shares the whole region, @@ -268,25 +269,25 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * return {@code this}. This method does not modify {@code readerIndex} or {@code writerIndex} * of this buffer. */ - ByteBuf order(ByteOrder endianness); + public abstract ByteBuf order(ByteOrder endianness); /** * Return the underlying buffer instance if this buffer is a wrapper of another buffer. * * @return {@code null} if this buffer is not a wrapper */ - ByteBuf unwrap(); + public abstract ByteBuf unwrap(); /** * Returns {@code true} if and only if this buffer is backed by an * NIO direct buffer. */ - boolean isDirect(); + public abstract boolean isDirect(); /** * Returns the {@code readerIndex} of this buffer. */ - int readerIndex(); + public abstract int readerIndex(); /** * Sets the {@code readerIndex} of this buffer. @@ -296,12 +297,12 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * less than {@code 0} or * greater than {@code this.writerIndex} */ - ByteBuf readerIndex(int readerIndex); + public abstract ByteBuf readerIndex(int readerIndex); /** * Returns the {@code writerIndex} of this buffer. */ - int writerIndex(); + public abstract int writerIndex(); /** * Sets the {@code writerIndex} of this buffer. @@ -311,7 +312,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * less than {@code this.readerIndex} or * greater than {@code this.capacity} */ - ByteBuf writerIndex(int writerIndex); + public abstract ByteBuf writerIndex(int writerIndex); /** * Sets the {@code readerIndex} and {@code writerIndex} of this buffer @@ -364,50 +365,50 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code readerIndex} or if the specified {@code writerIndex} is * greater than {@code this.capacity} */ - ByteBuf setIndex(int readerIndex, int writerIndex); + public abstract ByteBuf setIndex(int readerIndex, int writerIndex); /** * Returns the number of readable bytes which is equal to * {@code (this.writerIndex - this.readerIndex)}. */ - int readableBytes(); + public abstract int readableBytes(); /** * Returns the number of writable bytes which is equal to * {@code (this.capacity - this.writerIndex)}. */ - int writableBytes(); + public abstract int writableBytes(); /** * Returns the maximum possible number of writable bytes, which is equal to * {@code (this.maxCapacity - this.writerIndex)}. */ - int maxWritableBytes(); + public abstract int maxWritableBytes(); /** * Returns {@code true} * if and only if {@code (this.writerIndex - this.readerIndex)} is greater * than {@code 0}. */ - boolean isReadable(); + public abstract boolean isReadable(); /** * Returns {@code true} if and only if this buffer contains equal to or more than the specified number of elements. */ - boolean isReadable(int size); + public abstract boolean isReadable(int size); /** * Returns {@code true} * if and only if {@code (this.capacity - this.writerIndex)} is greater * than {@code 0}. */ - boolean isWritable(); + public abstract boolean isWritable(); /** * Returns {@code true} if and only if this buffer has enough room to allow writing the specified number of * elements. */ - boolean isWritable(int size); + public abstract boolean isWritable(int size); /** * Sets the {@code readerIndex} and {@code writerIndex} of this buffer to @@ -418,7 +419,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * from that of NIO buffer, which sets the {@code limit} to * the {@code capacity} of the buffer. */ - ByteBuf clear(); + public abstract ByteBuf clear(); /** * Marks the current {@code readerIndex} in this buffer. You can @@ -426,7 +427,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code readerIndex} by calling {@link #resetReaderIndex()}. * The initial value of the marked {@code readerIndex} is {@code 0}. */ - ByteBuf markReaderIndex(); + public abstract ByteBuf markReaderIndex(); /** * Repositions the current {@code readerIndex} to the marked @@ -436,7 +437,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the current {@code writerIndex} is less than the marked * {@code readerIndex} */ - ByteBuf resetReaderIndex(); + public abstract ByteBuf resetReaderIndex(); /** * Marks the current {@code writerIndex} in this buffer. You can @@ -444,7 +445,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code writerIndex} by calling {@link #resetWriterIndex()}. * The initial value of the marked {@code writerIndex} is {@code 0}. */ - ByteBuf markWriterIndex(); + public abstract ByteBuf markWriterIndex(); /** * Repositions the current {@code writerIndex} to the marked @@ -454,7 +455,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the current {@code readerIndex} is greater than the marked * {@code writerIndex} */ - ByteBuf resetWriterIndex(); + public abstract ByteBuf resetWriterIndex(); /** * Discards the bytes between the 0th index and {@code readerIndex}. @@ -464,7 +465,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { *

* Please refer to the class documentation for more detailed explanation. */ - ByteBuf discardReadBytes(); + public abstract ByteBuf discardReadBytes(); /** * Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard @@ -472,7 +473,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * overall memory bandwidth consumption at the cost of potentially additional memory * consumption. */ - ByteBuf discardSomeReadBytes(); + public abstract ByteBuf discardSomeReadBytes(); /** * Makes sure the number of {@linkplain #writableBytes() the writable bytes} @@ -485,7 +486,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()} */ - ByteBuf ensureWritable(int minWritableBytes); + public abstract ByteBuf ensureWritable(int minWritableBytes); /** * Tries to make sure the number of {@linkplain #writableBytes() the writable bytes} @@ -506,7 +507,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code 3} if the buffer does not have enough bytes, but its capacity has been * increased to its maximum. */ - int ensureWritable(int minWritableBytes, boolean force); + public abstract int ensureWritable(int minWritableBytes, boolean force); /** * Gets a boolean at the specified absolute (@code index) in this buffer. @@ -517,7 +518,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ - boolean getBoolean(int index); + public abstract boolean getBoolean(int index); /** * Gets a byte at the specified absolute {@code index} in this buffer. @@ -528,7 +529,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ - byte getByte(int index); + public abstract byte getByte(int index); /** * Gets an unsigned byte at the specified absolute {@code index} in this @@ -539,7 +540,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ - short getUnsignedByte(int index); + public abstract short getUnsignedByte(int index); /** * Gets a 16-bit short integer at the specified absolute {@code index} in @@ -550,7 +551,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ - short getShort(int index); + public abstract short getShort(int index); /** * Gets an unsigned 16-bit short integer at the specified absolute @@ -561,7 +562,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ - int getUnsignedShort(int index); + public abstract int getUnsignedShort(int index); /** * Gets a 24-bit medium integer at the specified absolute {@code index} in @@ -572,7 +573,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ - int getMedium(int index); + public abstract int getMedium(int index); /** * Gets an unsigned 24-bit medium integer at the specified absolute @@ -583,7 +584,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ - int getUnsignedMedium(int index); + public abstract int getUnsignedMedium(int index); /** * Gets a 32-bit integer at the specified absolute {@code index} in @@ -594,7 +595,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ - int getInt(int index); + public abstract int getInt(int index); /** * Gets an unsigned 32-bit integer at the specified absolute {@code index} @@ -605,7 +606,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ - long getUnsignedInt(int index); + public abstract long getUnsignedInt(int index); /** * Gets a 64-bit long integer at the specified absolute {@code index} in @@ -616,7 +617,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ - long getLong(int index); + public abstract long getLong(int index); /** * Gets a 2-byte UTF-16 character at the specified absolute @@ -627,7 +628,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ - char getChar(int index); + public abstract char getChar(int index); /** * Gets a 32-bit floating point number at the specified absolute @@ -638,7 +639,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ - float getFloat(int index); + public abstract float getFloat(int index); /** * Gets a 64-bit floating point number at the specified absolute @@ -649,7 +650,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ - double getDouble(int index); + public abstract double getDouble(int index); /** * Transfers this buffer's data to the specified destination starting at @@ -667,7 +668,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code index + dst.writableBytes} is greater than * {@code this.capacity} */ - ByteBuf getBytes(int index, ByteBuf dst); + public abstract ByteBuf getBytes(int index, ByteBuf dst); /** * Transfers this buffer's data to the specified destination starting at @@ -687,7 +688,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code this.capacity}, or * if {@code length} is greater than {@code dst.writableBytes} */ - ByteBuf getBytes(int index, ByteBuf dst, int length); + public abstract ByteBuf getBytes(int index, ByteBuf dst, int length); /** * Transfers this buffer's data to the specified destination starting at @@ -706,7 +707,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code dstIndex + length} is greater than * {@code dst.capacity} */ - ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length); + public abstract ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at @@ -719,7 +720,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code index + dst.length} is greater than * {@code this.capacity} */ - ByteBuf getBytes(int index, byte[] dst); + public abstract ByteBuf getBytes(int index, byte[] dst); /** * Transfers this buffer's data to the specified destination starting at @@ -738,7 +739,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code dstIndex + length} is greater than * {@code dst.length} */ - ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length); + public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at @@ -752,7 +753,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code index + dst.remaining()} is greater than * {@code this.capacity} */ - ByteBuf getBytes(int index, ByteBuffer dst); + public abstract ByteBuf getBytes(int index, ByteBuffer dst); /** * Transfers this buffer's data to the specified stream starting at the @@ -769,7 +770,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IOException * if the specified stream threw an exception during I/O */ - ByteBuf getBytes(int index, OutputStream out, int length) throws IOException; + public abstract ByteBuf getBytes(int index, OutputStream out, int length) throws IOException; /** * Transfers this buffer's data to the specified channel starting at the @@ -788,7 +789,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IOException * if the specified channel threw an exception during I/O */ - int getBytes(int index, GatheringByteChannel out, int length) throws IOException; + public abstract int getBytes(int index, GatheringByteChannel out, int length) throws IOException; /** * Sets the specified boolean at the specified absolute {@code index} in this @@ -800,7 +801,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ - ByteBuf setBoolean(int index, boolean value); + public abstract ByteBuf setBoolean(int index, boolean value); /** * Sets the specified byte at the specified absolute {@code index} in this @@ -812,7 +813,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 1} is greater than {@code this.capacity} */ - ByteBuf setByte(int index, int value); + public abstract ByteBuf setByte(int index, int value); /** * Sets the specified 16-bit short integer at the specified absolute @@ -825,7 +826,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ - ByteBuf setShort(int index, int value); + public abstract ByteBuf setShort(int index, int value); /** * Sets the specified 24-bit medium integer at the specified absolute @@ -838,7 +839,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 3} is greater than {@code this.capacity} */ - ByteBuf setMedium(int index, int value); + public abstract ByteBuf setMedium(int index, int value); /** * Sets the specified 32-bit integer at the specified absolute @@ -850,7 +851,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ - ByteBuf setInt(int index, int value); + public abstract ByteBuf setInt(int index, int value); /** * Sets the specified 64-bit long integer at the specified absolute @@ -862,7 +863,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ - ByteBuf setLong(int index, long value); + public abstract ByteBuf setLong(int index, long value); /** * Sets the specified 2-byte UTF-16 character at the specified absolute @@ -875,7 +876,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 2} is greater than {@code this.capacity} */ - ByteBuf setChar(int index, int value); + public abstract ByteBuf setChar(int index, int value); /** * Sets the specified 32-bit floating-point number at the specified @@ -887,7 +888,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 4} is greater than {@code this.capacity} */ - ByteBuf setFloat(int index, float value); + public abstract ByteBuf setFloat(int index, float value); /** * Sets the specified 64-bit floating-point number at the specified @@ -899,7 +900,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * {@code index + 8} is greater than {@code this.capacity} */ - ByteBuf setDouble(int index, double value); + public abstract ByteBuf setDouble(int index, double value); /** * Transfers the specified source buffer's data to this buffer starting at @@ -917,7 +918,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code index + src.readableBytes} is greater than * {@code this.capacity} */ - ByteBuf setBytes(int index, ByteBuf src); + public abstract ByteBuf setBytes(int index, ByteBuf src); /** * Transfers the specified source buffer's data to this buffer starting at @@ -937,7 +938,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code this.capacity}, or * if {@code length} is greater than {@code src.readableBytes} */ - ByteBuf setBytes(int index, ByteBuf src, int length); + public abstract ByteBuf setBytes(int index, ByteBuf src, int length); /** * Transfers the specified source buffer's data to this buffer starting at @@ -956,7 +957,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code srcIndex + length} is greater than * {@code src.capacity} */ - ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length); + public abstract ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length); /** * Transfers the specified source array's data to this buffer starting at @@ -969,7 +970,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code index + src.length} is greater than * {@code this.capacity} */ - ByteBuf setBytes(int index, byte[] src); + public abstract ByteBuf setBytes(int index, byte[] src); /** * Transfers the specified source array's data to this buffer starting at @@ -984,7 +985,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code this.capacity}, or * if {@code srcIndex + length} is greater than {@code src.length} */ - ByteBuf setBytes(int index, byte[] src, int srcIndex, int length); + public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length); /** * Transfers the specified source buffer's data to this buffer starting at @@ -998,7 +999,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code index + src.remaining()} is greater than * {@code this.capacity} */ - ByteBuf setBytes(int index, ByteBuffer src); + public abstract ByteBuf setBytes(int index, ByteBuffer src); /** * Transfers the content of the specified source stream to this buffer @@ -1017,7 +1018,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IOException * if the specified stream threw an exception during I/O */ - int setBytes(int index, InputStream in, int length) throws IOException; + public abstract int setBytes(int index, InputStream in, int length) throws IOException; /** * Transfers the content of the specified source channel to this buffer @@ -1036,7 +1037,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IOException * if the specified channel threw an exception during I/O */ - int setBytes(int index, ScatteringByteChannel in, int length) throws IOException; + public abstract int setBytes(int index, ScatteringByteChannel in, int length) throws IOException; /** * Fills this buffer with NUL (0x00) starting at the specified @@ -1050,7 +1051,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified {@code index} is less than {@code 0} or * if {@code index + length} is greater than {@code this.capacity} */ - ByteBuf setZero(int index, int length); + public abstract ByteBuf setZero(int index, int length); /** * Gets a boolean at the current {@code readerIndex} and increases @@ -1059,7 +1060,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 1} */ - boolean readBoolean(); + public abstract boolean readBoolean(); /** * Gets a byte at the current {@code readerIndex} and increases @@ -1068,7 +1069,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 1} */ - byte readByte(); + public abstract byte readByte(); /** * Gets an unsigned byte at the current {@code readerIndex} and increases @@ -1077,7 +1078,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 1} */ - short readUnsignedByte(); + public abstract short readUnsignedByte(); /** * Gets a 16-bit short integer at the current {@code readerIndex} @@ -1086,7 +1087,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 2} */ - short readShort(); + public abstract short readShort(); /** * Gets an unsigned 16-bit short integer at the current {@code readerIndex} @@ -1095,7 +1096,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 2} */ - int readUnsignedShort(); + public abstract int readUnsignedShort(); /** * Gets a 24-bit medium integer at the current {@code readerIndex} @@ -1104,7 +1105,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 3} */ - int readMedium(); + public abstract int readMedium(); /** * Gets an unsigned 24-bit medium integer at the current {@code readerIndex} @@ -1113,7 +1114,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 3} */ - int readUnsignedMedium(); + public abstract int readUnsignedMedium(); /** * Gets a 32-bit integer at the current {@code readerIndex} @@ -1122,7 +1123,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 4} */ - int readInt(); + public abstract int readInt(); /** * Gets an unsigned 32-bit integer at the current {@code readerIndex} @@ -1131,7 +1132,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 4} */ - long readUnsignedInt(); + public abstract long readUnsignedInt(); /** * Gets a 64-bit integer at the current {@code readerIndex} @@ -1140,7 +1141,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 8} */ - long readLong(); + public abstract long readLong(); /** * Gets a 2-byte UTF-16 character at the current {@code readerIndex} @@ -1149,7 +1150,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 2} */ - char readChar(); + public abstract char readChar(); /** * Gets a 32-bit floating point number at the current {@code readerIndex} @@ -1158,7 +1159,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 4} */ - float readFloat(); + public abstract float readFloat(); /** * Gets a 64-bit floating point number at the current {@code readerIndex} @@ -1167,7 +1168,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 8} */ - double readDouble(); + public abstract double readDouble(); /** * Transfers this buffer's data to a newly created buffer starting at @@ -1183,7 +1184,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ - ByteBuf readBytes(int length); + public abstract ByteBuf readBytes(int length); /** * Returns a new slice of this buffer's sub-region starting at the current @@ -1197,7 +1198,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ - ByteBuf readSlice(int length); + public abstract ByteBuf readSlice(int length); /** * Transfers this buffer's data to the specified destination starting at @@ -1213,7 +1214,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code dst.writableBytes} is greater than * {@code this.readableBytes} */ - ByteBuf readBytes(ByteBuf dst); + public abstract ByteBuf readBytes(ByteBuf dst); /** * Transfers this buffer's data to the specified destination starting at @@ -1228,7 +1229,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code length} is greater than {@code this.readableBytes} or * if {@code length} is greater than {@code dst.writableBytes} */ - ByteBuf readBytes(ByteBuf dst, int length); + public abstract ByteBuf readBytes(ByteBuf dst, int length); /** * Transfers this buffer's data to the specified destination starting at @@ -1244,7 +1245,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code dstIndex + length} is greater than * {@code dst.capacity} */ - ByteBuf readBytes(ByteBuf dst, int dstIndex, int length); + public abstract ByteBuf readBytes(ByteBuf dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at @@ -1254,7 +1255,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code dst.length} is greater than {@code this.readableBytes} */ - ByteBuf readBytes(byte[] dst); + public abstract ByteBuf readBytes(byte[] dst); /** * Transfers this buffer's data to the specified destination starting at @@ -1269,7 +1270,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code length} is greater than {@code this.readableBytes}, or * if {@code dstIndex + length} is greater than {@code dst.length} */ - ByteBuf readBytes(byte[] dst, int dstIndex, int length); + public abstract ByteBuf readBytes(byte[] dst, int dstIndex, int length); /** * Transfers this buffer's data to the specified destination starting at @@ -1281,7 +1282,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code dst.remaining()} is greater than * {@code this.readableBytes} */ - ByteBuf readBytes(ByteBuffer dst); + public abstract ByteBuf readBytes(ByteBuffer dst); /** * Transfers this buffer's data to the specified stream starting at the @@ -1294,7 +1295,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IOException * if the specified stream threw an exception during I/O */ - ByteBuf readBytes(OutputStream out, int length) throws IOException; + public abstract ByteBuf readBytes(OutputStream out, int length) throws IOException; /** * Transfers this buffer's data to the specified stream starting at the @@ -1309,7 +1310,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IOException * if the specified channel threw an exception during I/O */ - int readBytes(GatheringByteChannel out, int length) throws IOException; + public abstract int readBytes(GatheringByteChannel out, int length) throws IOException; /** * Increases the current {@code readerIndex} by the specified @@ -1318,7 +1319,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ - ByteBuf skipBytes(int length); + public abstract ByteBuf skipBytes(int length); /** * Sets the specified boolean at the current {@code writerIndex} @@ -1327,7 +1328,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 1} */ - ByteBuf writeBoolean(boolean value); + public abstract ByteBuf writeBoolean(boolean value); /** * Sets the specified byte at the current {@code writerIndex} @@ -1337,7 +1338,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 1} */ - ByteBuf writeByte(int value); + public abstract ByteBuf writeByte(int value); /** * Sets the specified 16-bit short integer at the current @@ -1347,7 +1348,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 2} */ - ByteBuf writeShort(int value); + public abstract ByteBuf writeShort(int value); /** * Sets the specified 24-bit medium integer at the current @@ -1357,7 +1358,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 3} */ - ByteBuf writeMedium(int value); + public abstract ByteBuf writeMedium(int value); /** * Sets the specified 32-bit integer at the current {@code writerIndex} @@ -1366,7 +1367,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 4} */ - ByteBuf writeInt(int value); + public abstract ByteBuf writeInt(int value); /** * Sets the specified 64-bit long integer at the current @@ -1376,7 +1377,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 8} */ - ByteBuf writeLong(long value); + public abstract ByteBuf writeLong(long value); /** * Sets the specified 2-byte UTF-16 character at the current @@ -1386,7 +1387,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 2} */ - ByteBuf writeChar(int value); + public abstract ByteBuf writeChar(int value); /** * Sets the specified 32-bit floating point number at the current @@ -1396,7 +1397,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 4} */ - ByteBuf writeFloat(float value); + public abstract ByteBuf writeFloat(float value); /** * Sets the specified 64-bit floating point number at the current @@ -1406,7 +1407,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 8} */ - ByteBuf writeDouble(double value); + public abstract ByteBuf writeDouble(double value); /** * Transfers the specified source buffer's data to this buffer starting at @@ -1422,7 +1423,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code src.readableBytes} is greater than * {@code this.writableBytes} */ - ByteBuf writeBytes(ByteBuf src); + public abstract ByteBuf writeBytes(ByteBuf src); /** * Transfers the specified source buffer's data to this buffer starting at @@ -1439,7 +1440,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code length} is greater than {@code this.writableBytes} or * if {@code length} is greater then {@code src.readableBytes} */ - ByteBuf writeBytes(ByteBuf src, int length); + public abstract ByteBuf writeBytes(ByteBuf src, int length); /** * Transfers the specified source buffer's data to this buffer starting at @@ -1455,7 +1456,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code src.capacity}, or * if {@code length} is greater than {@code this.writableBytes} */ - ByteBuf writeBytes(ByteBuf src, int srcIndex, int length); + public abstract ByteBuf writeBytes(ByteBuf src, int srcIndex, int length); /** * Transfers the specified source array's data to this buffer starting at @@ -1465,7 +1466,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code src.length} is greater than {@code this.writableBytes} */ - ByteBuf writeBytes(byte[] src); + public abstract ByteBuf writeBytes(byte[] src); /** * Transfers the specified source array's data to this buffer starting at @@ -1481,7 +1482,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code src.length}, or * if {@code length} is greater than {@code this.writableBytes} */ - ByteBuf writeBytes(byte[] src, int srcIndex, int length); + public abstract ByteBuf writeBytes(byte[] src, int srcIndex, int length); /** * Transfers the specified source buffer's data to this buffer starting at @@ -1493,7 +1494,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if {@code src.remaining()} is greater than * {@code this.writableBytes} */ - ByteBuf writeBytes(ByteBuffer src); + public abstract ByteBuf writeBytes(ByteBuffer src); /** * Transfers the content of the specified stream to this buffer @@ -1509,7 +1510,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IOException * if the specified stream threw an exception during I/O */ - int writeBytes(InputStream in, int length) throws IOException; + public abstract int writeBytes(InputStream in, int length) throws IOException; /** * Transfers the content of the specified channel to this buffer @@ -1525,7 +1526,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IOException * if the specified channel threw an exception during I/O */ - int writeBytes(ScatteringByteChannel in, int length) throws IOException; + public abstract int writeBytes(ScatteringByteChannel in, int length) throws IOException; /** * Fills this buffer with NUL (0x00) starting at the current @@ -1537,7 +1538,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.writableBytes} */ - ByteBuf writeZero(int length); + public abstract ByteBuf writeZero(int length); /** * Locates the first occurrence of the specified {@code value} in this @@ -1553,7 +1554,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @return the absolute index of the first occurrence if found. * {@code -1} otherwise. */ - int indexOf(int fromIndex, int toIndex, byte value); + public abstract int indexOf(int fromIndex, int toIndex, byte value); /** * Locates the first occurrence of the specified {@code value} in this @@ -1566,7 +1567,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @return the number of bytes between the current {@code readerIndex} * and the first occurrence if found. {@code -1} otherwise. */ - int bytesBefore(byte value); + public abstract int bytesBefore(byte value); /** * Locates the first occurrence of the specified {@code value} in this @@ -1582,7 +1583,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ - int bytesBefore(int length, byte value); + public abstract int bytesBefore(int length, byte value); /** * Locates the first occurrence of the specified {@code value} in this @@ -1598,7 +1599,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws IndexOutOfBoundsException * if {@code index + length} is greater than {@code this.capacity} */ - int bytesBefore(int index, int length, byte value); + public abstract int bytesBefore(int index, int length, byte value); /** * Iterates over the readable bytes of this buffer with the specified {@code processor} in ascending order. @@ -1606,7 +1607,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @return {@code -1} if the processor iterated to or beyond the end of the readable bytes. * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. */ - int forEachByte(ByteBufProcessor processor); + public abstract int forEachByte(ByteBufProcessor processor); /** * Iterates over the specified area of this buffer with the specified {@code processor} in ascending order. @@ -1615,7 +1616,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @return {@code -1} if the processor iterated to or beyond the end of the specified area. * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. */ - int forEachByte(int index, int length, ByteBufProcessor processor); + public abstract int forEachByte(int index, int length, ByteBufProcessor processor); /** * Iterates over the readable bytes of this buffer with the specified {@code processor} in descending order. @@ -1623,7 +1624,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes. * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. */ - int forEachByteDesc(ByteBufProcessor processor); + public abstract int forEachByteDesc(ByteBufProcessor processor); /** * Iterates over the specified area of this buffer with the specified {@code processor} in descending order. @@ -1633,7 +1634,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @return {@code -1} if the processor iterated to or beyond the beginning of the specified area. * The last-visited index If the {@link ByteBufProcessor#process(byte)} returned {@code false}. */ - int forEachByteDesc(int index, int length, ByteBufProcessor processor); + public abstract int forEachByteDesc(int index, int length, ByteBufProcessor processor); /** * Returns a copy of this buffer's readable bytes. Modifying the content @@ -1642,7 +1643,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. */ - ByteBuf copy(); + public abstract ByteBuf copy(); /** * Returns a copy of this buffer's sub-region. Modifying the content of @@ -1650,7 +1651,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. */ - ByteBuf copy(int index, int length); + public abstract ByteBuf copy(int index, int length); /** * Returns a slice of this buffer's readable bytes. Modifying the content @@ -1660,7 +1661,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. */ - ByteBuf slice(); + public abstract ByteBuf slice(); /** * Returns a slice of this buffer's sub-region. Modifying the content of @@ -1669,7 +1670,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. */ - ByteBuf slice(int index, int length); + public abstract ByteBuf slice(int index, int length); /** * Returns a buffer which shares the whole region of this buffer. @@ -1679,7 +1680,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. */ - ByteBuf duplicate(); + public abstract ByteBuf duplicate(); /** * Returns the maximum number of NIO {@link ByteBuffer}s that consist this buffer. Note that {@link #nioBuffers()} @@ -1694,7 +1695,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @see #nioBuffers() * @see #nioBuffers(int, int) */ - int nioBufferCount(); + public abstract int nioBufferCount(); /** * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}. The returned buffer @@ -1712,7 +1713,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @see #nioBuffers() * @see #nioBuffers(int, int) */ - ByteBuffer nioBuffer(); + public abstract ByteBuffer nioBuffer(); /** * Exposes this buffer's sub-region as an NIO {@link ByteBuffer}. The returned buffer @@ -1729,12 +1730,12 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @see #nioBuffers() * @see #nioBuffers(int, int) */ - ByteBuffer nioBuffer(int index, int length); + public abstract ByteBuffer nioBuffer(int index, int length); /** * Internal use only: Exposes the internal NIO buffer. */ - ByteBuffer internalNioBuffer(int index, int length); + public abstract ByteBuffer internalNioBuffer(int index, int length); /** * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}'s. The returned buffer @@ -1752,7 +1753,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @see #nioBuffer() * @see #nioBuffer(int, int) */ - ByteBuffer[] nioBuffers(); + public abstract ByteBuffer[] nioBuffers(); /** * Exposes this buffer's bytes as an NIO {@link ByteBuffer}'s for the specified index and length @@ -1769,14 +1770,14 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @see #nioBuffer() * @see #nioBuffer(int, int) */ - ByteBuffer[] nioBuffers(int index, int length); + public abstract ByteBuffer[] nioBuffers(int index, int length); /** * Returns {@code true} if and only if this buffer has a backing byte array. * If this method returns true, you can safely call {@link #array()} and * {@link #arrayOffset()}. */ - boolean hasArray(); + public abstract boolean hasArray(); /** * Returns the backing byte array of this buffer. @@ -1784,7 +1785,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws UnsupportedOperationException * if there no accessible backing byte array */ - byte[] array(); + public abstract byte[] array(); /** * Returns the offset of the first byte within the backing byte array of @@ -1793,13 +1794,13 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws UnsupportedOperationException * if there no accessible backing byte array */ - int arrayOffset(); + public abstract 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(); + public abstract boolean hasMemoryAddress(); /** * Returns the low-level memory address that point to the first byte of ths backing data. @@ -1807,7 +1808,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * @throws UnsupportedOperationException * if this buffer does not support accessing the low-level memory address */ - long memoryAddress(); + public abstract long memoryAddress(); /** * Decodes this buffer's readable bytes into a string with the specified @@ -1820,14 +1821,14 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * if the specified character set name is not supported by the * current VM */ - String toString(Charset charset); + public abstract String toString(Charset charset); /** * Decodes this buffer's sub-region into a string with the specified * character set. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. */ - String toString(int index, int length, Charset charset); + public abstract String toString(int index, int length, Charset charset); /** * Returns a hash code which was calculated from the content of this @@ -1836,7 +1837,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * return the same value. */ @Override - int hashCode(); + public abstract int hashCode(); /** * Determines if the content of the specified buffer is identical to the @@ -1851,7 +1852,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@link ByteBuf} type. */ @Override - boolean equals(Object obj); + public abstract boolean equals(Object obj); /** * Compares the content of the specified buffer to the content of this @@ -1860,7 +1861,7 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@code memcmp} and {@link String#compareTo(String)}. */ @Override - int compareTo(ByteBuf buffer); + public abstract int compareTo(ByteBuf buffer); /** * Returns the string representation of this buffer. This method does not @@ -1869,11 +1870,11 @@ public interface ByteBuf extends ReferenceCounted, Comparable { * {@link #writerIndex()} and {@link #capacity()}. */ @Override - String toString(); + public abstract String toString(); @Override - ByteBuf retain(int increment); + public abstract ByteBuf retain(int increment); @Override - ByteBuf retain(); + public abstract ByteBuf retain(); } diff --git a/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java b/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java index 9dad4ffabd..2e171fef9b 100644 --- a/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java @@ -15,15 +15,89 @@ */ package io.netty.buffer; +import io.netty.util.ResourceLeak; +import io.netty.util.internal.EmptyArrays; +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.channels.GatheringByteChannel; +import java.nio.channels.ScatteringByteChannel; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; import java.util.List; +import java.util.ListIterator; /** - * A {@link ByteBuf} which is composed out of other {@link ByteBuf}s. + * A virtual buffer which shows multiple buffers as a single merged buffer. It is recommended to use + * {@link ByteBufAllocator#compositeBuffer()} or {@link Unpooled#wrappedBuffer(ByteBuf...)} instead of calling the + * constructor explicitly. */ -public interface CompositeByteBuf extends ByteBuf, Iterable { +public class CompositeByteBuf extends AbstractReferenceCountedByteBuf { + + private final ResourceLeak leak; + private final ByteBufAllocator alloc; + private final boolean direct; + private final List components = new ArrayList(); + private final int maxNumComponents; + + private boolean freed; + + public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents) { + super(Integer.MAX_VALUE); + if (alloc == null) { + throw new NullPointerException("alloc"); + } + this.alloc = alloc; + this.direct = direct; + this.maxNumComponents = maxNumComponents; + leak = leakDetector.open(this); + } + + public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf... buffers) { + super(Integer.MAX_VALUE); + if (alloc == null) { + throw new NullPointerException("alloc"); + } + if (maxNumComponents < 2) { + throw new IllegalArgumentException( + "maxNumComponents: " + maxNumComponents + " (expected: >= 2)"); + } + + this.alloc = alloc; + this.direct = direct; + this.maxNumComponents = maxNumComponents; + + addComponents0(0, buffers); + consolidateIfNeeded(); + setIndex(0, capacity()); + leak = leakDetector.open(this); + } + + public CompositeByteBuf( + ByteBufAllocator alloc, boolean direct, int maxNumComponents, Iterable buffers) { + super(Integer.MAX_VALUE); + if (alloc == null) { + throw new NullPointerException("alloc"); + } + if (maxNumComponents < 2) { + throw new IllegalArgumentException( + "maxNumComponents: " + maxNumComponents + " (expected: >= 2)"); + } + + this.alloc = alloc; + this.direct = direct; + this.maxNumComponents = maxNumComponents; + addComponents0(0, buffers); + consolidateIfNeeded(); + setIndex(0, capacity()); + leak = leakDetector.open(this); + } /** * Add the given {@link ByteBuf}. @@ -31,10 +105,41 @@ public interface CompositeByteBuf extends ByteBuf, Iterable { * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. * If you need to have it increased you need to handle it by your own. * - * @param buffer the {@link ByteBuf} to add - * @return self this instance + * @param buffer the {@link ByteBuf} to add */ - CompositeByteBuf addComponent(ByteBuf buffer); + public CompositeByteBuf addComponent(ByteBuf buffer) { + addComponent0(components.size(), buffer); + consolidateIfNeeded(); + return this; + } + + /** + * Add the given {@link ByteBuf}s. + * + * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. + * If you need to have it increased you need to handle it by your own. + * + * @param buffers the {@link ByteBuf}s to add + */ + public CompositeByteBuf addComponents(ByteBuf... buffers) { + addComponents0(components.size(), buffers); + consolidateIfNeeded(); + return this; + } + + /** + * Add the given {@link ByteBuf}s. + * + * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. + * If you need to have it increased you need to handle it by your own. + * + * @param buffers the {@link ByteBuf}s to add + */ + public CompositeByteBuf addComponents(Iterable buffers) { + addComponents0(components.size(), buffers); + consolidateIfNeeded(); + return this; + } /** * Add the given {@link ByteBuf} on the specific index. @@ -42,38 +147,44 @@ public interface CompositeByteBuf extends ByteBuf, Iterable { * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. * If you need to have it increased you need to handle it by your own. * - * @param cIndex - * the index on which the {@link ByteBuf} will be added - * @param buffer - * the {@link ByteBuf} to add - * @return self - * this instance - * @throws IndexOutOfBoundsException - * if the index is invalid + * @param cIndex the index on which the {@link ByteBuf} will be added + * @param buffer the {@link ByteBuf} to add */ - CompositeByteBuf addComponent(int cIndex, ByteBuf buffer); + public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) { + addComponent0(cIndex, buffer); + consolidateIfNeeded(); + return this; + } - /** - * Add the given {@link ByteBuf}s. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param buffers the {@link ByteBuf}s to add - * @return self this instance - */ - CompositeByteBuf addComponents(ByteBuf... buffers); + private int addComponent0(int cIndex, ByteBuf buffer) { + checkComponentIndex(cIndex); - /** - * Add the given {@link ByteBuf}s. - * - * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. - * If you need to have it increased you need to handle it by your own. - * - * @param buffers the {@link ByteBuf}s to add - * @return self this instance - */ - CompositeByteBuf addComponents(Iterable buffers); + if (buffer == null) { + throw new NullPointerException("buffer"); + } + + int readableBytes = buffer.readableBytes(); + if (readableBytes == 0) { + return cIndex; + } + + // No need to consolidate - just add a component to the list. + Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice()); + if (cIndex == components.size()) { + components.add(c); + if (cIndex == 0) { + c.endOffset = readableBytes; + } else { + Component prev = components.get(cIndex - 1); + c.offset = prev.endOffset; + c.endOffset = c.offset + readableBytes; + } + } else { + components.add(cIndex, c); + updateComponentOffsets(cIndex); + } + return cIndex; + } /** * Add the given {@link ByteBuf}s on the specific index @@ -81,17 +192,51 @@ public interface CompositeByteBuf extends ByteBuf, Iterable { * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. * If you need to have it increased you need to handle it by your own. * - * @param cIndex - * the index on which the {@link ByteBuf} will be added. - * @param buffers - * the {@link ByteBuf}s to add - * @return self - * this instance - * @throws IndexOutOfBoundsException - * if the index is invalid - * + * @param cIndex the index on which the {@link ByteBuf} will be added. + * @param buffers the {@link ByteBuf}s to add */ - CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers); + public CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers) { + addComponents0(cIndex, buffers); + consolidateIfNeeded(); + return this; + } + + private int addComponents0(int cIndex, ByteBuf... buffers) { + checkComponentIndex(cIndex); + + if (buffers == null) { + throw new NullPointerException("buffers"); + } + + int readableBytes = 0; + for (ByteBuf b: buffers) { + if (b == null) { + break; + } + readableBytes += b.readableBytes(); + } + + if (readableBytes == 0) { + return cIndex; + } + + // No need for consolidation + for (ByteBuf b: buffers) { + if (b == null) { + break; + } + if (b.isReadable()) { + cIndex = addComponent0(cIndex, b) + 1; + int size = components.size(); + if (cIndex > size) { + cIndex = size; + } + } else { + b.release(); + } + } + return cIndex; + } /** * Add the given {@link ByteBuf}s on the specific index @@ -99,313 +244,1335 @@ public interface CompositeByteBuf extends ByteBuf, Iterable { * Be aware that this method does not increase the {@code writerIndex} of the {@link CompositeByteBuf}. * If you need to have it increased you need to handle it by your own. * - * @param cIndex - * the index on which the {@link ByteBuf} will be added. - * @param buffers - * the {@link ByteBuf}s to add - * @return self - * this instance - * @throws IndexOutOfBoundsException - * if the index is invalid + * @param cIndex the index on which the {@link ByteBuf} will be added. + * @param buffers the {@link ByteBuf}s to add */ - CompositeByteBuf addComponents(int cIndex, Iterable buffers); + public CompositeByteBuf addComponents(int cIndex, Iterable buffers) { + addComponents0(cIndex, buffers); + consolidateIfNeeded(); + return this; + } + + private int addComponents0(int cIndex, Iterable buffers) { + if (buffers == null) { + throw new NullPointerException("buffers"); + } + + if (buffers instanceof ByteBuf) { + // If buffers also implements ByteBuf (e.g. CompositeByteBuf), it has to go to addComponent(ByteBuf). + return addComponent0(cIndex, (ByteBuf) buffers); + } + + if (!(buffers instanceof Collection)) { + List list = new ArrayList(); + for (ByteBuf b: buffers) { + list.add(b); + } + buffers = list; + } + + Collection col = (Collection) buffers; + return addComponents0(cIndex, col.toArray(new ByteBuf[col.size()])); + } + + /** + * This should only be called as last operation from a method as this may adjust the underlying + * array of components and so affect the index etc. + */ + private void consolidateIfNeeded() { + // Consolidate if the number of components will exceed the allowed maximum by the current + // operation. + final int numComponents = components.size(); + if (numComponents > maxNumComponents) { + final int capacity = components.get(numComponents - 1).endOffset; + + ByteBuf consolidated = allocBuffer(capacity); + + // We're not using foreach to avoid creating an iterator. + // noinspection ForLoopReplaceableByForEach + for (int i = 0; i < numComponents; i ++) { + Component c = components.get(i); + ByteBuf b = c.buf; + consolidated.writeBytes(b); + c.freeIfNecessary(); + } + Component c = new Component(consolidated); + c.endOffset = c.length; + components.clear(); + components.add(c); + } + } + + private void checkComponentIndex(int cIndex) { + assert !freed; + if (cIndex < 0 || cIndex > components.size()) { + throw new IndexOutOfBoundsException(String.format( + "cIndex: %d (expected: >= 0 && <= numComponents(%d))", + cIndex, components.size())); + } + } + + private void checkComponentIndex(int cIndex, int numComponents) { + assert !freed; + if (cIndex < 0 || cIndex + numComponents > components.size()) { + throw new IndexOutOfBoundsException(String.format( + "cIndex: %d, numComponents: %d " + + "(expected: cIndex >= 0 && cIndex + numComponents <= totalNumComponents(%d))", + cIndex, numComponents, components.size())); + } + } + + private void updateComponentOffsets(int cIndex) { + if (components.isEmpty()) { + return; + } + + Component c = components.get(cIndex); + if (cIndex == 0) { + c.offset = 0; + c.endOffset = c.length; + cIndex ++; + } + + for (int i = cIndex; i < components.size(); i ++) { + Component prev = components.get(i - 1); + Component cur = components.get(i); + cur.offset = prev.endOffset; + cur.endOffset = cur.offset + cur.length; + } + } /** * Remove the {@link ByteBuf} from the given index. * - * @param cIndex - * the index on from which the {@link ByteBuf} will be remove - * @return self - * this instance - * @throws IndexOutOfBoundsException - * if the index is invalid + * @param cIndex the index on from which the {@link ByteBuf} will be remove */ - CompositeByteBuf removeComponent(int cIndex); + public CompositeByteBuf removeComponent(int cIndex) { + checkComponentIndex(cIndex); + components.remove(cIndex).freeIfNecessary(); + updateComponentOffsets(cIndex); + return this; + } /** * Remove the number of {@link ByteBuf}s starting from the given index. * - * @param cIndex - * the index on which the {@link ByteBuf}s will be started to removed - * @param numComponents - * the number of components to remove - * @return self - * this instance - * @throws IndexOutOfBoundsException - * if the index is invalid + * @param cIndex the index on which the {@link ByteBuf}s will be started to removed + * @param numComponents the number of components to remove */ - CompositeByteBuf removeComponents(int cIndex, int numComponents); + public CompositeByteBuf removeComponents(int cIndex, int numComponents) { + checkComponentIndex(cIndex, numComponents); - /** - * Return the current number of {@link ByteBuf}'s that are composed in this instance - */ - int numComponents(); + List toRemove = components.subList(cIndex, cIndex + numComponents); + for (Component c: toRemove) { + c.freeIfNecessary(); + } + toRemove.clear(); - /** - * Return the max number of {@link ByteBuf}'s that are composed in this instance - */ - int maxNumComponents(); + updateComponentOffsets(cIndex); + return this; + } - /** - * Return the {@link ByteBuf} on the specified index - * - * @param cIndex - * the index for which the {@link ByteBuf} should be returned - * @return buf - * the {@link ByteBuf} on the specified index - * @throws IndexOutOfBoundsException - * if the index is invalid - */ - ByteBuf component(int cIndex); - - /** - * Return the {@link ByteBuf} on the specified index - * - * @param offset - * the offset for which the {@link ByteBuf} should be returned - * @return buf - * the {@link ByteBuf} on the specified index - * @throws IndexOutOfBoundsException - * if the offset is invalid - */ - ByteBuf componentAtOffset(int offset); - - /** - * Return the internal {@link ByteBuf} on the specified index. Note that updating the indexes of the returned - * buffer will lead to an undefined behavior of this buffer. - * - * @param cIndex the index for which the {@link ByteBuf} should be returned - */ - ByteBuf internalComponent(int cIndex); - - /** - * Return the internal {@link ByteBuf} on the specified offset. Note that updating the indexes of the returned - * buffer will lead to an undefined behavior of this buffer. - * - * @param offset the offset for which the {@link ByteBuf} should be returned - */ - ByteBuf internalComponentAtOffset(int offset); - - /** - * Discard all {@link ByteBuf}s which are read. - * - * @return self this instance - */ - CompositeByteBuf discardReadComponents(); - - /** - * Consolidate the composed {@link ByteBuf}s - * - * @return self this instance - */ - CompositeByteBuf consolidate(); - - /** - * Consolidate the composed {@link ByteBuf}s - * - * @param cIndex - * the index on which to start to compose - * @param numComponents - * the number of components to compose - * @return self - * this instance - * @throws IndexOutOfBoundsException - * if the offset is invalid - */ - CompositeByteBuf consolidate(int cIndex, int numComponents); - - /** - * Return the index for the given offset - */ - int toComponentIndex(int offset); - - int toByteIndex(int cIndex); + public Iterator iterator() { + assert !freed; + List list = new ArrayList(components.size()); + for (Component c: components) { + list.add(c.buf); + } + return list.iterator(); + } /** * Same with {@link #slice(int, int)} except that this method returns a list. */ - List decompose(int offset, int length); + public List decompose(int offset, int length) { + checkIndex(offset, length); + if (length == 0) { + return Collections.emptyList(); + } + + int componentId = toComponentIndex(offset); + List slice = new ArrayList(components.size()); + + // The first component + Component firstC = components.get(componentId); + ByteBuf first = firstC.buf.duplicate(); + first.readerIndex(offset - firstC.offset); + + ByteBuf buf = first; + int bytesToSlice = length; + do { + int readableBytes = buf.readableBytes(); + if (bytesToSlice <= readableBytes) { + // Last component + buf.writerIndex(buf.readerIndex() + bytesToSlice); + slice.add(buf); + break; + } else { + // Not the last component + slice.add(buf); + bytesToSlice -= readableBytes; + componentId ++; + + // Fetch the next component. + buf = components.get(componentId).buf.duplicate(); + } + } while (bytesToSlice > 0); + + // Slice all components because only readable bytes are interesting. + for (int i = 0; i < slice.size(); i ++) { + slice.set(i, slice.get(i).slice()); + } + + return slice; + } @Override - CompositeByteBuf capacity(int newCapacity); + public boolean isDirect() { + if (components.size() == 1) { + return components.get(0).buf.isDirect(); + } + return false; + } @Override - CompositeByteBuf readerIndex(int readerIndex); + public boolean hasArray() { + if (components.size() == 1) { + return components.get(0).buf.hasArray(); + } + return false; + } @Override - CompositeByteBuf writerIndex(int writerIndex); + public byte[] array() { + if (components.size() == 1) { + return components.get(0).buf.array(); + } + throw new UnsupportedOperationException(); + } @Override - CompositeByteBuf setIndex(int readerIndex, int writerIndex); + public int arrayOffset() { + if (components.size() == 1) { + return components.get(0).buf.arrayOffset(); + } + throw new UnsupportedOperationException(); + } @Override - CompositeByteBuf clear(); + public boolean hasMemoryAddress() { + if (components.size() == 1) { + return components.get(0).buf.hasMemoryAddress(); + } + return false; + } @Override - CompositeByteBuf markReaderIndex(); + public long memoryAddress() { + if (components.size() == 1) { + return components.get(0).buf.memoryAddress(); + } + throw new UnsupportedOperationException(); + } @Override - CompositeByteBuf resetReaderIndex(); + public int capacity() { + if (components.isEmpty()) { + return 0; + } + return components.get(components.size() - 1).endOffset; + } @Override - CompositeByteBuf markWriterIndex(); + public CompositeByteBuf capacity(int newCapacity) { + assert !freed; + if (newCapacity < 0 || newCapacity > maxCapacity()) { + throw new IllegalArgumentException("newCapacity: " + newCapacity); + } + + int oldCapacity = capacity(); + if (newCapacity > oldCapacity) { + final int paddingLength = newCapacity - oldCapacity; + ByteBuf padding; + int nComponents = components.size(); + if (nComponents < maxNumComponents) { + padding = allocBuffer(paddingLength); + padding.setIndex(0, paddingLength); + addComponent0(components.size(), padding); + } else { + padding = allocBuffer(paddingLength); + padding.setIndex(0, paddingLength); + // FIXME: No need to create a padding buffer and consolidate. + // Just create a big single buffer and put the current content there. + addComponent0(components.size(), padding); + consolidateIfNeeded(); + } + } else if (newCapacity < oldCapacity) { + int bytesToTrim = oldCapacity - newCapacity; + for (ListIterator i = components.listIterator(components.size()); i.hasPrevious();) { + Component c = i.previous(); + if (bytesToTrim >= c.length) { + bytesToTrim -= c.length; + i.remove(); + continue; + } + + // Replace the last component with the trimmed slice. + Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim)); + newC.offset = c.offset; + newC.endOffset = newC.offset + newC.length; + i.set(newC); + break; + } + + if (readerIndex() > newCapacity) { + setIndex(newCapacity, newCapacity); + } else if (writerIndex() > newCapacity) { + writerIndex(newCapacity); + } + } + return this; + } @Override - CompositeByteBuf resetWriterIndex(); + public ByteBufAllocator alloc() { + return alloc; + } @Override - CompositeByteBuf discardReadBytes(); + public ByteOrder order() { + return ByteOrder.BIG_ENDIAN; + } + + /** + * Return the current number of {@link ByteBuf}'s that are composed in this instance + */ + public int numComponents() { + return components.size(); + } + + /** + * Return the max number of {@link ByteBuf}'s that are composed in this instance + */ + public int maxNumComponents() { + return maxNumComponents; + } + + /** + * Return the index for the given offset + */ + public int toComponentIndex(int offset) { + assert !freed; + checkIndex(offset); + + for (int low = 0, high = components.size(); low <= high;) { + int mid = low + high >>> 1; + Component c = components.get(mid); + if (offset >= c.endOffset) { + low = mid + 1; + } else if (offset < c.offset) { + high = mid - 1; + } else { + return mid; + } + } + + throw new Error("should not reach here"); + } + + public int toByteIndex(int cIndex) { + checkComponentIndex(cIndex); + return components.get(cIndex).offset; + } @Override - CompositeByteBuf discardSomeReadBytes(); + public byte getByte(int index) { + return _getByte(index); + } @Override - CompositeByteBuf ensureWritable(int minWritableBytes); + protected byte _getByte(int index) { + Component c = findComponent(index); + return c.buf.getByte(index - c.offset); + } @Override - CompositeByteBuf getBytes(int index, ByteBuf dst); + protected short _getShort(int index) { + Component c = findComponent(index); + if (index + 2 <= c.endOffset) { + return c.buf.getShort(index - c.offset); + } else if (order() == ByteOrder.BIG_ENDIAN) { + return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff); + } else { + return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8); + } + } @Override - CompositeByteBuf getBytes(int index, ByteBuf dst, int length); + protected int _getUnsignedMedium(int index) { + Component c = findComponent(index); + if (index + 3 <= c.endOffset) { + return c.buf.getUnsignedMedium(index - c.offset); + } else if (order() == ByteOrder.BIG_ENDIAN) { + return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff; + } else { + return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16; + } + } @Override - CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length); + protected int _getInt(int index) { + Component c = findComponent(index); + if (index + 4 <= c.endOffset) { + return c.buf.getInt(index - c.offset); + } else if (order() == ByteOrder.BIG_ENDIAN) { + return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff; + } else { + return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16; + } + } @Override - CompositeByteBuf getBytes(int index, byte[] dst); + protected long _getLong(int index) { + Component c = findComponent(index); + if (index + 8 <= c.endOffset) { + return c.buf.getLong(index - c.offset); + } else if (order() == ByteOrder.BIG_ENDIAN) { + return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL; + } else { + return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32; + } + } @Override - CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length); + public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { + checkDstIndex(index, length, dstIndex, dst.length); + if (length == 0) { + return this; + } + + int i = toComponentIndex(index); + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + s.getBytes(index - adjustment, dst, dstIndex, localLength); + index += localLength; + dstIndex += localLength; + length -= localLength; + i ++; + } + return this; + } @Override - CompositeByteBuf getBytes(int index, ByteBuffer dst); + public CompositeByteBuf getBytes(int index, ByteBuffer dst) { + int limit = dst.limit(); + int length = dst.remaining(); + + checkIndex(index, length); + if (length == 0) { + return this; + } + + int i = toComponentIndex(index); + try { + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + dst.limit(dst.position() + localLength); + s.getBytes(index - adjustment, dst); + index += localLength; + length -= localLength; + i ++; + } + } finally { + dst.limit(limit); + } + return this; + } @Override - CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException; + public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { + checkDstIndex(index, length, dstIndex, dst.capacity()); + int i = toComponentIndex(index); + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + s.getBytes(index - adjustment, dst, dstIndex, localLength); + index += localLength; + dstIndex += localLength; + length -= localLength; + i ++; + } + return this; + } @Override - CompositeByteBuf setBoolean(int index, boolean value); + public int getBytes(int index, GatheringByteChannel out, int length) + throws IOException { + if (PlatformDependent.javaVersion() < 7) { + // XXX Gathering write is not supported because of a known issue. + // See http://bugs.sun.com/view_bug.do?bug_id=6210541 + return out.write(copiedNioBuffer(index, length)); + } else { + long writtenBytes = out.write(nioBuffers(index, length)); + if (writtenBytes > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } else { + return (int) writtenBytes; + } + } + } @Override - CompositeByteBuf setByte(int index, int value); + public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException { + checkIndex(index, length); + if (length == 0) { + return this; + } + + int i = toComponentIndex(index); + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + s.getBytes(index - adjustment, out, localLength); + index += localLength; + length -= localLength; + i ++; + } + return this; + } @Override - CompositeByteBuf setShort(int index, int value); + public CompositeByteBuf setByte(int index, int value) { + Component c = findComponent(index); + c.buf.setByte(index - c.offset, value); + return this; + } @Override - CompositeByteBuf setMedium(int index, int value); + protected void _setByte(int index, int value) { + setByte(index, value); + } @Override - CompositeByteBuf setInt(int index, int value); + public CompositeByteBuf setShort(int index, int value) { + return (CompositeByteBuf) super.setShort(index, value); + } @Override - CompositeByteBuf setLong(int index, long value); + protected void _setShort(int index, int value) { + Component c = findComponent(index); + if (index + 2 <= c.endOffset) { + c.buf.setShort(index - c.offset, value); + } else if (order() == ByteOrder.BIG_ENDIAN) { + _setByte(index, (byte) (value >>> 8)); + _setByte(index + 1, (byte) value); + } else { + _setByte(index, (byte) value); + _setByte(index + 1, (byte) (value >>> 8)); + } + } @Override - CompositeByteBuf setChar(int index, int value); + public CompositeByteBuf setMedium(int index, int value) { + return (CompositeByteBuf) super.setMedium(index, value); + } @Override - CompositeByteBuf setFloat(int index, float value); + protected void _setMedium(int index, int value) { + Component c = findComponent(index); + if (index + 3 <= c.endOffset) { + c.buf.setMedium(index - c.offset, value); + } else if (order() == ByteOrder.BIG_ENDIAN) { + _setShort(index, (short) (value >> 8)); + _setByte(index + 2, (byte) value); + } else { + _setShort(index, (short) value); + _setByte(index + 2, (byte) (value >>> 16)); + } + } @Override - CompositeByteBuf setDouble(int index, double value); + public CompositeByteBuf setInt(int index, int value) { + return (CompositeByteBuf) super.setInt(index, value); + } @Override - CompositeByteBuf setBytes(int index, ByteBuf src); + protected void _setInt(int index, int value) { + Component c = findComponent(index); + if (index + 4 <= c.endOffset) { + c.buf.setInt(index - c.offset, value); + } else if (order() == ByteOrder.BIG_ENDIAN) { + _setShort(index, (short) (value >>> 16)); + _setShort(index + 2, (short) value); + } else { + _setShort(index, (short) value); + _setShort(index + 2, (short) (value >>> 16)); + } + } @Override - CompositeByteBuf setBytes(int index, ByteBuf src, int length); + public CompositeByteBuf setLong(int index, long value) { + return (CompositeByteBuf) super.setLong(index, value); + } @Override - CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length); + protected void _setLong(int index, long value) { + Component c = findComponent(index); + if (index + 8 <= c.endOffset) { + c.buf.setLong(index - c.offset, value); + } else if (order() == ByteOrder.BIG_ENDIAN) { + _setInt(index, (int) (value >>> 32)); + _setInt(index + 4, (int) value); + } else { + _setInt(index, (int) value); + _setInt(index + 4, (int) (value >>> 32)); + } + } @Override - CompositeByteBuf setBytes(int index, byte[] src); + public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { + checkSrcIndex(index, length, srcIndex, src.length); + + int i = toComponentIndex(index); + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + s.setBytes(index - adjustment, src, srcIndex, localLength); + index += localLength; + srcIndex += localLength; + length -= localLength; + i ++; + } + return this; + } @Override - CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length); + public CompositeByteBuf setBytes(int index, ByteBuffer src) { + int limit = src.limit(); + int length = src.remaining(); + + checkIndex(index, length); + int i = toComponentIndex(index); + try { + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + src.limit(src.position() + localLength); + s.setBytes(index - adjustment, src); + index += localLength; + length -= localLength; + i ++; + } + } finally { + src.limit(limit); + } + return this; + } @Override - CompositeByteBuf setBytes(int index, ByteBuffer src); + public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { + checkSrcIndex(index, length, srcIndex, src.capacity()); + + int i = toComponentIndex(index); + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + s.setBytes(index - adjustment, src, srcIndex, localLength); + index += localLength; + srcIndex += localLength; + length -= localLength; + i ++; + } + return this; + } @Override - CompositeByteBuf setZero(int index, int length); + public int setBytes(int index, InputStream in, int length) throws IOException { + checkIndex(index, length); + + int i = toComponentIndex(index); + int readBytes = 0; + + do { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + int localReadBytes = s.setBytes(index - adjustment, in, localLength); + if (localReadBytes < 0) { + if (readBytes == 0) { + return -1; + } else { + break; + } + } + + if (localReadBytes == localLength) { + index += localLength; + length -= localLength; + readBytes += localLength; + i ++; + } else { + index += localReadBytes; + length -= localReadBytes; + readBytes += localReadBytes; + } + } while (length > 0); + + return readBytes; + } @Override - CompositeByteBuf readBytes(ByteBuf dst); + public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { + checkIndex(index, length); + + int i = toComponentIndex(index); + int readBytes = 0; + do { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + int localReadBytes = s.setBytes(index - adjustment, in, localLength); + + if (localReadBytes == 0) { + break; + } + + if (localReadBytes < 0) { + if (readBytes == 0) { + return -1; + } else { + break; + } + } + + if (localReadBytes == localLength) { + index += localLength; + length -= localLength; + readBytes += localLength; + i ++; + } else { + index += localReadBytes; + length -= localReadBytes; + readBytes += localReadBytes; + } + } while (length > 0); + + return readBytes; + } @Override - CompositeByteBuf readBytes(ByteBuf dst, int length); + public ByteBuf copy(int index, int length) { + checkIndex(index, length); + ByteBuf dst = Unpooled.buffer(length); + copyTo(index, length, toComponentIndex(index), dst); + return dst; + } + + private void copyTo(int index, int length, int componentId, ByteBuf dst) { + int dstIndex = 0; + int i = componentId; + + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + s.getBytes(index - adjustment, dst, dstIndex, localLength); + index += localLength; + dstIndex += localLength; + length -= localLength; + i ++; + } + + dst.writerIndex(dst.capacity()); + } + + /** + * Return the {@link ByteBuf} on the specified index + * + * @param cIndex the index for which the {@link ByteBuf} should be returned + * @return buf the {@link ByteBuf} on the specified index + */ + public ByteBuf component(int cIndex) { + return internalComponent(cIndex).duplicate(); + } + + /** + * Return the {@link ByteBuf} on the specified index + * + * @param offset the offset for which the {@link ByteBuf} should be returned + * @return the {@link ByteBuf} on the specified index + */ + public ByteBuf componentAtOffset(int offset) { + return internalComponentAtOffset(offset).duplicate(); + } + + /** + * Return the internal {@link ByteBuf} on the specified index. Note that updating the indexes of the returned + * buffer will lead to an undefined behavior of this buffer. + * + * @param cIndex the index for which the {@link ByteBuf} should be returned + */ + public ByteBuf internalComponent(int cIndex) { + checkComponentIndex(cIndex); + return components.get(cIndex).buf; + } + + /** + * Return the internal {@link ByteBuf} on the specified offset. Note that updating the indexes of the returned + * buffer will lead to an undefined behavior of this buffer. + * + * @param offset the offset for which the {@link ByteBuf} should be returned + */ + public ByteBuf internalComponentAtOffset(int offset) { + return findComponent(offset).buf; + } + + private Component findComponent(int offset) { + assert !freed; + checkIndex(offset); + + assert !freed; + checkIndex(offset); + + for (int low = 0, high = components.size(); low <= high;) { + int mid = low + high >>> 1; + Component c = components.get(mid); + if (offset >= c.endOffset) { + low = mid + 1; + } else if (offset < c.offset) { + high = mid - 1; + } else { + return c; + } + } + + throw new Error("should not reach here"); + } @Override - CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length); + public int nioBufferCount() { + if (components.size() == 1) { + return components.get(0).buf.nioBufferCount(); + } else { + int count = 0; + int componentsCount = components.size(); + //noinspection ForLoopReplaceableByForEach + for (int i = 0; i < componentsCount; i++) { + Component c = components.get(i); + count += c.buf.nioBufferCount(); + } + return count; + } + } @Override - CompositeByteBuf readBytes(byte[] dst); + public ByteBuffer internalNioBuffer(int index, int length) { + if (components.size() == 1) { + return components.get(0).buf.internalNioBuffer(index, length); + } + throw new UnsupportedOperationException(); + } + + private ByteBuffer copiedNioBuffer(int index, int length) { + assert !freed; + if (components.size() == 1) { + return toNioBuffer(components.get(0).buf, index, length); + } + + ByteBuffer[] buffers = nioBuffers(index, length); + ByteBuffer merged = ByteBuffer.allocate(length).order(order()); + for (ByteBuffer b: buffers) { + merged.put(b); + } + merged.flip(); + return merged; + } @Override - CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length); + public ByteBuffer[] nioBuffers(int index, int length) { + checkIndex(index, length); + if (length == 0) { + return EmptyArrays.EMPTY_BYTE_BUFFERS; + } + + List buffers = new ArrayList(components.size()); + int i = toComponentIndex(index); + while (length > 0) { + Component c = components.get(i); + ByteBuf s = c.buf; + int adjustment = c.offset; + int localLength = Math.min(length, s.capacity() - (index - adjustment)); + switch (s.nioBufferCount()) { + case 0: + throw new UnsupportedOperationException(); + case 1: + buffers.add(s.nioBuffer(index - adjustment, localLength)); + break; + default: + Collections.addAll(buffers, s.nioBuffers(index - adjustment, localLength)); + } + + index += localLength; + length -= localLength; + i ++; + } + + return buffers.toArray(new ByteBuffer[buffers.size()]); + } + + private static ByteBuffer toNioBuffer(ByteBuf buf, int index, int length) { + if (buf.nioBufferCount() == 1) { + return buf.nioBuffer(index, length); + } else { + return buf.copy(index, length).nioBuffer(0, length); + } + } + + /** + * Consolidate the composed {@link ByteBuf}s + */ + public CompositeByteBuf consolidate() { + assert !freed; + final int numComponents = numComponents(); + if (numComponents <= 1) { + return this; + } + + final Component last = components.get(numComponents - 1); + final int capacity = last.endOffset; + final ByteBuf consolidated = allocBuffer(capacity); + + for (int i = 0; i < numComponents; i ++) { + Component c = components.get(i); + ByteBuf b = c.buf; + consolidated.writeBytes(b); + c.freeIfNecessary(); + } + + components.clear(); + components.add(new Component(consolidated)); + updateComponentOffsets(0); + return this; + } + + /** + * Consolidate the composed {@link ByteBuf}s + * + * @param cIndex the index on which to start to compose + * @param numComponents the number of components to compose + */ + public CompositeByteBuf consolidate(int cIndex, int numComponents) { + checkComponentIndex(cIndex, numComponents); + if (numComponents <= 1) { + return this; + } + + final int endCIndex = cIndex + numComponents; + final Component last = components.get(endCIndex - 1); + final int capacity = last.endOffset - components.get(cIndex).offset; + final ByteBuf consolidated = allocBuffer(capacity); + + for (int i = cIndex; i < endCIndex; i ++) { + Component c = components.get(i); + ByteBuf b = c.buf; + consolidated.writeBytes(b); + c.freeIfNecessary(); + } + + components.subList(cIndex + 1, endCIndex).clear(); + components.set(cIndex, new Component(consolidated)); + updateComponentOffsets(cIndex); + return this; + } + + /** + * Discard all {@link ByteBuf}s which are read. + */ + public CompositeByteBuf discardReadComponents() { + assert !freed; + final int readerIndex = readerIndex(); + if (readerIndex == 0) { + return this; + } + + // Discard everything if (readerIndex = writerIndex = capacity). + int writerIndex = writerIndex(); + if (readerIndex == writerIndex && writerIndex == capacity()) { + for (Component c: components) { + c.freeIfNecessary(); + } + components.clear(); + setIndex(0, 0); + adjustMarkers(readerIndex); + return this; + } + + // Remove read components. + int firstComponentId = toComponentIndex(readerIndex); + for (int i = 0; i < firstComponentId; i ++) { + components.get(i).freeIfNecessary(); + } + components.subList(0, firstComponentId).clear(); + + // Update indexes and markers. + Component first = components.get(0); + updateComponentOffsets(0); + setIndex(readerIndex - first.offset, writerIndex - first.offset); + adjustMarkers(first.offset); + return this; + } @Override - CompositeByteBuf readBytes(ByteBuffer dst); + public CompositeByteBuf discardReadBytes() { + assert !freed; + final int readerIndex = readerIndex(); + if (readerIndex == 0) { + return this; + } + + // Discard everything if (readerIndex = writerIndex = capacity). + int writerIndex = writerIndex(); + if (readerIndex == writerIndex && writerIndex == capacity()) { + for (Component c: components) { + c.freeIfNecessary(); + } + components.clear(); + setIndex(0, 0); + adjustMarkers(readerIndex); + return this; + } + + // Remove read components. + int firstComponentId = toComponentIndex(readerIndex); + for (int i = 0; i < firstComponentId; i ++) { + components.get(i).freeIfNecessary(); + } + components.subList(0, firstComponentId).clear(); + + // Remove or replace the first readable component with a new slice. + Component c = components.get(0); + int adjustment = readerIndex - c.offset; + if (adjustment == c.length) { + // new slice would be empty, so remove instead + components.remove(0); + } else { + Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment)); + components.set(0, newC); + } + + // Update indexes and markers. + updateComponentOffsets(0); + setIndex(0, writerIndex - readerIndex); + adjustMarkers(readerIndex); + return this; + } + + private ByteBuf allocBuffer(int capacity) { + if (direct) { + return alloc().directBuffer(capacity); + } + return alloc().heapBuffer(capacity); + } @Override - CompositeByteBuf readBytes(OutputStream out, int length) throws IOException; + public String toString() { + String result = super.toString(); + result = result.substring(0, result.length() - 1); + return result + ", components=" + components.size() + ')'; + } + + private final class Component { + final ByteBuf buf; + final int length; + int offset; + int endOffset; + + Component(ByteBuf buf) { + this.buf = buf; + length = buf.readableBytes(); + } + + void freeIfNecessary() { + // Unwrap so that we can free slices, too. + buf.release(); // We should not get a NPE here. If so, it must be a bug. + } + } @Override - CompositeByteBuf skipBytes(int length); + public CompositeByteBuf readerIndex(int readerIndex) { + return (CompositeByteBuf) super.readerIndex(readerIndex); + } @Override - CompositeByteBuf writeBoolean(boolean value); + public CompositeByteBuf writerIndex(int writerIndex) { + return (CompositeByteBuf) super.writerIndex(writerIndex); + } @Override - CompositeByteBuf writeByte(int value); + public CompositeByteBuf setIndex(int readerIndex, int writerIndex) { + return (CompositeByteBuf) super.setIndex(readerIndex, writerIndex); + } @Override - CompositeByteBuf writeShort(int value); + public CompositeByteBuf clear() { + return (CompositeByteBuf) super.clear(); + } @Override - CompositeByteBuf writeMedium(int value); + public CompositeByteBuf markReaderIndex() { + return (CompositeByteBuf) super.markReaderIndex(); + } @Override - CompositeByteBuf writeInt(int value); + public CompositeByteBuf resetReaderIndex() { + return (CompositeByteBuf) super.resetReaderIndex(); + } @Override - CompositeByteBuf writeLong(long value); + public CompositeByteBuf markWriterIndex() { + return (CompositeByteBuf) super.markWriterIndex(); + } @Override - CompositeByteBuf writeChar(int value); + public CompositeByteBuf resetWriterIndex() { + return (CompositeByteBuf) super.resetWriterIndex(); + } @Override - CompositeByteBuf writeFloat(float value); + public CompositeByteBuf ensureWritable(int minWritableBytes) { + return (CompositeByteBuf) super.ensureWritable(minWritableBytes); + } @Override - CompositeByteBuf writeDouble(double value); + public CompositeByteBuf getBytes(int index, ByteBuf dst) { + return (CompositeByteBuf) super.getBytes(index, dst); + } @Override - CompositeByteBuf writeBytes(ByteBuf src); + public CompositeByteBuf getBytes(int index, ByteBuf dst, int length) { + return (CompositeByteBuf) super.getBytes(index, dst, length); + } @Override - CompositeByteBuf writeBytes(ByteBuf src, int length); + public CompositeByteBuf getBytes(int index, byte[] dst) { + return (CompositeByteBuf) super.getBytes(index, dst); + } @Override - CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length); + public CompositeByteBuf setBoolean(int index, boolean value) { + return (CompositeByteBuf) super.setBoolean(index, value); + } @Override - CompositeByteBuf writeBytes(byte[] src); + public CompositeByteBuf setChar(int index, int value) { + return (CompositeByteBuf) super.setChar(index, value); + } @Override - CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length); + public CompositeByteBuf setFloat(int index, float value) { + return (CompositeByteBuf) super.setFloat(index, value); + } @Override - CompositeByteBuf writeBytes(ByteBuffer src); + public CompositeByteBuf setDouble(int index, double value) { + return (CompositeByteBuf) super.setDouble(index, value); + } @Override - CompositeByteBuf writeZero(int length); + public CompositeByteBuf setBytes(int index, ByteBuf src) { + return (CompositeByteBuf) super.setBytes(index, src); + } @Override - CompositeByteBuf retain(int increment); + public CompositeByteBuf setBytes(int index, ByteBuf src, int length) { + return (CompositeByteBuf) super.setBytes(index, src, length); + } @Override - CompositeByteBuf retain(); + public CompositeByteBuf setBytes(int index, byte[] src) { + return (CompositeByteBuf) super.setBytes(index, src); + } + + @Override + public CompositeByteBuf setZero(int index, int length) { + return (CompositeByteBuf) super.setZero(index, length); + } + + @Override + public CompositeByteBuf readBytes(ByteBuf dst) { + return (CompositeByteBuf) super.readBytes(dst); + } + + @Override + public CompositeByteBuf readBytes(ByteBuf dst, int length) { + return (CompositeByteBuf) super.readBytes(dst, length); + } + + @Override + public CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { + return (CompositeByteBuf) super.readBytes(dst, dstIndex, length); + } + + @Override + public CompositeByteBuf readBytes(byte[] dst) { + return (CompositeByteBuf) super.readBytes(dst); + } + + @Override + public CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) { + return (CompositeByteBuf) super.readBytes(dst, dstIndex, length); + } + + @Override + public CompositeByteBuf readBytes(ByteBuffer dst) { + return (CompositeByteBuf) super.readBytes(dst); + } + + @Override + public CompositeByteBuf readBytes(OutputStream out, int length) throws IOException { + return (CompositeByteBuf) super.readBytes(out, length); + } + + @Override + public CompositeByteBuf skipBytes(int length) { + return (CompositeByteBuf) super.skipBytes(length); + } + + @Override + public CompositeByteBuf writeBoolean(boolean value) { + return (CompositeByteBuf) super.writeBoolean(value); + } + + @Override + public CompositeByteBuf writeByte(int value) { + return (CompositeByteBuf) super.writeByte(value); + } + + @Override + public CompositeByteBuf writeShort(int value) { + return (CompositeByteBuf) super.writeShort(value); + } + + @Override + public CompositeByteBuf writeMedium(int value) { + return (CompositeByteBuf) super.writeMedium(value); + } + + @Override + public CompositeByteBuf writeInt(int value) { + return (CompositeByteBuf) super.writeInt(value); + } + + @Override + public CompositeByteBuf writeLong(long value) { + return (CompositeByteBuf) super.writeLong(value); + } + + @Override + public CompositeByteBuf writeChar(int value) { + return (CompositeByteBuf) super.writeChar(value); + } + + @Override + public CompositeByteBuf writeFloat(float value) { + return (CompositeByteBuf) super.writeFloat(value); + } + + @Override + public CompositeByteBuf writeDouble(double value) { + return (CompositeByteBuf) super.writeDouble(value); + } + + @Override + public CompositeByteBuf writeBytes(ByteBuf src) { + return (CompositeByteBuf) super.writeBytes(src); + } + + @Override + public CompositeByteBuf writeBytes(ByteBuf src, int length) { + return (CompositeByteBuf) super.writeBytes(src, length); + } + + @Override + public CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { + return (CompositeByteBuf) super.writeBytes(src, srcIndex, length); + } + + @Override + public CompositeByteBuf writeBytes(byte[] src) { + return (CompositeByteBuf) super.writeBytes(src); + } + + @Override + public CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) { + return (CompositeByteBuf) super.writeBytes(src, srcIndex, length); + } + + @Override + public CompositeByteBuf writeBytes(ByteBuffer src) { + return (CompositeByteBuf) super.writeBytes(src); + } + + @Override + public CompositeByteBuf writeZero(int length) { + return (CompositeByteBuf) super.writeZero(length); + } + + @Override + public CompositeByteBuf retain(int increment) { + return (CompositeByteBuf) super.retain(increment); + } + + @Override + public CompositeByteBuf retain() { + return (CompositeByteBuf) super.retain(); + } + + @Override + public ByteBuffer[] nioBuffers() { + return nioBuffers(readerIndex(), readableBytes()); + } + + @Override + public CompositeByteBuf discardSomeReadBytes() { + return discardReadComponents(); + } + + @Override + protected void deallocate() { + if (freed) { + return; + } + + freed = true; + for (Component c: components) { + c.freeIfNecessary(); + } + + leak.close(); + } + + @Override + public ByteBuf unwrap() { + return null; + } } diff --git a/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java b/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java deleted file mode 100644 index 93474a8caa..0000000000 --- a/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java +++ /dev/null @@ -1,1489 +0,0 @@ -/* - * 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 io.netty.util.ResourceLeak; -import io.netty.util.internal.EmptyArrays; -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.channels.GatheringByteChannel; -import java.nio.channels.ScatteringByteChannel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - - -/** - * A virtual buffer which shows multiple buffers as a single merged buffer. It - * is recommended to use {@link Unpooled#wrappedBuffer(ByteBuf...)} - * instead of calling the constructor explicitly. - */ -public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf implements CompositeByteBuf { - - private final ResourceLeak leak; - private final ByteBufAllocator alloc; - private final boolean direct; - private final List components = new ArrayList(); - private final int maxNumComponents; - - private boolean freed; - - public DefaultCompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - leak = leakDetector.open(this); - } - - public DefaultCompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf... buffers) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (maxNumComponents < 2) { - throw new IllegalArgumentException( - "maxNumComponents: " + maxNumComponents + " (expected: >= 2)"); - } - - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - - addComponents0(0, buffers); - consolidateIfNeeded(); - setIndex(0, capacity()); - leak = leakDetector.open(this); - } - - public DefaultCompositeByteBuf( - ByteBufAllocator alloc, boolean direct, int maxNumComponents, Iterable buffers) { - super(Integer.MAX_VALUE); - if (alloc == null) { - throw new NullPointerException("alloc"); - } - if (maxNumComponents < 2) { - throw new IllegalArgumentException( - "maxNumComponents: " + maxNumComponents + " (expected: >= 2)"); - } - - this.alloc = alloc; - this.direct = direct; - this.maxNumComponents = maxNumComponents; - addComponents0(0, buffers); - consolidateIfNeeded(); - setIndex(0, capacity()); - leak = leakDetector.open(this); - } - - @Override - public CompositeByteBuf addComponent(ByteBuf buffer) { - addComponent0(components.size(), buffer); - consolidateIfNeeded(); - return this; - } - - @Override - public CompositeByteBuf addComponents(ByteBuf... buffers) { - addComponents0(components.size(), buffers); - consolidateIfNeeded(); - return this; - } - - @Override - public CompositeByteBuf addComponents(Iterable buffers) { - addComponents0(components.size(), buffers); - consolidateIfNeeded(); - return this; - } - - @Override - public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) { - addComponent0(cIndex, buffer); - consolidateIfNeeded(); - return this; - } - - private int addComponent0(int cIndex, ByteBuf buffer) { - checkComponentIndex(cIndex); - - if (buffer == null) { - throw new NullPointerException("buffer"); - } - - int readableBytes = buffer.readableBytes(); - if (readableBytes == 0) { - return cIndex; - } - - // No need to consolidate - just add a component to the list. - Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice()); - if (cIndex == components.size()) { - components.add(c); - if (cIndex == 0) { - c.endOffset = readableBytes; - } else { - Component prev = components.get(cIndex - 1); - c.offset = prev.endOffset; - c.endOffset = c.offset + readableBytes; - } - } else { - components.add(cIndex, c); - updateComponentOffsets(cIndex); - } - return cIndex; - } - @Override - public CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers) { - addComponents0(cIndex, buffers); - consolidateIfNeeded(); - return this; - } - - private int addComponents0(int cIndex, ByteBuf... buffers) { - checkComponentIndex(cIndex); - - if (buffers == null) { - throw new NullPointerException("buffers"); - } - - int readableBytes = 0; - for (ByteBuf b: buffers) { - if (b == null) { - break; - } - readableBytes += b.readableBytes(); - } - - if (readableBytes == 0) { - return cIndex; - } - - // No need for consolidation - for (ByteBuf b: buffers) { - if (b == null) { - break; - } - if (b.isReadable()) { - cIndex = addComponent0(cIndex, b) + 1; - int size = components.size(); - if (cIndex > size) { - cIndex = size; - } - } else { - b.release(); - } - } - return cIndex; - } - - @Override - public CompositeByteBuf addComponents(int cIndex, Iterable buffers) { - addComponents0(cIndex, buffers); - consolidateIfNeeded(); - return this; - } - - private int addComponents0(int cIndex, Iterable buffers) { - if (buffers == null) { - throw new NullPointerException("buffers"); - } - - if (buffers instanceof ByteBuf) { - // If buffers also implements ByteBuf (e.g. CompositeByteBuf), it has to go to addComponent(ByteBuf). - return addComponent0(cIndex, (ByteBuf) buffers); - } - - if (!(buffers instanceof Collection)) { - List list = new ArrayList(); - for (ByteBuf b: buffers) { - list.add(b); - } - buffers = list; - } - - Collection col = (Collection) buffers; - return addComponents0(cIndex, col.toArray(new ByteBuf[col.size()])); - } - - /** - * This should only be called as last operation from a method as this may adjust the underlying - * array of components and so affect the index etc. - */ - private void consolidateIfNeeded() { - // Consolidate if the number of components will exceed the allowed maximum by the current - // operation. - final int numComponents = components.size(); - if (numComponents > maxNumComponents) { - final int capacity = components.get(numComponents - 1).endOffset; - - ByteBuf consolidated = allocBuffer(capacity); - - // We're not using foreach to avoid creating an iterator. - // noinspection ForLoopReplaceableByForEach - for (int i = 0; i < numComponents; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - Component c = new Component(consolidated); - c.endOffset = c.length; - components.clear(); - components.add(c); - } - } - - private void checkComponentIndex(int cIndex) { - assert !freed; - if (cIndex < 0 || cIndex > components.size()) { - throw new IndexOutOfBoundsException(String.format( - "cIndex: %d (expected: >= 0 && <= numComponents(%d))", - cIndex, components.size())); - } - } - - private void checkComponentIndex(int cIndex, int numComponents) { - assert !freed; - if (cIndex < 0 || cIndex + numComponents > components.size()) { - throw new IndexOutOfBoundsException(String.format( - "cIndex: %d, numComponents: %d " + - "(expected: cIndex >= 0 && cIndex + numComponents <= totalNumComponents(%d))", - cIndex, numComponents, components.size())); - } - } - - private void updateComponentOffsets(int cIndex) { - if (components.isEmpty()) { - return; - } - - Component c = components.get(cIndex); - if (cIndex == 0) { - c.offset = 0; - c.endOffset = c.length; - cIndex ++; - } - - for (int i = cIndex; i < components.size(); i ++) { - Component prev = components.get(i - 1); - Component cur = components.get(i); - cur.offset = prev.endOffset; - cur.endOffset = cur.offset + cur.length; - } - } - - @Override - public CompositeByteBuf removeComponent(int cIndex) { - checkComponentIndex(cIndex); - components.remove(cIndex).freeIfNecessary(); - updateComponentOffsets(cIndex); - return this; - } - - @Override - public CompositeByteBuf removeComponents(int cIndex, int numComponents) { - checkComponentIndex(cIndex, numComponents); - - List toRemove = components.subList(cIndex, cIndex + numComponents); - for (Component c: toRemove) { - c.freeIfNecessary(); - } - toRemove.clear(); - - updateComponentOffsets(cIndex); - return this; - } - - @Override - public Iterator iterator() { - assert !freed; - List list = new ArrayList(components.size()); - for (Component c: components) { - list.add(c.buf); - } - return list.iterator(); - } - - @Override - public List decompose(int offset, int length) { - checkIndex(offset, length); - if (length == 0) { - return Collections.emptyList(); - } - - int componentId = toComponentIndex(offset); - List slice = new ArrayList(components.size()); - - // The first component - Component firstC = components.get(componentId); - ByteBuf first = firstC.buf.duplicate(); - first.readerIndex(offset - firstC.offset); - - ByteBuf buf = first; - int bytesToSlice = length; - do { - int readableBytes = buf.readableBytes(); - if (bytesToSlice <= readableBytes) { - // Last component - buf.writerIndex(buf.readerIndex() + bytesToSlice); - slice.add(buf); - break; - } else { - // Not the last component - slice.add(buf); - bytesToSlice -= readableBytes; - componentId ++; - - // Fetch the next component. - buf = components.get(componentId).buf.duplicate(); - } - } while (bytesToSlice > 0); - - // Slice all components because only readable bytes are interesting. - for (int i = 0; i < slice.size(); i ++) { - slice.set(i, slice.get(i).slice()); - } - - return slice; - } - - @Override - public boolean isDirect() { - if (components.size() == 1) { - return components.get(0).buf.isDirect(); - } - return false; - } - - @Override - public boolean hasArray() { - if (components.size() == 1) { - return components.get(0).buf.hasArray(); - } - return false; - } - - @Override - public byte[] array() { - if (components.size() == 1) { - return components.get(0).buf.array(); - } - throw new UnsupportedOperationException(); - } - - @Override - public int arrayOffset() { - if (components.size() == 1) { - return components.get(0).buf.arrayOffset(); - } - 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()) { - return 0; - } - return components.get(components.size() - 1).endOffset; - } - - @Override - public CompositeByteBuf capacity(int newCapacity) { - assert !freed; - if (newCapacity < 0 || newCapacity > maxCapacity()) { - throw new IllegalArgumentException("newCapacity: " + newCapacity); - } - - int oldCapacity = capacity(); - if (newCapacity > oldCapacity) { - final int paddingLength = newCapacity - oldCapacity; - ByteBuf padding; - int nComponents = components.size(); - if (nComponents < maxNumComponents) { - padding = allocBuffer(paddingLength); - padding.setIndex(0, paddingLength); - addComponent0(components.size(), padding); - } else { - padding = allocBuffer(paddingLength); - padding.setIndex(0, paddingLength); - // FIXME: No need to create a padding buffer and consolidate. - // Just create a big single buffer and put the current content there. - addComponent0(components.size(), padding); - consolidateIfNeeded(); - } - } else if (newCapacity < oldCapacity) { - int bytesToTrim = oldCapacity - newCapacity; - for (ListIterator i = components.listIterator(components.size()); i.hasPrevious();) { - Component c = i.previous(); - if (bytesToTrim >= c.length) { - bytesToTrim -= c.length; - i.remove(); - continue; - } - - // Replace the last component with the trimmed slice. - Component newC = new Component(c.buf.slice(0, c.length - bytesToTrim)); - newC.offset = c.offset; - newC.endOffset = newC.offset + newC.length; - i.set(newC); - break; - } - - if (readerIndex() > newCapacity) { - setIndex(newCapacity, newCapacity); - } else if (writerIndex() > newCapacity) { - writerIndex(newCapacity); - } - } - return this; - } - - @Override - public ByteBufAllocator alloc() { - return alloc; - } - - @Override - public ByteOrder order() { - return ByteOrder.BIG_ENDIAN; - } - - @Override - public int numComponents() { - return components.size(); - } - - @Override - public int maxNumComponents() { - return maxNumComponents; - } - - @Override - public int toComponentIndex(int offset) { - assert !freed; - checkIndex(offset); - - for (int low = 0, high = components.size(); low <= high;) { - int mid = low + high >>> 1; - Component c = components.get(mid); - if (offset >= c.endOffset) { - low = mid + 1; - } else if (offset < c.offset) { - high = mid - 1; - } else { - return mid; - } - } - - throw new Error("should not reach here"); - } - - @Override - public int toByteIndex(int cIndex) { - checkComponentIndex(cIndex); - return components.get(cIndex).offset; - } - - @Override - public byte getByte(int index) { - return _getByte(index); - } - - @Override - protected byte _getByte(int index) { - Component c = findComponent(index); - return c.buf.getByte(index - c.offset); - } - - @Override - protected short _getShort(int index) { - Component c = findComponent(index); - if (index + 2 <= c.endOffset) { - return c.buf.getShort(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (short) ((_getByte(index) & 0xff) << 8 | _getByte(index + 1) & 0xff); - } else { - return (short) (_getByte(index) & 0xff | (_getByte(index + 1) & 0xff) << 8); - } - } - - @Override - protected int _getUnsignedMedium(int index) { - Component c = findComponent(index); - if (index + 3 <= c.endOffset) { - return c.buf.getUnsignedMedium(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getShort(index) & 0xffff) << 8 | _getByte(index + 2) & 0xff; - } else { - return _getShort(index) & 0xFFFF | (_getByte(index + 2) & 0xFF) << 16; - } - } - - @Override - protected int _getInt(int index) { - Component c = findComponent(index); - if (index + 4 <= c.endOffset) { - return c.buf.getInt(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getShort(index) & 0xffff) << 16 | _getShort(index + 2) & 0xffff; - } else { - return _getShort(index) & 0xFFFF | (_getShort(index + 2) & 0xFFFF) << 16; - } - } - - @Override - protected long _getLong(int index) { - Component c = findComponent(index); - if (index + 8 <= c.endOffset) { - return c.buf.getLong(index - c.offset); - } else if (order() == ByteOrder.BIG_ENDIAN) { - return (_getInt(index) & 0xffffffffL) << 32 | _getInt(index + 4) & 0xffffffffL; - } else { - return _getInt(index) & 0xFFFFFFFFL | (_getInt(index + 4) & 0xFFFFFFFFL) << 32; - } - } - - @Override - public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuffer dst) { - int limit = dst.limit(); - int length = dst.remaining(); - - checkIndex(index, length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - try { - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - dst.limit(dst.position() + localLength); - s.getBytes(index - adjustment, dst); - index += localLength; - length -= localLength; - i ++; - } - } finally { - dst.limit(limit); - } - return this; - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { - checkDstIndex(index, length, dstIndex, dst.capacity()); - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public int getBytes(int index, GatheringByteChannel out, int length) - throws IOException { - if (PlatformDependent.javaVersion() < 7) { - // XXX Gathering write is not supported because of a known issue. - // See http://bugs.sun.com/view_bug.do?bug_id=6210541 - return out.write(copiedNioBuffer(index, length)); - } else { - long writtenBytes = out.write(nioBuffers(index, length)); - if (writtenBytes > Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } else { - return (int) writtenBytes; - } - } - } - - @Override - public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException { - checkIndex(index, length); - if (length == 0) { - return this; - } - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, out, localLength); - index += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf setByte(int index, int value) { - Component c = findComponent(index); - c.buf.setByte(index - c.offset, value); - return this; - } - - @Override - protected void _setByte(int index, int value) { - setByte(index, value); - } - - @Override - public CompositeByteBuf setShort(int index, int value) { - return (CompositeByteBuf) super.setShort(index, value); - } - - @Override - protected void _setShort(int index, int value) { - Component c = findComponent(index); - if (index + 2 <= c.endOffset) { - c.buf.setShort(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setByte(index, (byte) (value >>> 8)); - _setByte(index + 1, (byte) value); - } else { - _setByte(index, (byte) value); - _setByte(index + 1, (byte) (value >>> 8)); - } - } - - @Override - public CompositeByteBuf setMedium(int index, int value) { - return (CompositeByteBuf) super.setMedium(index, value); - } - - @Override - protected void _setMedium(int index, int value) { - Component c = findComponent(index); - if (index + 3 <= c.endOffset) { - c.buf.setMedium(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setShort(index, (short) (value >> 8)); - _setByte(index + 2, (byte) value); - } else { - _setShort(index, (short) value); - _setByte(index + 2, (byte) (value >>> 16)); - } - } - - @Override - public CompositeByteBuf setInt(int index, int value) { - return (CompositeByteBuf) super.setInt(index, value); - } - - @Override - protected void _setInt(int index, int value) { - Component c = findComponent(index); - if (index + 4 <= c.endOffset) { - c.buf.setInt(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setShort(index, (short) (value >>> 16)); - _setShort(index + 2, (short) value); - } else { - _setShort(index, (short) value); - _setShort(index + 2, (short) (value >>> 16)); - } - } - - @Override - public CompositeByteBuf setLong(int index, long value) { - return (CompositeByteBuf) super.setLong(index, value); - } - - @Override - protected void _setLong(int index, long value) { - Component c = findComponent(index); - if (index + 8 <= c.endOffset) { - c.buf.setLong(index - c.offset, value); - } else if (order() == ByteOrder.BIG_ENDIAN) { - _setInt(index, (int) (value >>> 32)); - _setInt(index + 4, (int) value); - } else { - _setInt(index, (int) value); - _setInt(index + 4, (int) (value >>> 32)); - } - } - - @Override - public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.length); - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.setBytes(index - adjustment, src, srcIndex, localLength); - index += localLength; - srcIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuffer src) { - int limit = src.limit(); - int length = src.remaining(); - - checkIndex(index, length); - int i = toComponentIndex(index); - try { - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - src.limit(src.position() + localLength); - s.setBytes(index - adjustment, src); - index += localLength; - length -= localLength; - i ++; - } - } finally { - src.limit(limit); - } - return this; - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { - checkSrcIndex(index, length, srcIndex, src.capacity()); - - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.setBytes(index - adjustment, src, srcIndex, localLength); - index += localLength; - srcIndex += localLength; - length -= localLength; - i ++; - } - return this; - } - - @Override - public int setBytes(int index, InputStream in, int length) throws IOException { - checkIndex(index, length); - - int i = toComponentIndex(index); - int readBytes = 0; - - do { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - int localReadBytes = s.setBytes(index - adjustment, in, localLength); - if (localReadBytes < 0) { - if (readBytes == 0) { - return -1; - } else { - break; - } - } - - if (localReadBytes == localLength) { - index += localLength; - length -= localLength; - readBytes += localLength; - i ++; - } else { - index += localReadBytes; - length -= localReadBytes; - readBytes += localReadBytes; - } - } while (length > 0); - - return readBytes; - } - - @Override - public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { - checkIndex(index, length); - - int i = toComponentIndex(index); - int readBytes = 0; - do { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - int localReadBytes = s.setBytes(index - adjustment, in, localLength); - - if (localReadBytes == 0) { - break; - } - - if (localReadBytes < 0) { - if (readBytes == 0) { - return -1; - } else { - break; - } - } - - if (localReadBytes == localLength) { - index += localLength; - length -= localLength; - readBytes += localLength; - i ++; - } else { - index += localReadBytes; - length -= localReadBytes; - readBytes += localReadBytes; - } - } while (length > 0); - - return readBytes; - } - - @Override - public ByteBuf copy(int index, int length) { - checkIndex(index, length); - ByteBuf dst = Unpooled.buffer(length); - copyTo(index, length, toComponentIndex(index), dst); - return dst; - } - - private void copyTo(int index, int length, int componentId, ByteBuf dst) { - int dstIndex = 0; - int i = componentId; - - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - s.getBytes(index - adjustment, dst, dstIndex, localLength); - index += localLength; - dstIndex += localLength; - length -= localLength; - i ++; - } - - dst.writerIndex(dst.capacity()); - } - - @Override - public ByteBuf component(int cIndex) { - return internalComponent(cIndex).duplicate(); - } - - @Override - public ByteBuf componentAtOffset(int offset) { - return internalComponentAtOffset(offset).duplicate(); - } - - @Override - public ByteBuf internalComponent(int cIndex) { - checkComponentIndex(cIndex); - return components.get(cIndex).buf; - } - - @Override - public ByteBuf internalComponentAtOffset(int offset) { - return findComponent(offset).buf; - } - - private Component findComponent(int offset) { - assert !freed; - checkIndex(offset); - - assert !freed; - checkIndex(offset); - - for (int low = 0, high = components.size(); low <= high;) { - int mid = low + high >>> 1; - Component c = components.get(mid); - if (offset >= c.endOffset) { - low = mid + 1; - } else if (offset < c.offset) { - high = mid - 1; - } else { - return c; - } - } - - throw new Error("should not reach here"); - } - - @Override - public int nioBufferCount() { - if (components.size() == 1) { - return components.get(0).buf.nioBufferCount(); - } else { - int count = 0; - int componentsCount = components.size(); - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < componentsCount; i++) { - Component c = components.get(i); - count += c.buf.nioBufferCount(); - } - return count; - } - } - - @Override - public ByteBuffer internalNioBuffer(int index, int length) { - if (components.size() == 1) { - return components.get(0).buf.internalNioBuffer(index, length); - } - throw new UnsupportedOperationException(); - } - - private ByteBuffer copiedNioBuffer(int index, int length) { - assert !freed; - if (components.size() == 1) { - return toNioBuffer(components.get(0).buf, index, length); - } - - ByteBuffer[] buffers = nioBuffers(index, length); - ByteBuffer merged = ByteBuffer.allocate(length).order(order()); - for (ByteBuffer b: buffers) { - merged.put(b); - } - merged.flip(); - return merged; - } - - @Override - public ByteBuffer[] nioBuffers(int index, int length) { - checkIndex(index, length); - if (length == 0) { - return EmptyArrays.EMPTY_BYTE_BUFFERS; - } - - List buffers = new ArrayList(components.size()); - int i = toComponentIndex(index); - while (length > 0) { - Component c = components.get(i); - ByteBuf s = c.buf; - int adjustment = c.offset; - int localLength = Math.min(length, s.capacity() - (index - adjustment)); - switch (s.nioBufferCount()) { - case 0: - throw new UnsupportedOperationException(); - case 1: - buffers.add(s.nioBuffer(index - adjustment, localLength)); - break; - default: - Collections.addAll(buffers, s.nioBuffers(index - adjustment, localLength)); - } - - index += localLength; - length -= localLength; - i ++; - } - - return buffers.toArray(new ByteBuffer[buffers.size()]); - } - - private static ByteBuffer toNioBuffer(ByteBuf buf, int index, int length) { - if (buf.nioBufferCount() == 1) { - return buf.nioBuffer(index, length); - } else { - return buf.copy(index, length).nioBuffer(0, length); - } - } - - @Override - public CompositeByteBuf consolidate() { - assert !freed; - final int numComponents = numComponents(); - if (numComponents <= 1) { - return this; - } - - final Component last = components.get(numComponents - 1); - final int capacity = last.endOffset; - final ByteBuf consolidated = allocBuffer(capacity); - - for (int i = 0; i < numComponents; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - - components.clear(); - components.add(new Component(consolidated)); - updateComponentOffsets(0); - return this; - } - - @Override - public CompositeByteBuf consolidate(int cIndex, int numComponents) { - checkComponentIndex(cIndex, numComponents); - if (numComponents <= 1) { - return this; - } - - final int endCIndex = cIndex + numComponents; - final Component last = components.get(endCIndex - 1); - final int capacity = last.endOffset - components.get(cIndex).offset; - final ByteBuf consolidated = allocBuffer(capacity); - - for (int i = cIndex; i < endCIndex; i ++) { - Component c = components.get(i); - ByteBuf b = c.buf; - consolidated.writeBytes(b); - c.freeIfNecessary(); - } - - components.subList(cIndex + 1, endCIndex).clear(); - components.set(cIndex, new Component(consolidated)); - updateComponentOffsets(cIndex); - return this; - } - - @Override - public CompositeByteBuf discardReadComponents() { - assert !freed; - final int readerIndex = readerIndex(); - if (readerIndex == 0) { - return this; - } - - // Discard everything if (readerIndex = writerIndex = capacity). - int writerIndex = writerIndex(); - if (readerIndex == writerIndex && writerIndex == capacity()) { - for (Component c: components) { - c.freeIfNecessary(); - } - components.clear(); - setIndex(0, 0); - adjustMarkers(readerIndex); - return this; - } - - // Remove read components. - int firstComponentId = toComponentIndex(readerIndex); - for (int i = 0; i < firstComponentId; i ++) { - components.get(i).freeIfNecessary(); - } - components.subList(0, firstComponentId).clear(); - - // Update indexes and markers. - Component first = components.get(0); - updateComponentOffsets(0); - setIndex(readerIndex - first.offset, writerIndex - first.offset); - adjustMarkers(first.offset); - return this; - } - - @Override - public CompositeByteBuf discardReadBytes() { - assert !freed; - final int readerIndex = readerIndex(); - if (readerIndex == 0) { - return this; - } - - // Discard everything if (readerIndex = writerIndex = capacity). - int writerIndex = writerIndex(); - if (readerIndex == writerIndex && writerIndex == capacity()) { - for (Component c: components) { - c.freeIfNecessary(); - } - components.clear(); - setIndex(0, 0); - adjustMarkers(readerIndex); - return this; - } - - // Remove read components. - int firstComponentId = toComponentIndex(readerIndex); - for (int i = 0; i < firstComponentId; i ++) { - components.get(i).freeIfNecessary(); - } - components.subList(0, firstComponentId).clear(); - - // Remove or replace the first readable component with a new slice. - Component c = components.get(0); - int adjustment = readerIndex - c.offset; - if (adjustment == c.length) { - // new slice would be empty, so remove instead - components.remove(0); - } else { - Component newC = new Component(c.buf.slice(adjustment, c.length - adjustment)); - components.set(0, newC); - } - - // Update indexes and markers. - updateComponentOffsets(0); - setIndex(0, writerIndex - readerIndex); - adjustMarkers(readerIndex); - return this; - } - - private ByteBuf allocBuffer(int capacity) { - if (direct) { - return alloc().directBuffer(capacity); - } - return alloc().heapBuffer(capacity); - } - - @Override - public String toString() { - String result = super.toString(); - result = result.substring(0, result.length() - 1); - return result + ", components=" + components.size() + ')'; - } - - private final class Component { - final ByteBuf buf; - final int length; - int offset; - int endOffset; - - Component(ByteBuf buf) { - this.buf = buf; - length = buf.readableBytes(); - } - - void freeIfNecessary() { - // Unwrap so that we can free slices, too. - buf.release(); // We should not get a NPE here. If so, it must be a bug. - } - } - - @Override - public CompositeByteBuf readerIndex(int readerIndex) { - return (CompositeByteBuf) super.readerIndex(readerIndex); - } - - @Override - public CompositeByteBuf writerIndex(int writerIndex) { - return (CompositeByteBuf) super.writerIndex(writerIndex); - } - - @Override - public CompositeByteBuf setIndex(int readerIndex, int writerIndex) { - return (CompositeByteBuf) super.setIndex(readerIndex, writerIndex); - } - - @Override - public CompositeByteBuf clear() { - return (CompositeByteBuf) super.clear(); - } - - @Override - public CompositeByteBuf markReaderIndex() { - return (CompositeByteBuf) super.markReaderIndex(); - } - - @Override - public CompositeByteBuf resetReaderIndex() { - return (CompositeByteBuf) super.resetReaderIndex(); - } - - @Override - public CompositeByteBuf markWriterIndex() { - return (CompositeByteBuf) super.markWriterIndex(); - } - - @Override - public CompositeByteBuf resetWriterIndex() { - return (CompositeByteBuf) super.resetWriterIndex(); - } - - @Override - public CompositeByteBuf ensureWritable(int minWritableBytes) { - return (CompositeByteBuf) super.ensureWritable(minWritableBytes); - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst) { - return (CompositeByteBuf) super.getBytes(index, dst); - } - - @Override - public CompositeByteBuf getBytes(int index, ByteBuf dst, int length) { - return (CompositeByteBuf) super.getBytes(index, dst, length); - } - - @Override - public CompositeByteBuf getBytes(int index, byte[] dst) { - return (CompositeByteBuf) super.getBytes(index, dst); - } - - @Override - public CompositeByteBuf setBoolean(int index, boolean value) { - return (CompositeByteBuf) super.setBoolean(index, value); - } - - @Override - public CompositeByteBuf setChar(int index, int value) { - return (CompositeByteBuf) super.setChar(index, value); - } - - @Override - public CompositeByteBuf setFloat(int index, float value) { - return (CompositeByteBuf) super.setFloat(index, value); - } - - @Override - public CompositeByteBuf setDouble(int index, double value) { - return (CompositeByteBuf) super.setDouble(index, value); - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src) { - return (CompositeByteBuf) super.setBytes(index, src); - } - - @Override - public CompositeByteBuf setBytes(int index, ByteBuf src, int length) { - return (CompositeByteBuf) super.setBytes(index, src, length); - } - - @Override - public CompositeByteBuf setBytes(int index, byte[] src) { - return (CompositeByteBuf) super.setBytes(index, src); - } - - @Override - public CompositeByteBuf setZero(int index, int length) { - return (CompositeByteBuf) super.setZero(index, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst, int length) { - return (CompositeByteBuf) super.readBytes(dst, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) { - return (CompositeByteBuf) super.readBytes(dst, dstIndex, length); - } - - @Override - public CompositeByteBuf readBytes(byte[] dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) { - return (CompositeByteBuf) super.readBytes(dst, dstIndex, length); - } - - @Override - public CompositeByteBuf readBytes(ByteBuffer dst) { - return (CompositeByteBuf) super.readBytes(dst); - } - - @Override - public CompositeByteBuf readBytes(OutputStream out, int length) throws IOException { - return (CompositeByteBuf) super.readBytes(out, length); - } - - @Override - public CompositeByteBuf skipBytes(int length) { - return (CompositeByteBuf) super.skipBytes(length); - } - - @Override - public CompositeByteBuf writeBoolean(boolean value) { - return (CompositeByteBuf) super.writeBoolean(value); - } - - @Override - public CompositeByteBuf writeByte(int value) { - return (CompositeByteBuf) super.writeByte(value); - } - - @Override - public CompositeByteBuf writeShort(int value) { - return (CompositeByteBuf) super.writeShort(value); - } - - @Override - public CompositeByteBuf writeMedium(int value) { - return (CompositeByteBuf) super.writeMedium(value); - } - - @Override - public CompositeByteBuf writeInt(int value) { - return (CompositeByteBuf) super.writeInt(value); - } - - @Override - public CompositeByteBuf writeLong(long value) { - return (CompositeByteBuf) super.writeLong(value); - } - - @Override - public CompositeByteBuf writeChar(int value) { - return (CompositeByteBuf) super.writeChar(value); - } - - @Override - public CompositeByteBuf writeFloat(float value) { - return (CompositeByteBuf) super.writeFloat(value); - } - - @Override - public CompositeByteBuf writeDouble(double value) { - return (CompositeByteBuf) super.writeDouble(value); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src, int length) { - return (CompositeByteBuf) super.writeBytes(src, length); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) { - return (CompositeByteBuf) super.writeBytes(src, srcIndex, length); - } - - @Override - public CompositeByteBuf writeBytes(byte[] src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) { - return (CompositeByteBuf) super.writeBytes(src, srcIndex, length); - } - - @Override - public CompositeByteBuf writeBytes(ByteBuffer src) { - return (CompositeByteBuf) super.writeBytes(src); - } - - @Override - public CompositeByteBuf writeZero(int length) { - return (CompositeByteBuf) super.writeZero(length); - } - - @Override - public CompositeByteBuf retain(int increment) { - return (CompositeByteBuf) super.retain(increment); - } - - @Override - public CompositeByteBuf retain() { - return (CompositeByteBuf) super.retain(); - } - - @Override - public ByteBuffer[] nioBuffers() { - return nioBuffers(readerIndex(), readableBytes()); - } - - @Override - public CompositeByteBuf discardSomeReadBytes() { - return discardReadComponents(); - } - - @Override - protected void deallocate() { - if (freed) { - return; - } - - freed = true; - for (Component c: components) { - c.freeIfNecessary(); - } - - leak.close(); - } - - @Override - public ByteBuf unwrap() { - return null; - } -} diff --git a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java index e79698ed1f..1f9baf5d2a 100644 --- a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java @@ -31,7 +31,7 @@ import java.nio.charset.Charset; /** * An empty {@link ByteBuf} whose capacity and maximum capacity are all {@code 0}. */ -public final class EmptyByteBuf implements ByteBuf { +public final class EmptyByteBuf extends ByteBuf { private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0); private static final long EMPTY_BYTE_BUFFER_ADDRESS; diff --git a/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java b/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java index 7626c35893..9ebdc11111 100644 --- a/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java @@ -24,7 +24,7 @@ import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; import java.nio.charset.Charset; -public final class SwappedByteBuf implements ByteBuf { +public final class SwappedByteBuf extends ByteBuf { private final ByteBuf buf; private final ByteOrder order; diff --git a/buffer/src/main/java/io/netty/buffer/Unpooled.java b/buffer/src/main/java/io/netty/buffer/Unpooled.java index 46fce0fc3a..5fce44772e 100644 --- a/buffer/src/main/java/io/netty/buffer/Unpooled.java +++ b/buffer/src/main/java/io/netty/buffer/Unpooled.java @@ -274,7 +274,7 @@ public final class Unpooled { } if (!components.isEmpty()) { - return new DefaultCompositeByteBuf(ALLOC, false, maxNumComponents, components); + return new CompositeByteBuf(ALLOC, false, maxNumComponents, components); } } @@ -298,7 +298,7 @@ public final class Unpooled { default: for (ByteBuf b: buffers) { if (b.isReadable()) { - return new DefaultCompositeByteBuf(ALLOC, false, maxNumComponents, buffers); + return new CompositeByteBuf(ALLOC, false, maxNumComponents, buffers); } } } @@ -332,7 +332,7 @@ public final class Unpooled { } if (!components.isEmpty()) { - return new DefaultCompositeByteBuf(ALLOC, false, maxNumComponents, components); + return new CompositeByteBuf(ALLOC, false, maxNumComponents, components); } } @@ -350,7 +350,7 @@ public final class Unpooled { * Returns a new big-endian composite buffer with no components. */ public static CompositeByteBuf compositeBuffer(int maxNumComponents) { - return new DefaultCompositeByteBuf(ALLOC, false, maxNumComponents); + return new CompositeByteBuf(ALLOC, false, maxNumComponents); } /** diff --git a/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java b/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java index 38126f497b..274f94822f 100644 --- a/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java @@ -30,7 +30,7 @@ import java.nio.charset.Charset; * A {@link ByteBuf} implementation that wraps another buffer to prevent a user from increasing or decreasing the * wrapped buffer's reference count. */ -final class UnreleasableByteBuf implements ByteBuf { +final class UnreleasableByteBuf extends ByteBuf { private final ByteBuf buf; private SwappedByteBuf swappedBuf; diff --git a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderBuffer.java b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderBuffer.java index b717352f66..918c07d9fb 100644 --- a/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderBuffer.java +++ b/codec/src/main/java/io/netty/handler/codec/ReplayingDecoderBuffer.java @@ -33,7 +33,7 @@ import java.nio.charset.Charset; /** * Special {@link ByteBuf} implementation which is used by the {@link ReplayingDecoder} */ -final class ReplayingDecoderBuffer implements ByteBuf { +final class ReplayingDecoderBuffer extends ByteBuf { private static final Signal REPLAY = ReplayingDecoder.REPLAY;