netty5/buffer/src/main/java/io/net5/buffer/ByteBuf.java

2444 lines
102 KiB
Java
Raw Normal View History

/*
2012-06-04 22:31:44 +02:00
* 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:
*
* https://www.apache.org/licenses/LICENSE-2.0
*
2009-08-28 09:15:49 +02:00
* 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
2009-08-28 09:15:49 +02:00
* License for the specific language governing permissions and limitations
* under the License.
*/
2021-09-17 16:28:14 +02:00
package io.net5.buffer;
2021-09-17 16:28:14 +02:00
import io.net5.util.ByteProcessor;
import io.net5.util.ReferenceCounted;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
2008-08-10 16:25:13 +02:00
import java.nio.charset.UnsupportedCharsetException;
/**
2008-09-02 09:13:20 +02:00
* A random and sequential accessible sequence of zero or more bytes (octets).
* This interface provides an abstract view for one or more primitive byte
* arrays ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers}.
*
* <h3>Creation of a buffer</h3>
*
2008-09-03 03:04:33 +02:00
* It is recommended to create a new buffer using the helper methods in
* {@link Unpooled} rather than calling an individual implementation's
2008-09-03 03:04:33 +02:00
* constructor.
*
* <h3>Random Access Indexing</h3>
*
* Just like an ordinary primitive byte array, {@link ByteBuf} uses
* <a href="https://en.wikipedia.org/wiki/Zero-based_numbering">zero-based indexing</a>.
2012-06-08 12:28:12 +02:00
* It means the index of the first byte is always {@code 0} and the index of the last byte is
* always {@link #capacity() capacity - 1}. For example, to iterate all bytes of a buffer, you
* can do the following, regardless of its internal implementation:
*
* <pre>
* {@link ByteBuf} buffer = ...;
* for (int i = 0; i &lt; buffer.capacity(); i ++) {
* byte b = buffer.getByte(i);
* System.out.println((char) b);
* }
* </pre>
*
* <h3>Sequential Access Indexing</h3>
*
* {@link ByteBuf} provides two pointer variables to support sequential
* read and write operations - {@link #readerIndex() readerIndex} for a read
* operation and {@link #writerIndex() writerIndex} for a write operation
* respectively. The following diagram shows how a buffer is segmented into
* three areas by the two pointers:
*
* <pre>
* +-------------------+------------------+------------------+
* | discardable bytes | readable bytes | writable bytes |
* | | (CONTENT) | |
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
* </pre>
*
* <h4>Readable bytes (the actual content)</h4>
*
* This segment is where the actual data is stored. Any operation whose name
* starts with {@code read} or {@code skip} will get or skip the data at the
* current {@link #readerIndex() readerIndex} and increase it by the number of
* read bytes. If the argument of the read operation is also a
* {@link ByteBuf} and no destination index is specified, the specified
* buffer's {@link #writerIndex() writerIndex} is increased together.
* <p>
* If there's not enough content left, {@link IndexOutOfBoundsException} is
* raised. The default value of newly allocated, wrapped or copied buffer's
* {@link #readerIndex() readerIndex} is {@code 0}.
*
* <pre>
* // Iterates the readable bytes of a buffer.
* {@link ByteBuf} buffer = ...;
* while (buffer.isReadable()) {
* System.out.println(buffer.readByte());
* }
* </pre>
*
* <h4>Writable bytes</h4>
*
* This segment is a undefined space which needs to be filled. Any operation
2015-12-28 02:57:08 +01:00
* whose name starts with {@code write} will write the data at the current
* {@link #writerIndex() writerIndex} and increase it by the number of written
* bytes. If the argument of the write operation is also a {@link ByteBuf},
* and no source index is specified, the specified buffer's
* {@link #readerIndex() readerIndex} is increased together.
* <p>
* If there's not enough writable bytes left, {@link IndexOutOfBoundsException}
* is raised. The default value of newly allocated buffer's
* {@link #writerIndex() writerIndex} is {@code 0}. The default value of
* wrapped or copied buffer's {@link #writerIndex() writerIndex} is the
* {@link #capacity() capacity} of the buffer.
*
* <pre>
* // Fills the writable bytes of a buffer with random integers.
* {@link ByteBuf} buffer = ...;
2013-04-03 15:18:38 +02:00
* while (buffer.maxWritableBytes() >= 4) {
* buffer.writeInt(random.nextInt());
* }
* </pre>
*
* <h4>Discardable bytes</h4>
*
* This segment contains the bytes which were read already by a read operation.
* Initially, the size of this segment is {@code 0}, but its size increases up
* to the {@link #writerIndex() writerIndex} as read operations are executed.
* The read bytes can be discarded by calling {@link #discardReadBytes()} to
* reclaim unused area as depicted by the following diagram:
*
* <pre>
* BEFORE discardReadBytes()
*
* +-------------------+------------------+------------------+
* | discardable bytes | readable bytes | writable bytes |
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
*
*
* AFTER discardReadBytes()
*
* +------------------+--------------------------------------+
* | readable bytes | writable bytes (got more space) |
* +------------------+--------------------------------------+
* | | |
* readerIndex (0) <= writerIndex (decreased) <= capacity
* </pre>
*
* Please note that there is no guarantee about the content of writable bytes
* after calling {@link #discardReadBytes()}. The writable bytes will not be
* moved in most cases and could even be filled with completely different data
* depending on the underlying buffer implementation.
*
* <h4>Clearing the buffer indexes</h4>
*
* You can set both {@link #readerIndex() readerIndex} and
* {@link #writerIndex() writerIndex} to {@code 0} by calling {@link #clear()}.
2008-11-14 08:45:53 +01:00
* It does not clear the buffer content (e.g. filling with {@code 0}) but just
* clears the two pointers. Please also note that the semantic of this
* operation is different from {@link ByteBuffer#clear()}.
*
* <pre>
* BEFORE clear()
*
* +-------------------+------------------+------------------+
* | discardable bytes | readable bytes | writable bytes |
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
*
*
* AFTER clear()
*
* +---------------------------------------------------------+
* | writable bytes (got more space) |
* +---------------------------------------------------------+
* | |
* 0 = readerIndex = writerIndex <= capacity
* </pre>
*
* <h3>Search operations</h3>
*
* For simple single-byte searches, use {@link #indexOf(int, int, byte)} and {@link #bytesBefore(int, int, byte)}.
* {@link #bytesBefore(byte)} is especially useful when you deal with a {@code NUL}-terminated string.
* For complicated searches, use {@link #forEachByte(int, int, ByteProcessor)} with a {@link ByteProcessor}
* implementation.
*
* <h3>Derived buffers</h3>
*
* You can create a view of an existing buffer by calling one of the following methods:
* <ul>
* <li>{@link #duplicate()}</li>
* <li>{@link #slice()}</li>
* <li>{@link #slice(int, int)}</li>
* <li>{@link #readSlice(int)}</li>
* <li>{@link #retainedDuplicate()}</li>
* <li>{@link #retainedSlice()}</li>
* <li>{@link #retainedSlice(int, int)}</li>
* <li>{@link #readRetainedSlice(int)}</li>
* </ul>
* A derived buffer will have an independent {@link #readerIndex() readerIndex},
* {@link #writerIndex() writerIndex}, while it shares
* other internal data representation, just like a NIO buffer does.
* <p>
* In case a completely fresh copy of an existing buffer is required, please
* call {@link #copy()} method instead.
*
* <h4>Non-retained and retained derived buffers</h4>
*
* Note that the {@link #duplicate()}, {@link #slice()}, {@link #slice(int, int)} and {@link #readSlice(int)} does NOT
* call {@link #retain()} on the returned derived buffer, and thus its reference count will NOT be increased. If you
* need to create a derived buffer with increased reference count, consider using {@link #retainedDuplicate()},
* {@link #retainedSlice()}, {@link #retainedSlice(int, int)} and {@link #readRetainedSlice(int)} which may return
* a buffer implementation that produces less garbage.
*
* <h3>Conversion to existing JDK types</h3>
*
2010-05-06 09:33:26 +02:00
* <h4>Byte array</h4>
*
* If a {@link ByteBuf} is backed by a byte array (i.e. {@code byte[]}),
2010-05-06 09:33:26 +02:00
* you can access it directly via the {@link #array()} method. To determine
* if a buffer is backed by a byte array, {@link #hasArray()} should be used.
*
* <h4>NIO Buffers</h4>
2008-08-10 07:09:55 +02:00
*
* If a {@link ByteBuf} can be converted into an NIO {@link ByteBuffer} which shares its
* content (i.e. view buffer), you can get it via the {@link #nioBuffer()} method. To determine
2013-03-28 10:01:26 +01:00
* if a buffer can be converted into an NIO buffer, use {@link #nioBufferCount()}.
2008-08-10 07:09:55 +02:00
*
* <h4>Strings</h4>
2008-08-10 07:09:55 +02:00
*
* Various {@link #toString(Charset)} methods convert a {@link ByteBuf}
* into a {@link String}. Please note that {@link #toString()} is not a
2008-08-10 07:09:55 +02:00
* conversion method.
*
* <h4>I/O Streams</h4>
2008-08-10 07:09:55 +02:00
*
* Please refer to {@link ByteBufInputStream} and
* {@link ByteBufOutputStream}.
*/
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf>, ByteBufConvertible {
/**
* Returns the number of bytes (octets) this buffer can contain.
*/
public abstract int capacity();
/**
* Adjusts the capacity of this buffer. If the {@code newCapacity} is less than the current
* capacity, the content of this buffer is truncated. If the {@code newCapacity} is greater
* than the current capacity, the buffer is appended with unspecified data whose length is
* {@code (newCapacity - currentCapacity)}.
*
* @throws IllegalArgumentException if the {@code newCapacity} is greater than {@link #maxCapacity()}
*/
public abstract ByteBuf capacity(int newCapacity);
/**
* Returns the maximum allowed capacity of this buffer. This value provides an upper
* bound on {@link #capacity()}.
*/
public abstract int maxCapacity();
ByteBufAllocator API w/ ByteBuf perf improvements This commit introduces a new API for ByteBuf allocation which fixes issue #643 along with refactoring of ByteBuf for simplicity and better performance. (see #62) A user can configure the ByteBufAllocator of a Channel via ChannelOption.ALLOCATOR or ChannelConfig.get/setAllocator(). The default allocator is currently UnpooledByteBufAllocator.HEAP_BY_DEFAULT. To allocate a buffer, do not use Unpooled anymore. do the following: ctx.alloc().buffer(...); // allocator chooses the buffer type. ctx.alloc().heapBuffer(...); ctx.alloc().directBuffer(...); To deallocate a buffer, use the unsafe free() operation: ((UnsafeByteBuf) buf).free(); The following is the list of the relevant changes: - Add ChannelInboundHandler.freeInboundBuffer() and ChannelOutboundHandler.freeOutboundBuffer() to let a user free the buffer he or she allocated. ChannelHandler adapter classes implement is already, so most users won't need to call free() by themselves. freeIn/OutboundBuffer() methods are invoked when a Channel is closed and deregistered. - All ByteBuf by contract must implement UnsafeByteBuf. To access an unsafe operation: ((UnsafeByteBuf) buf).internalNioBuffer() - Replace WrappedByteBuf and ByteBuf.Unsafe with UnsafeByteBuf to simplify overall class hierarchy and to avoid unnecesary instantiation of Unsafe instances on an unsafe operation. - Remove buffer reference counting which is confusing - Instantiate SwappedByteBuf lazily to avoid instantiation cost - Rename ChannelFutureFactory to ChannelPropertyAccess and move common methods between Channel and ChannelHandlerContext there. Also made it package-private to hide it from a user. - Remove unused unsafe operations such as newBuffer() - Add DetectionUtil.canFreeDirectBuffer() so that an allocator decides which buffer type to use safely
2012-11-15 22:04:37 +01:00
/**
* Returns the {@link ByteBufAllocator} which created this buffer.
*/
public abstract ByteBufAllocator alloc();
ByteBufAllocator API w/ ByteBuf perf improvements This commit introduces a new API for ByteBuf allocation which fixes issue #643 along with refactoring of ByteBuf for simplicity and better performance. (see #62) A user can configure the ByteBufAllocator of a Channel via ChannelOption.ALLOCATOR or ChannelConfig.get/setAllocator(). The default allocator is currently UnpooledByteBufAllocator.HEAP_BY_DEFAULT. To allocate a buffer, do not use Unpooled anymore. do the following: ctx.alloc().buffer(...); // allocator chooses the buffer type. ctx.alloc().heapBuffer(...); ctx.alloc().directBuffer(...); To deallocate a buffer, use the unsafe free() operation: ((UnsafeByteBuf) buf).free(); The following is the list of the relevant changes: - Add ChannelInboundHandler.freeInboundBuffer() and ChannelOutboundHandler.freeOutboundBuffer() to let a user free the buffer he or she allocated. ChannelHandler adapter classes implement is already, so most users won't need to call free() by themselves. freeIn/OutboundBuffer() methods are invoked when a Channel is closed and deregistered. - All ByteBuf by contract must implement UnsafeByteBuf. To access an unsafe operation: ((UnsafeByteBuf) buf).internalNioBuffer() - Replace WrappedByteBuf and ByteBuf.Unsafe with UnsafeByteBuf to simplify overall class hierarchy and to avoid unnecesary instantiation of Unsafe instances on an unsafe operation. - Remove buffer reference counting which is confusing - Instantiate SwappedByteBuf lazily to avoid instantiation cost - Rename ChannelFutureFactory to ChannelPropertyAccess and move common methods between Channel and ChannelHandlerContext there. Also made it package-private to hide it from a user. - Remove unused unsafe operations such as newBuffer() - Add DetectionUtil.canFreeDirectBuffer() so that an allocator decides which buffer type to use safely
2012-11-15 22:04:37 +01:00
/**
* Returns the <a href="https://en.wikipedia.org/wiki/Endianness">endianness</a>
* of this buffer.
*
* @deprecated use the Little Endian accessors, e.g. {@code getShortLE}, {@code getIntLE}
* instead of creating a buffer with swapped {@code endianness}.
*/
@Deprecated
public abstract ByteOrder order();
/**
* Returns a buffer with the specified {@code endianness} which shares the whole region,
* indexes of this buffer. Modifying the content, the indexes of the
* returned buffer or this buffer affects each other's content, and indexes. If the
* specified {@code endianness} is identical to this buffer's byte order, this method can
* return {@code this}. This method does not modify {@code readerIndex} or {@code writerIndex}
* of this buffer.
*
* @deprecated use the Little Endian accessors, e.g. {@code getShortLE}, {@code getIntLE}
* instead of creating a buffer with swapped {@code endianness}.
*/
@Deprecated
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
*/
public abstract ByteBuf unwrap();
/**
* Returns {@code true} if and only if this buffer is backed by an
* NIO direct buffer.
*/
public abstract boolean isDirect();
/**
* Returns {@code true} if and only if this buffer is read-only.
*/
public abstract boolean isReadOnly();
/**
* Returns a read-only version of this buffer.
*/
public abstract ByteBuf asReadOnly();
/**
* Returns the {@code readerIndex} of this buffer.
*/
public abstract int readerIndex();
/**
* Sets the {@code readerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code readerIndex} is
* less than {@code 0} or
* greater than {@code this.writerIndex}
*/
public abstract ByteBuf readerIndex(int readerIndex);
/**
* Returns the {@code writerIndex} of this buffer.
*/
public abstract int writerIndex();
/**
* Sets the {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code writerIndex} is
* less than {@code this.readerIndex} or
* greater than {@code this.capacity}
*/
public abstract ByteBuf writerIndex(int writerIndex);
/**
* Sets the {@code readerIndex} and {@code writerIndex} of this buffer
2008-08-10 16:25:13 +02:00
* in one shot. This method is useful when you have to worry about the
* invocation order of {@link #readerIndex(int)} and {@link #writerIndex(int)}
* methods. For example, the following code will fail:
*
* <pre>
* // Create a buffer whose readerIndex, writerIndex and capacity are
* // 0, 0 and 8 respectively.
* {@link ByteBuf} buf = {@link Unpooled}.buffer(8);
*
* // IndexOutOfBoundsException is thrown because the specified
* // readerIndex (2) cannot be greater than the current writerIndex (0).
* buf.readerIndex(2);
* buf.writerIndex(4);
* </pre>
*
* The following code will also fail:
*
* <pre>
* // Create a buffer whose readerIndex, writerIndex and capacity are
* // 0, 8 and 8 respectively.
* {@link ByteBuf} buf = {@link Unpooled}.wrappedBuffer(new byte[8]);
*
* // readerIndex becomes 8.
* buf.readLong();
*
* // IndexOutOfBoundsException is thrown because the specified
* // writerIndex (4) cannot be less than the current readerIndex (8).
* buf.writerIndex(4);
* buf.readerIndex(2);
* </pre>
*
* By contrast, this method guarantees that it never
* throws an {@link IndexOutOfBoundsException} as long as the specified
* indexes meet basic constraints, regardless what the current index
* values of the buffer are:
*
* <pre>
* // No matter what the current state of the buffer is, the following
* // call always succeeds as long as the capacity of the buffer is not
* // less than 4.
* buf.setIndex(2, 4);
* </pre>
*
* @throws IndexOutOfBoundsException
* if the specified {@code readerIndex} is less than 0,
* if the specified {@code writerIndex} is less than the specified
* {@code readerIndex} or if the specified {@code writerIndex} is
2008-08-10 16:25:13 +02:00
* greater than {@code this.capacity}
*/
public abstract ByteBuf setIndex(int readerIndex, int writerIndex);
/**
* Returns the number of readable bytes which is logically equivalent to
* {@code (this.writerIndex - this.readerIndex)}, but maybe overridden to accommodate
* specialized behavior (e.g. write only).
*/
public abstract int readableBytes();
/**
* Returns the number of writable bytes which is logically equivalent to
* {@code (this.capacity - this.writerIndex)}, but maybe overridden to accommodate
* specialized behavior (e.g. read only).
*/
public abstract int writableBytes();
/**
* Returns the maximum possible number of writable bytes, which is logically equivalent to
* {@code (this.maxCapacity - this.writerIndex)}, but maybe overridden to accommodate
* specialized behavior (e.g. read only).
*/
public abstract int maxWritableBytes();
/**
* Returns the maximum number of bytes which can be written for certain without involving
* an internal reallocation or data-copy. The returned value will be &ge; {@link #writableBytes()}
* and &le; {@link #maxWritableBytes()}.
*/
public int maxFastWritableBytes() {
return writableBytes();
}
/**
* Returns {@code true} if and only if {@link #readableBytes()} is greater than {@code 0}.
*/
public abstract boolean isReadable();
Revamp the core API to reduce memory footprint and consumption The API changes made so far turned out to increase the memory footprint and consumption while our intention was actually decreasing them. Memory consumption issue: When there are many connections which does not exchange data frequently, the old Netty 4 API spent a lot more memory than 3 because it always allocates per-handler buffer for each connection unless otherwise explicitly stated by a user. In a usual real world load, a client doesn't always send requests without pausing, so the idea of having a buffer whose life cycle if bound to the life cycle of a connection didn't work as expected. Memory footprint issue: The old Netty 4 API decreased overall memory footprint by a great deal in many cases. It was mainly because the old Netty 4 API did not allocate a new buffer and event object for each read. Instead, it created a new buffer for each handler in a pipeline. This works pretty well as long as the number of handlers in a pipeline is only a few. However, for a highly modular application with many handlers which handles connections which lasts for relatively short period, it actually makes the memory footprint issue much worse. Changes: All in all, this is about retaining all the good changes we made in 4 so far such as better thread model and going back to the way how we dealt with message events in 3. To fix the memory consumption/footprint issue mentioned above, we made a hard decision to break the backward compatibility again with the following changes: - Remove MessageBuf - Merge Buf into ByteBuf - Merge ChannelInboundByte/MessageHandler and ChannelStateHandler into ChannelInboundHandler - Similar changes were made to the adapter classes - Merge ChannelOutboundByte/MessageHandler and ChannelOperationHandler into ChannelOutboundHandler - Similar changes were made to the adapter classes - Introduce MessageList which is similar to `MessageEvent` in Netty 3 - Replace inboundBufferUpdated(ctx) with messageReceived(ctx, MessageList) - Replace flush(ctx, promise) with write(ctx, MessageList, promise) - Remove ByteToByteEncoder/Decoder/Codec - Replaced by MessageToByteEncoder<ByteBuf>, ByteToMessageDecoder<ByteBuf>, and ByteMessageCodec<ByteBuf> - Merge EmbeddedByteChannel and EmbeddedMessageChannel into EmbeddedChannel - Add SimpleChannelInboundHandler which is sometimes more useful than ChannelInboundHandlerAdapter - Bring back Channel.isWritable() from Netty 3 - Add ChannelInboundHandler.channelWritabilityChanges() event - Add RecvByteBufAllocator configuration property - Similar to ReceiveBufferSizePredictor in Netty 3 - Some existing configuration properties such as DatagramChannelConfig.receivePacketSize is gone now. - Remove suspend/resumeIntermediaryDeallocation() in ByteBuf This change would have been impossible without @normanmaurer's help. He fixed, ported, and improved many parts of the changes.
2013-05-28 13:40:19 +02:00
/**
* Returns {@code true} if and only if this buffer contains equal to or more than the specified number of elements.
*/
public abstract boolean isReadable(int size);
Revamp the core API to reduce memory footprint and consumption The API changes made so far turned out to increase the memory footprint and consumption while our intention was actually decreasing them. Memory consumption issue: When there are many connections which does not exchange data frequently, the old Netty 4 API spent a lot more memory than 3 because it always allocates per-handler buffer for each connection unless otherwise explicitly stated by a user. In a usual real world load, a client doesn't always send requests without pausing, so the idea of having a buffer whose life cycle if bound to the life cycle of a connection didn't work as expected. Memory footprint issue: The old Netty 4 API decreased overall memory footprint by a great deal in many cases. It was mainly because the old Netty 4 API did not allocate a new buffer and event object for each read. Instead, it created a new buffer for each handler in a pipeline. This works pretty well as long as the number of handlers in a pipeline is only a few. However, for a highly modular application with many handlers which handles connections which lasts for relatively short period, it actually makes the memory footprint issue much worse. Changes: All in all, this is about retaining all the good changes we made in 4 so far such as better thread model and going back to the way how we dealt with message events in 3. To fix the memory consumption/footprint issue mentioned above, we made a hard decision to break the backward compatibility again with the following changes: - Remove MessageBuf - Merge Buf into ByteBuf - Merge ChannelInboundByte/MessageHandler and ChannelStateHandler into ChannelInboundHandler - Similar changes were made to the adapter classes - Merge ChannelOutboundByte/MessageHandler and ChannelOperationHandler into ChannelOutboundHandler - Similar changes were made to the adapter classes - Introduce MessageList which is similar to `MessageEvent` in Netty 3 - Replace inboundBufferUpdated(ctx) with messageReceived(ctx, MessageList) - Replace flush(ctx, promise) with write(ctx, MessageList, promise) - Remove ByteToByteEncoder/Decoder/Codec - Replaced by MessageToByteEncoder<ByteBuf>, ByteToMessageDecoder<ByteBuf>, and ByteMessageCodec<ByteBuf> - Merge EmbeddedByteChannel and EmbeddedMessageChannel into EmbeddedChannel - Add SimpleChannelInboundHandler which is sometimes more useful than ChannelInboundHandlerAdapter - Bring back Channel.isWritable() from Netty 3 - Add ChannelInboundHandler.channelWritabilityChanges() event - Add RecvByteBufAllocator configuration property - Similar to ReceiveBufferSizePredictor in Netty 3 - Some existing configuration properties such as DatagramChannelConfig.receivePacketSize is gone now. - Remove suspend/resumeIntermediaryDeallocation() in ByteBuf This change would have been impossible without @normanmaurer's help. He fixed, ported, and improved many parts of the changes.
2013-05-28 13:40:19 +02:00
/**
* Returns {@code true} if and only if {@link #writableBytes()} is greater than {@code 0}.
*/
public abstract boolean isWritable();
Revamp the core API to reduce memory footprint and consumption The API changes made so far turned out to increase the memory footprint and consumption while our intention was actually decreasing them. Memory consumption issue: When there are many connections which does not exchange data frequently, the old Netty 4 API spent a lot more memory than 3 because it always allocates per-handler buffer for each connection unless otherwise explicitly stated by a user. In a usual real world load, a client doesn't always send requests without pausing, so the idea of having a buffer whose life cycle if bound to the life cycle of a connection didn't work as expected. Memory footprint issue: The old Netty 4 API decreased overall memory footprint by a great deal in many cases. It was mainly because the old Netty 4 API did not allocate a new buffer and event object for each read. Instead, it created a new buffer for each handler in a pipeline. This works pretty well as long as the number of handlers in a pipeline is only a few. However, for a highly modular application with many handlers which handles connections which lasts for relatively short period, it actually makes the memory footprint issue much worse. Changes: All in all, this is about retaining all the good changes we made in 4 so far such as better thread model and going back to the way how we dealt with message events in 3. To fix the memory consumption/footprint issue mentioned above, we made a hard decision to break the backward compatibility again with the following changes: - Remove MessageBuf - Merge Buf into ByteBuf - Merge ChannelInboundByte/MessageHandler and ChannelStateHandler into ChannelInboundHandler - Similar changes were made to the adapter classes - Merge ChannelOutboundByte/MessageHandler and ChannelOperationHandler into ChannelOutboundHandler - Similar changes were made to the adapter classes - Introduce MessageList which is similar to `MessageEvent` in Netty 3 - Replace inboundBufferUpdated(ctx) with messageReceived(ctx, MessageList) - Replace flush(ctx, promise) with write(ctx, MessageList, promise) - Remove ByteToByteEncoder/Decoder/Codec - Replaced by MessageToByteEncoder<ByteBuf>, ByteToMessageDecoder<ByteBuf>, and ByteMessageCodec<ByteBuf> - Merge EmbeddedByteChannel and EmbeddedMessageChannel into EmbeddedChannel - Add SimpleChannelInboundHandler which is sometimes more useful than ChannelInboundHandlerAdapter - Bring back Channel.isWritable() from Netty 3 - Add ChannelInboundHandler.channelWritabilityChanges() event - Add RecvByteBufAllocator configuration property - Similar to ReceiveBufferSizePredictor in Netty 3 - Some existing configuration properties such as DatagramChannelConfig.receivePacketSize is gone now. - Remove suspend/resumeIntermediaryDeallocation() in ByteBuf This change would have been impossible without @normanmaurer's help. He fixed, ported, and improved many parts of the changes.
2013-05-28 13:40:19 +02:00
/**
* Returns {@code true} if and only if this buffer has enough room to allow writing the specified number of
* elements.
*/
public abstract boolean isWritable(int size);
Revamp the core API to reduce memory footprint and consumption The API changes made so far turned out to increase the memory footprint and consumption while our intention was actually decreasing them. Memory consumption issue: When there are many connections which does not exchange data frequently, the old Netty 4 API spent a lot more memory than 3 because it always allocates per-handler buffer for each connection unless otherwise explicitly stated by a user. In a usual real world load, a client doesn't always send requests without pausing, so the idea of having a buffer whose life cycle if bound to the life cycle of a connection didn't work as expected. Memory footprint issue: The old Netty 4 API decreased overall memory footprint by a great deal in many cases. It was mainly because the old Netty 4 API did not allocate a new buffer and event object for each read. Instead, it created a new buffer for each handler in a pipeline. This works pretty well as long as the number of handlers in a pipeline is only a few. However, for a highly modular application with many handlers which handles connections which lasts for relatively short period, it actually makes the memory footprint issue much worse. Changes: All in all, this is about retaining all the good changes we made in 4 so far such as better thread model and going back to the way how we dealt with message events in 3. To fix the memory consumption/footprint issue mentioned above, we made a hard decision to break the backward compatibility again with the following changes: - Remove MessageBuf - Merge Buf into ByteBuf - Merge ChannelInboundByte/MessageHandler and ChannelStateHandler into ChannelInboundHandler - Similar changes were made to the adapter classes - Merge ChannelOutboundByte/MessageHandler and ChannelOperationHandler into ChannelOutboundHandler - Similar changes were made to the adapter classes - Introduce MessageList which is similar to `MessageEvent` in Netty 3 - Replace inboundBufferUpdated(ctx) with messageReceived(ctx, MessageList) - Replace flush(ctx, promise) with write(ctx, MessageList, promise) - Remove ByteToByteEncoder/Decoder/Codec - Replaced by MessageToByteEncoder<ByteBuf>, ByteToMessageDecoder<ByteBuf>, and ByteMessageCodec<ByteBuf> - Merge EmbeddedByteChannel and EmbeddedMessageChannel into EmbeddedChannel - Add SimpleChannelInboundHandler which is sometimes more useful than ChannelInboundHandlerAdapter - Bring back Channel.isWritable() from Netty 3 - Add ChannelInboundHandler.channelWritabilityChanges() event - Add RecvByteBufAllocator configuration property - Similar to ReceiveBufferSizePredictor in Netty 3 - Some existing configuration properties such as DatagramChannelConfig.receivePacketSize is gone now. - Remove suspend/resumeIntermediaryDeallocation() in ByteBuf This change would have been impossible without @normanmaurer's help. He fixed, ported, and improved many parts of the changes.
2013-05-28 13:40:19 +02:00
/**
* Sets the {@code readerIndex} and {@code writerIndex} of this buffer to
* {@code 0}.
* This method is identical to {@link #setIndex(int, int) setIndex(0, 0)}.
* <p>
* Please note that the behavior of this method is different
* from that of NIO buffer, which sets the {@code limit} to
2008-08-10 16:25:13 +02:00
* the {@code capacity} of the buffer.
*/
public abstract ByteBuf clear();
/**
* Discards the bytes between the 0th index and {@code readerIndex}.
* It moves the bytes between {@code readerIndex} and {@code writerIndex}
* to the 0th index, and sets {@code readerIndex} and {@code writerIndex}
* to {@code 0} and {@code oldWriterIndex - oldReaderIndex} respectively.
* <p>
2008-08-10 16:25:13 +02:00
* Please refer to the class documentation for more detailed explanation.
*/
public abstract ByteBuf discardReadBytes();
/**
* Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard
* some, all, or none of read bytes depending on its internal implementation to reduce
* overall memory bandwidth consumption at the cost of potentially additional memory
* consumption.
*/
public abstract ByteBuf discardSomeReadBytes();
/**
* Expands the buffer {@link #capacity()} to make sure the number of
* {@linkplain #writableBytes() writable bytes} is equal to or greater than the
* specified value. If there are enough writable bytes in this buffer, this method
* returns with no side effect.
*
* @param minWritableBytes
* the expected minimum number of writable bytes
* @throws IndexOutOfBoundsException
* if {@link #writerIndex()} + {@code minWritableBytes} &gt; {@link #maxCapacity()}.
* @see #capacity(int)
*/
public abstract ByteBuf ensureWritable(int minWritableBytes);
/**
* Expands the buffer {@link #capacity()} to make sure the number of
* {@linkplain #writableBytes() writable bytes} is equal to or greater than the
* specified value. Unlike {@link #ensureWritable(int)}, this method returns a status code.
*
* @param minWritableBytes
* the expected minimum number of writable bytes
* @param force
* When {@link #writerIndex()} + {@code minWritableBytes} &gt; {@link #maxCapacity()}:
* <ul>
* <li>{@code true} - the capacity of the buffer is expanded to {@link #maxCapacity()}</li>
* <li>{@code false} - the capacity of the buffer is unchanged</li>
* </ul>
* @return {@code 0} if the buffer has enough writable bytes, and its capacity is unchanged.
* {@code 1} if the buffer does not have enough bytes, and its capacity is unchanged.
* {@code 2} if the buffer has enough writable bytes, and its capacity has been increased.
* {@code 3} if the buffer does not have enough bytes, but its capacity has been
* increased to its maximum.
*/
public abstract int ensureWritable(int minWritableBytes, boolean force);
2012-05-31 21:03:01 +02:00
/**
* Gets a boolean at the specified absolute (@code index) in this buffer.
* This method does not modify the {@code readerIndex} or {@code writerIndex}
* of this buffer.
2012-05-31 21:03:01 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 1} is greater than {@code this.capacity}
*/
public abstract boolean getBoolean(int index);
/**
* Gets a byte at the specified absolute {@code index} in this buffer.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 1} is greater than {@code this.capacity}
*/
public abstract byte getByte(int index);
2008-08-10 02:52:59 +02:00
/**
* Gets an unsigned byte at the specified absolute {@code index} in this
2009-04-24 15:56:35 +02:00
* buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
2008-08-10 02:52:59 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 1} is greater than {@code this.capacity}
2008-08-10 02:52:59 +02:00
*/
public abstract short getUnsignedByte(int index);
2008-08-10 02:52:59 +02:00
/**
* Gets a 16-bit short integer at the specified absolute {@code index} in
2009-04-24 15:56:35 +02:00
* this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 2} is greater than {@code this.capacity}
*/
public abstract short getShort(int index);
/**
* Gets a 16-bit short integer at the specified absolute {@code index} in
* this buffer in Little Endian Byte Order. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
public abstract short getShortLE(int index);
2008-08-10 02:52:59 +02:00
/**
* Gets an unsigned 16-bit short integer at the specified absolute
2009-04-24 15:56:35 +02:00
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
2008-08-10 02:52:59 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 2} is greater than {@code this.capacity}
2008-08-10 02:52:59 +02:00
*/
public abstract int getUnsignedShort(int index);
2008-08-10 02:52:59 +02:00
/**
* Gets an unsigned 16-bit short integer at the specified absolute
* {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
public abstract int getUnsignedShortLE(int index);
/**
* Gets a 24-bit medium integer at the specified absolute {@code index} in
2009-04-24 15:56:35 +02:00
* this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 3} is greater than {@code this.capacity}
*/
public abstract int getMedium(int index);
/**
* Gets a 24-bit medium integer at the specified absolute {@code index} in
* this buffer in the Little Endian Byte Order. This method does not
* modify {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 3} is greater than {@code this.capacity}
*/
public abstract int getMediumLE(int index);
2008-08-10 02:52:59 +02:00
/**
* Gets an unsigned 24-bit medium integer at the specified absolute
2009-04-24 15:56:35 +02:00
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
2008-08-10 02:52:59 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 3} is greater than {@code this.capacity}
2008-08-10 02:52:59 +02:00
*/
public abstract int getUnsignedMedium(int index);
2008-08-10 02:52:59 +02:00
/**
* Gets an unsigned 24-bit medium integer at the specified absolute
* {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 3} is greater than {@code this.capacity}
*/
public abstract int getUnsignedMediumLE(int index);
/**
* Gets a 32-bit integer at the specified absolute {@code index} in
2009-04-24 15:56:35 +02:00
* this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 4} is greater than {@code this.capacity}
*/
public abstract int getInt(int index);
/**
* Gets a 32-bit integer at the specified absolute {@code index} in
* this buffer with Little Endian Byte Order. This method does not
* modify {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public abstract int getIntLE(int index);
2008-08-10 02:52:59 +02:00
/**
* Gets an unsigned 32-bit integer at the specified absolute {@code index}
2009-04-24 15:56:35 +02:00
* in this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
2008-08-10 02:52:59 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 4} is greater than {@code this.capacity}
2008-08-10 02:52:59 +02:00
*/
public abstract long getUnsignedInt(int index);
2008-08-10 02:52:59 +02:00
/**
* Gets an unsigned 32-bit integer at the specified absolute {@code index}
* in this buffer in Little Endian Byte Order. This method does not
* modify {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public abstract long getUnsignedIntLE(int index);
/**
* Gets a 64-bit long integer at the specified absolute {@code index} in
2009-04-24 15:56:35 +02:00
* this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 8} is greater than {@code this.capacity}
*/
public abstract long getLong(int index);
/**
* Gets a 64-bit long integer at the specified absolute {@code index} in
* this buffer in Little Endian Byte Order. This method does not
* modify {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
public abstract long getLongLE(int index);
/**
* Gets a 2-byte UTF-16 character at the specified absolute
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
public abstract char getChar(int index);
/**
* Gets a 32-bit floating point number at the specified absolute
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public abstract float getFloat(int index);
/**
* Gets a 32-bit floating point number at the specified absolute
* {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public float getFloatLE(int index) {
return Float.intBitsToFloat(getIntLE(index));
}
/**
* Gets a 64-bit floating point number at the specified absolute
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
public abstract double getDouble(int index);
/**
* Gets a 64-bit floating point number at the specified absolute
* {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
public double getDoubleLE(int index) {
return Double.longBitsToDouble(getLongLE(index));
}
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index} until the destination becomes
* non-writable. This method is basically same with
* {@link #getBytes(int, ByteBuf, int, int)}, except that this
2008-08-10 16:25:13 +02:00
* method increases the {@code writerIndex} of the destination by the
* number of the transferred bytes while
* {@link #getBytes(int, ByteBuf, int, int)} does not.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* the source buffer (i.e. {@code this}).
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + dst.writableBytes} is greater than
* {@code this.capacity}
*/
public abstract ByteBuf getBytes(int index, ByteBuf dst);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index}. This method is basically same
* with {@link #getBytes(int, ByteBuf, int, int)}, except that this
* method increases the {@code writerIndex} of the destination by the
* number of the transferred bytes while
* {@link #getBytes(int, ByteBuf, int, int)} does not.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* the source buffer (i.e. {@code this}).
*
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code length} is greater than {@code dst.writableBytes}
*/
public abstract ByteBuf getBytes(int index, ByteBuf dst, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex}
* of both the source (i.e. {@code this}) and the destination.
*
2008-08-10 16:25:13 +02:00
* @param dstIndex the first index of the destination
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if the specified {@code dstIndex} is less than {@code 0},
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code dstIndex + length} is greater than
* {@code dst.capacity}
*/
public abstract ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + dst.length} is greater than
* {@code this.capacity}
*/
public abstract ByteBuf getBytes(int index, byte[] dst);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex}
* of this buffer.
*
2008-08-10 16:25:13 +02:00
* @param dstIndex the first index of the destination
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if the specified {@code dstIndex} is less than {@code 0},
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code dstIndex + length} is greater than
* {@code dst.length}
*/
public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index} until the destination's position
* reaches its limit.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer while the destination's {@code position} will be increased.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + dst.remaining()} is greater than
* {@code this.capacity}
*/
public abstract ByteBuf getBytes(int index, ByteBuffer dst);
/**
* Transfers this buffer's data to the specified stream starting at the
* specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
2008-08-10 16:25:13 +02:00
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than
* {@code this.capacity}
* @throws IOException
* if the specified stream threw an exception during I/O
*/
public abstract ByteBuf getBytes(int index, OutputStream out, int length) throws IOException;
/**
* Transfers this buffer's data to the specified channel starting at the
* specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
2008-08-10 16:25:13 +02:00
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes written out to the specified channel
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than
* {@code this.capacity}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int getBytes(int index, GatheringByteChannel out, int length) throws IOException;
/**
* Transfers this buffer's data starting at the specified absolute {@code index}
* to the specified channel starting at the given file position.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer. This method does not modify the channel's position.
*
* @param position the file position at which the transfer is to begin
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes written out to the specified channel
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than
* {@code this.capacity}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int getBytes(int index, FileChannel out, long position, int length) throws IOException;
/**
* Gets a {@link CharSequence} with the given length at the given index.
*
* @param length the length to read
* @param charset that should be used
* @return the sequence
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
public abstract CharSequence getCharSequence(int index, int length, Charset charset);
/**
* Sets the specified boolean at the specified absolute {@code index} in this
* buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 1} is greater than {@code this.capacity}
*/
public abstract ByteBuf setBoolean(int index, boolean value);
2012-05-31 21:03:01 +02:00
/**
* Sets the specified byte at the specified absolute {@code index} in this
* buffer. The 24 high-order bits of the specified value are ignored.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 1} is greater than {@code this.capacity}
*/
public abstract ByteBuf setByte(int index, int value);
/**
* Sets the specified 16-bit short integer at the specified absolute
* {@code index} in this buffer. The 16 high-order bits of the specified
* value are ignored.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 2} is greater than {@code this.capacity}
*/
public abstract ByteBuf setShort(int index, int value);
/**
* Sets the specified 16-bit short integer at the specified absolute
* {@code index} in this buffer with the Little Endian Byte Order.
* The 16 high-order bits of the specified value are ignored.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
public abstract ByteBuf setShortLE(int index, int value);
/**
* Sets the specified 24-bit medium integer at the specified absolute
* {@code index} in this buffer. Please note that the most significant
* byte is ignored in the specified value.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 3} is greater than {@code this.capacity}
*/
public abstract ByteBuf setMedium(int index, int value);
/**
* Sets the specified 24-bit medium integer at the specified absolute
* {@code index} in this buffer in the Little Endian Byte Order.
* Please note that the most significant byte is ignored in the
* specified value.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 3} is greater than {@code this.capacity}
*/
public abstract ByteBuf setMediumLE(int index, int value);
/**
* Sets the specified 32-bit integer at the specified absolute
* {@code index} in this buffer.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 4} is greater than {@code this.capacity}
*/
public abstract ByteBuf setInt(int index, int value);
/**
* Sets the specified 32-bit integer at the specified absolute
* {@code index} in this buffer with Little Endian byte order
* .
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public abstract ByteBuf setIntLE(int index, int value);
/**
* Sets the specified 64-bit long integer at the specified absolute
* {@code index} in this buffer.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* {@code index + 8} is greater than {@code this.capacity}
*/
public abstract ByteBuf setLong(int index, long value);
/**
* Sets the specified 64-bit long integer at the specified absolute
* {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
public abstract ByteBuf setLongLE(int index, long value);
/**
* Sets the specified 2-byte UTF-16 character at the specified absolute
* {@code index} in this buffer.
* The 16 high-order bits of the specified value are ignored.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
public abstract ByteBuf setChar(int index, int value);
/**
* Sets the specified 32-bit floating-point number at the specified
* absolute {@code index} in this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public abstract ByteBuf setFloat(int index, float value);
/**
* Sets the specified 32-bit floating-point number at the specified
* absolute {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public ByteBuf setFloatLE(int index, float value) {
return setIntLE(index, Float.floatToRawIntBits(value));
}
/**
* Sets the specified 64-bit floating-point number at the specified
* absolute {@code index} in this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
public abstract ByteBuf setDouble(int index, double value);
/**
* Sets the specified 64-bit floating-point number at the specified
* absolute {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
public ByteBuf setDoubleLE(int index, double value) {
return setLongLE(index, Double.doubleToRawLongBits(value));
}
2008-08-10 07:09:55 +02:00
/**
* Transfers the specified source buffer's data to this buffer starting at
2010-05-06 09:33:26 +02:00
* the specified absolute {@code index} until the source buffer becomes
2008-08-10 16:25:13 +02:00
* unreadable. This method is basically same with
* {@link #setBytes(int, ByteBuf, int, int)}, except that this
* method increases the {@code readerIndex} of the source buffer by
2008-08-10 16:25:13 +02:00
* the number of the transferred bytes while
* {@link #setBytes(int, ByteBuf, int, int)} does not.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer (i.e. {@code this}).
2008-08-10 07:09:55 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + src.readableBytes} is greater than
* {@code this.capacity}
2008-08-10 07:09:55 +02:00
*/
public abstract ByteBuf setBytes(int index, ByteBuf src);
2008-08-10 07:09:55 +02:00
/**
* Transfers the specified source buffer's data to this buffer starting at
* the specified absolute {@code index}. This method is basically same
* with {@link #setBytes(int, ByteBuf, int, int)}, except that this
* method increases the {@code readerIndex} of the source buffer by
* the number of the transferred bytes while
* {@link #setBytes(int, ByteBuf, int, int)} does not.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer (i.e. {@code this}).
*
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code length} is greater than {@code src.readableBytes}
*/
public abstract ByteBuf setBytes(int index, ByteBuf src, int length);
2008-08-10 07:09:55 +02:00
/**
* Transfers the specified source buffer's data to this buffer starting at
* the specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex}
* of both the source (i.e. {@code this}) and the destination.
2008-08-10 07:09:55 +02:00
*
2008-08-10 16:25:13 +02:00
* @param srcIndex the first index of the source
* @param length the number of bytes to transfer
*
2008-08-10 07:09:55 +02:00
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if the specified {@code srcIndex} is less than {@code 0},
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code srcIndex + length} is greater than
* {@code src.capacity}
2008-08-10 07:09:55 +02:00
*/
public abstract ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length);
2008-08-10 07:09:55 +02:00
/**
* Transfers the specified source array's data to this buffer starting at
* the specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-10 07:09:55 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + src.length} is greater than
* {@code this.capacity}
2008-08-10 07:09:55 +02:00
*/
public abstract ByteBuf setBytes(int index, byte[] src);
2008-08-10 07:09:55 +02:00
/**
* Transfers the specified source array's data to this buffer starting at
* the specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-10 07:09:55 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if the specified {@code srcIndex} is less than {@code 0},
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code srcIndex + length} is greater than {@code src.length}
2008-08-10 07:09:55 +02:00
*/
public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length);
2008-08-10 07:09:55 +02:00
/**
* Transfers the specified source buffer's data to this buffer starting at
* the specified absolute {@code index} until the source buffer's position
* reaches its limit.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-10 07:09:55 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + src.remaining()} is greater than
* {@code this.capacity}
2008-08-10 07:09:55 +02:00
*/
public abstract ByteBuf setBytes(int index, ByteBuffer src);
2008-08-10 07:09:55 +02:00
/**
* Transfers the content of the specified source stream to this buffer
* starting at the specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-10 07:09:55 +02:00
*
2008-08-10 16:25:13 +02:00
* @param length the number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel.
* {@code -1} if the specified channel is closed.
*
2008-08-10 07:09:55 +02:00
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than {@code this.capacity}
2008-08-10 07:09:55 +02:00
* @throws IOException
* if the specified stream threw an exception during I/O
*/
public abstract int setBytes(int index, InputStream in, int length) throws IOException;
2008-08-10 07:09:55 +02:00
/**
* Transfers the content of the specified source channel to this buffer
* starting at the specified absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-10 07:09:55 +02:00
*
2008-08-10 16:25:13 +02:00
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel.
* {@code -1} if the specified channel is closed.
2008-08-10 07:09:55 +02:00
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than {@code this.capacity}
2008-08-10 07:09:55 +02:00
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int setBytes(int index, ScatteringByteChannel in, int length) throws IOException;
/**
* Transfers the content of the specified source channel starting at the given file position
* to this buffer starting at the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer. This method does not modify the channel's position.
*
* @param position the file position at which the transfer is to begin
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel.
* {@code -1} if the specified channel is closed.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than {@code this.capacity}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int setBytes(int index, FileChannel in, long position, int length) throws IOException;
2008-08-10 07:09:55 +02:00
/**
* Fills this buffer with <tt>NUL (0x00)</tt> starting at the specified
* absolute {@code index}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-10 07:09:55 +02:00
*
* @param length the number of <tt>NUL</tt>s to write to the buffer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
2008-08-10 16:25:13 +02:00
* if {@code index + length} is greater than {@code this.capacity}
2008-08-10 07:09:55 +02:00
*/
public abstract ByteBuf setZero(int index, int length);
2012-05-31 21:03:01 +02:00
/**
* Writes the specified {@link CharSequence} at the current {@code writerIndex} and increases
* the {@code writerIndex} by the written bytes.
*
* @param index on which the sequence should be written
* @param sequence to write
* @param charset that should be used.
* @return the written number of bytes.
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is not large enough to write the whole sequence
*/
public abstract int setCharSequence(int index, CharSequence sequence, Charset charset);
/**
* Gets a boolean at the current {@code readerIndex} and increases
* the {@code readerIndex} by {@code 1} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 1}
*/
public abstract boolean readBoolean();
2008-08-10 07:09:55 +02:00
/**
* Gets a byte at the current {@code readerIndex} and increases
* the {@code readerIndex} by {@code 1} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 1}
2008-08-10 07:09:55 +02:00
*/
public abstract byte readByte();
2008-08-10 07:09:55 +02:00
/**
* Gets an unsigned byte at the current {@code readerIndex} and increases
2008-08-10 07:09:55 +02:00
* the {@code readerIndex} by {@code 1} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 1}
2008-08-10 07:09:55 +02:00
*/
public abstract short readUnsignedByte();
2008-08-10 07:09:55 +02:00
/**
* Gets a 16-bit short integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 2} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 2}
2008-08-10 07:09:55 +02:00
*/
public abstract short readShort();
2008-08-10 07:09:55 +02:00
/**
* Gets a 16-bit short integer at the current {@code readerIndex}
* in the Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 2} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 2}
*/
public abstract short readShortLE();
2008-08-10 07:09:55 +02:00
/**
* Gets an unsigned 16-bit short integer at the current {@code readerIndex}
2008-08-10 07:09:55 +02:00
* and increases the {@code readerIndex} by {@code 2} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 2}
2008-08-10 07:09:55 +02:00
*/
public abstract int readUnsignedShort();
2008-08-10 07:09:55 +02:00
/**
* Gets an unsigned 16-bit short integer at the current {@code readerIndex}
* in the Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 2} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 2}
*/
public abstract int readUnsignedShortLE();
2008-08-10 07:09:55 +02:00
/**
* Gets a 24-bit medium integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 3} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 3}
2008-08-10 07:09:55 +02:00
*/
public abstract int readMedium();
2008-08-10 07:09:55 +02:00
/**
* Gets a 24-bit medium integer at the current {@code readerIndex}
* in the Little Endian Byte Order and increases the
* {@code readerIndex} by {@code 3} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 3}
*/
public abstract int readMediumLE();
2008-08-10 07:09:55 +02:00
/**
* Gets an unsigned 24-bit medium integer at the current {@code readerIndex}
2008-08-10 07:09:55 +02:00
* and increases the {@code readerIndex} by {@code 3} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 3}
2008-08-10 07:09:55 +02:00
*/
public abstract int readUnsignedMedium();
2008-08-10 07:09:55 +02:00
/**
* Gets an unsigned 24-bit medium integer at the current {@code readerIndex}
* in the Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 3} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 3}
*/
public abstract int readUnsignedMediumLE();
2008-08-10 07:09:55 +02:00
/**
* Gets a 32-bit integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
2008-08-10 07:09:55 +02:00
*/
public abstract int readInt();
2008-08-10 07:09:55 +02:00
/**
* Gets a 32-bit integer at the current {@code readerIndex}
* in the Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
*/
public abstract int readIntLE();
2008-08-10 07:09:55 +02:00
/**
* Gets an unsigned 32-bit integer at the current {@code readerIndex}
2008-08-10 07:09:55 +02:00
* and increases the {@code readerIndex} by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
2008-08-10 07:09:55 +02:00
*/
public abstract long readUnsignedInt();
2008-08-10 07:09:55 +02:00
/**
* Gets an unsigned 32-bit integer at the current {@code readerIndex}
* in the Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
*/
public abstract long readUnsignedIntLE();
2008-08-10 07:09:55 +02:00
/**
* Gets a 64-bit integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 8} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 8}
2008-08-10 07:09:55 +02:00
*/
public abstract long readLong();
/**
* Gets a 64-bit integer at the current {@code readerIndex}
* in the Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 8} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 8}
*/
public abstract long readLongLE();
/**
* Gets a 2-byte UTF-16 character at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 2} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 2}
*/
public abstract char readChar();
/**
* Gets a 32-bit floating point number at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
*/
public abstract float readFloat();
/**
* Gets a 32-bit floating point number at the current {@code readerIndex}
* in Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
*/
public float readFloatLE() {
return Float.intBitsToFloat(readIntLE());
}
/**
* Gets a 64-bit floating point number at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 8} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 8}
*/
public abstract double readDouble();
/**
* Gets a 64-bit floating point number at the current {@code readerIndex}
* in Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 8} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 8}
*/
public double readDoubleLE() {
return Double.longBitsToDouble(readLongLE());
}
2008-08-11 06:08:41 +02:00
/**
* Transfers this buffer's data to a newly created buffer starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code length}).
* The returned buffer's {@code readerIndex} and {@code writerIndex} are
* {@code 0} and {@code length} respectively.
*
* @param length the number of bytes to transfer
*
* @return the newly created buffer which contains the transferred bytes
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
public abstract ByteBuf readBytes(int length);
2008-08-11 06:08:41 +02:00
/**
* Returns a new slice of this buffer's sub-region starting at the current
* {@code readerIndex} and increases the {@code readerIndex} by the size
* of the new slice (= {@code length}).
* <p>
* Also be aware that this method will NOT call {@link #retain()} and so the
* reference count will NOT be increased.
2008-08-11 06:08:41 +02:00
*
* @param length the size of the new slice
*
* @return the newly created slice
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
public abstract ByteBuf readSlice(int length);
2008-08-11 06:08:41 +02:00
/**
* Returns a new retained slice of this buffer's sub-region starting at the current
* {@code readerIndex} and increases the {@code readerIndex} by the size
* of the new slice (= {@code length}).
* <p>
* Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #readSlice(int)}.
* This method behaves similarly to {@code readSlice(...).retain()} except that this method may return
* a buffer implementation that produces less garbage.
*
* @param length the size of the new slice
*
* @return the newly created slice
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
public abstract ByteBuf readRetainedSlice(int length);
2008-08-10 16:25:13 +02:00
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} until the destination becomes
* non-writable, and increases the {@code readerIndex} by the number of the
2008-08-10 16:25:13 +02:00
* transferred bytes. This method is basically same with
* {@link #readBytes(ByteBuf, int, int)}, except that this method
2008-08-10 16:25:13 +02:00
* increases the {@code writerIndex} of the destination by the number of
* the transferred bytes while {@link #readBytes(ByteBuf, int, int)}
2008-11-14 08:45:53 +01:00
* does not.
2008-08-10 16:25:13 +02:00
*
* @throws IndexOutOfBoundsException
* if {@code dst.writableBytes} is greater than
* {@code this.readableBytes}
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf readBytes(ByteBuf dst);
2008-08-10 16:25:13 +02:00
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code length}). This method
* is basically same with {@link #readBytes(ByteBuf, int, int)},
2008-08-10 16:25:13 +02:00
* except that this method increases the {@code writerIndex} of the
* destination by the number of the transferred bytes (= {@code length})
* while {@link #readBytes(ByteBuf, int, int)} does not.
2008-08-10 16:25:13 +02:00
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes} or
* if {@code length} is greater than {@code dst.writableBytes}
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf readBytes(ByteBuf dst, int length);
2008-08-10 16:25:13 +02:00
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code length}).
*
* @param dstIndex the first index of the destination
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code dstIndex} is less than {@code 0},
* if {@code length} is greater than {@code this.readableBytes}, or
2008-08-10 16:25:13 +02:00
* if {@code dstIndex + length} is greater than
* {@code dst.capacity}
*/
public abstract ByteBuf readBytes(ByteBuf dst, int dstIndex, int length);
2008-08-10 16:25:13 +02:00
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code dst.length}).
*
* @throws IndexOutOfBoundsException
* if {@code dst.length} is greater than {@code this.readableBytes}
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf readBytes(byte[] dst);
2008-08-10 16:25:13 +02:00
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code length}).
*
* @param dstIndex the first index of the destination
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code dstIndex} is less than {@code 0},
* if {@code length} is greater than {@code this.readableBytes}, or
2008-08-10 16:25:13 +02:00
* if {@code dstIndex + length} is greater than {@code dst.length}
*/
public abstract ByteBuf readBytes(byte[] dst, int dstIndex, int length);
2008-08-10 16:25:13 +02:00
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} until the destination's position
* reaches its limit, and increases the {@code readerIndex} by the
2008-08-10 16:25:13 +02:00
* number of the transferred bytes.
*
* @throws IndexOutOfBoundsException
* if {@code dst.remaining()} is greater than
* {@code this.readableBytes}
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf readBytes(ByteBuffer dst);
2008-08-10 16:25:13 +02:00
/**
* Transfers this buffer's data to the specified stream starting at the
* current {@code readerIndex}.
*
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
2008-08-10 16:25:13 +02:00
* @throws IOException
* if the specified stream threw an exception during I/O
*/
public abstract ByteBuf readBytes(OutputStream out, int length) throws IOException;
2008-08-10 16:25:13 +02:00
/**
* Transfers this buffer's data to the specified stream starting at the
* current {@code readerIndex}.
*
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes written out to the specified channel
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
2008-08-10 16:25:13 +02:00
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int readBytes(GatheringByteChannel out, int length) throws IOException;
/**
* Gets a {@link CharSequence} with the given length at the current {@code readerIndex}
* and increases the {@code readerIndex} by the given length.
*
* @param length the length to read
* @param charset that should be used
* @return the sequence
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
public abstract CharSequence readCharSequence(int length, Charset charset);
/**
* Transfers this buffer's data starting at the current {@code readerIndex}
* to the specified channel starting at the given file position.
* This method does not modify the channel's position.
*
* @param position the file position at which the transfer is to begin
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes written out to the specified channel
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int readBytes(FileChannel out, long position, int length) throws IOException;
2008-08-10 16:25:13 +02:00
/**
* Increases the current {@code readerIndex} by the specified
* {@code length} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf skipBytes(int length);
2008-08-10 16:25:13 +02:00
/**
* Sets the specified boolean at the current {@code writerIndex}
* and increases the {@code writerIndex} by {@code 1} in this buffer.
* If {@code this.writableBytes} is less than {@code 1}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public abstract ByteBuf writeBoolean(boolean value);
2012-05-31 21:03:01 +02:00
2008-08-10 16:25:13 +02:00
/**
* Sets the specified byte at the current {@code writerIndex}
* and increases the {@code writerIndex} by {@code 1} in this buffer.
* The 24 high-order bits of the specified value are ignored.
* If {@code this.writableBytes} is less than {@code 1}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeByte(int value);
2008-08-10 16:25:13 +02:00
/**
* Sets the specified 16-bit short integer at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 2}
* in this buffer. The 16 high-order bits of the specified value are ignored.
* If {@code this.writableBytes} is less than {@code 2}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeShort(int value);
2008-08-10 16:25:13 +02:00
/**
* Sets the specified 16-bit short integer in the Little Endian Byte
* Order at the current {@code writerIndex} and increases the
* {@code writerIndex} by {@code 2} in this buffer.
* The 16 high-order bits of the specified value are ignored.
* If {@code this.writableBytes} is less than {@code 2}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public abstract ByteBuf writeShortLE(int value);
2008-08-10 16:25:13 +02:00
/**
* Sets the specified 24-bit medium integer at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 3}
* in this buffer.
* If {@code this.writableBytes} is less than {@code 3}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeMedium(int value);
2008-08-10 16:25:13 +02:00
/**
* Sets the specified 24-bit medium integer at the current
* {@code writerIndex} in the Little Endian Byte Order and
* increases the {@code writerIndex} by {@code 3} in this
* buffer.
* If {@code this.writableBytes} is less than {@code 3}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public abstract ByteBuf writeMediumLE(int value);
2008-08-10 16:25:13 +02:00
/**
* Sets the specified 32-bit integer at the current {@code writerIndex}
* and increases the {@code writerIndex} by {@code 4} in this buffer.
* If {@code this.writableBytes} is less than {@code 4}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeInt(int value);
2008-08-10 16:25:13 +02:00
/**
* Sets the specified 32-bit integer at the current {@code writerIndex}
* in the Little Endian Byte Order and increases the {@code writerIndex}
* by {@code 4} in this buffer.
* If {@code this.writableBytes} is less than {@code 4}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public abstract ByteBuf writeIntLE(int value);
2008-08-10 16:25:13 +02:00
/**
* Sets the specified 64-bit long integer at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 8}
* in this buffer.
* If {@code this.writableBytes} is less than {@code 8}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeLong(long value);
/**
* Sets the specified 64-bit long integer at the current
* {@code writerIndex} in the Little Endian Byte Order and
* increases the {@code writerIndex} by {@code 8}
* in this buffer.
* If {@code this.writableBytes} is less than {@code 8}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public abstract ByteBuf writeLongLE(long value);
/**
* Sets the specified 2-byte UTF-16 character at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 2}
* in this buffer. The 16 high-order bits of the specified value are ignored.
* If {@code this.writableBytes} is less than {@code 2}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public abstract ByteBuf writeChar(int value);
/**
* Sets the specified 32-bit floating point number at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 4}
* in this buffer.
* If {@code this.writableBytes} is less than {@code 4}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public abstract ByteBuf writeFloat(float value);
/**
* Sets the specified 32-bit floating point number at the current
* {@code writerIndex} in Little Endian Byte Order and increases
* the {@code writerIndex} by {@code 4} in this buffer.
* If {@code this.writableBytes} is less than {@code 4}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public ByteBuf writeFloatLE(float value) {
return writeIntLE(Float.floatToRawIntBits(value));
}
/**
* Sets the specified 64-bit floating point number at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 8}
* in this buffer.
* If {@code this.writableBytes} is less than {@code 8}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public abstract ByteBuf writeDouble(double value);
/**
* Sets the specified 64-bit floating point number at the current
* {@code writerIndex} in Little Endian Byte Order and increases
* the {@code writerIndex} by {@code 8} in this buffer.
* If {@code this.writableBytes} is less than {@code 8}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*/
public ByteBuf writeDoubleLE(double value) {
return writeLongLE(Double.doubleToRawLongBits(value));
}
2008-08-10 16:25:13 +02:00
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} until the source buffer becomes
* unreadable, and increases the {@code writerIndex} by the number of
* the transferred bytes. This method is basically same with
* {@link #writeBytes(ByteBuf, int, int)}, except that this method
2008-08-10 16:25:13 +02:00
* increases the {@code readerIndex} of the source buffer by the number of
* the transferred bytes while {@link #writeBytes(ByteBuf, int, int)}
2008-11-14 08:45:53 +01:00
* does not.
* If {@code this.writableBytes} is less than {@code src.readableBytes},
* {@link #ensureWritable(int)} will be called in an attempt to expand
* capacity to accommodate.
*/
public abstract ByteBuf writeBytes(ByteBuf src);
2008-08-10 16:25:13 +02:00
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} and increases the {@code writerIndex}
* by the number of the transferred bytes (= {@code length}). This method
* is basically same with {@link #writeBytes(ByteBuf, int, int)},
2008-08-10 16:25:13 +02:00
* except that this method increases the {@code readerIndex} of the source
* buffer by the number of the transferred bytes (= {@code length}) while
* {@link #writeBytes(ByteBuf, int, int)} does not.
* If {@code this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*
* @param length the number of bytes to transfer
* @throws IndexOutOfBoundsException if {@code length} is greater then {@code src.readableBytes}
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeBytes(ByteBuf src, int length);
2008-08-10 16:25:13 +02:00
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} and increases the {@code writerIndex}
* by the number of the transferred bytes (= {@code length}).
* If {@code this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*
* @param srcIndex the first index of the source
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code srcIndex} is less than {@code 0}, or
* if {@code srcIndex + length} is greater than {@code src.capacity}
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeBytes(ByteBuf src, int srcIndex, int length);
2008-08-10 16:25:13 +02:00
/**
* Transfers the specified source array's data to this buffer starting at
* the current {@code writerIndex} and increases the {@code writerIndex}
* by the number of the transferred bytes (= {@code src.length}).
* If {@code this.writableBytes} is less than {@code src.length}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeBytes(byte[] src);
2008-08-10 16:25:13 +02:00
/**
* Transfers the specified source array's data to this buffer starting at
* the current {@code writerIndex} and increases the {@code writerIndex}
* by the number of the transferred bytes (= {@code length}).
* If {@code this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*
* @param srcIndex the first index of the source
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code srcIndex} is less than {@code 0}, or
* if {@code srcIndex + length} is greater than {@code src.length}
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeBytes(byte[] src, int srcIndex, int length);
2008-08-10 16:25:13 +02:00
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} until the source buffer's position
* reaches its limit, and increases the {@code writerIndex} by the
2008-08-10 16:25:13 +02:00
* number of the transferred bytes.
* If {@code this.writableBytes} is less than {@code src.remaining()},
* {@link #ensureWritable(int)} will be called in an attempt to expand
* capacity to accommodate.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf writeBytes(ByteBuffer src);
2008-08-10 16:25:13 +02:00
/**
* Transfers the content of the specified stream to this buffer
* starting at the current {@code writerIndex} and increases the
* {@code writerIndex} by the number of the transferred bytes.
* If {@code this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*
* @param length the number of bytes to transfer
*
* @return the actual number of bytes read in from the specified stream
*
* @throws IOException if the specified stream threw an exception during I/O
2008-08-10 16:25:13 +02:00
*/
public abstract int writeBytes(InputStream in, int length) throws IOException;
2008-08-10 16:25:13 +02:00
/**
* Transfers the content of the specified channel to this buffer
* starting at the current {@code writerIndex} and increases the
* {@code writerIndex} by the number of the transferred bytes.
* If {@code this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel
*
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int writeBytes(ScatteringByteChannel in, int length) throws IOException;
/**
* Transfers the content of the specified channel starting at the given file position
* to this buffer starting at the current {@code writerIndex} and increases the
* {@code writerIndex} by the number of the transferred bytes.
* This method does not modify the channel's position.
* If {@code this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
*
* @param position the file position at which the transfer is to begin
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel
*
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int writeBytes(FileChannel in, long position, int length) throws IOException;
2008-08-10 16:25:13 +02:00
/**
* Fills this buffer with <tt>NUL (0x00)</tt> starting at the current
* {@code writerIndex} and increases the {@code writerIndex} by the
* specified {@code length}.
* If {@code this.writableBytes} is less than {@code length}, {@link #ensureWritable(int)}
* will be called in an attempt to expand capacity to accommodate.
2008-08-10 16:25:13 +02:00
*
* @param length the number of <tt>NUL</tt>s to write to the buffer
*/
public abstract ByteBuf writeZero(int length);
/**
* Writes the specified {@link CharSequence} at the current {@code writerIndex} and increases
* the {@code writerIndex} by the written bytes.
* in this buffer.
* If {@code this.writableBytes} is not large enough to write the whole sequence,
* {@link #ensureWritable(int)} will be called in an attempt to expand capacity to accommodate.
*
* @param sequence to write
* @param charset that should be used
* @return the written number of bytes
*/
public abstract int writeCharSequence(CharSequence sequence, Charset charset);
2008-08-11 06:08:41 +02:00
/**
* Locates the first occurrence of the specified {@code value} in this
* buffer. The search takes place from the specified {@code fromIndex}
* (inclusive) to the specified {@code toIndex} (exclusive).
2008-08-11 06:08:41 +02:00
* <p>
* If {@code fromIndex} is greater than {@code toIndex}, the search is
* performed in a reversed order from {@code fromIndex} (exclusive)
* down to {@code toIndex} (inclusive).
* <p>
* Note that the lower index is always included and higher always excluded.
2009-04-24 15:56:35 +02:00
* <p>
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-11 06:08:41 +02:00
*
* @return the absolute index of the first occurrence if found.
* {@code -1} otherwise.
*/
public abstract int indexOf(int fromIndex, int toIndex, byte value);
2008-08-11 06:08:41 +02:00
/**
* Locates the first occurrence of the specified {@code value} in this
* buffer. The search takes place from the current {@code readerIndex}
* (inclusive) to the current {@code writerIndex} (exclusive).
* <p>
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the current {@code readerIndex}
* and the first occurrence if found. {@code -1} otherwise.
*/
public abstract int bytesBefore(byte value);
/**
* Locates the first occurrence of the specified {@code value} in this
* buffer. The search starts from the current {@code readerIndex}
* (inclusive) and lasts for the specified {@code length}.
* <p>
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the current {@code readerIndex}
* and the first occurrence if found. {@code -1} otherwise.
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
public abstract int bytesBefore(int length, byte value);
/**
* Locates the first occurrence of the specified {@code value} in this
* buffer. The search starts from the specified {@code index} (inclusive)
* and lasts for the specified {@code length}.
* <p>
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the specified {@code index}
* and the first occurrence if found. {@code -1} otherwise.
*
* @throws IndexOutOfBoundsException
* if {@code index + length} is greater than {@code this.capacity}
*/
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.
*
* @return {@code -1} if the processor iterated to or beyond the end of the readable bytes.
* The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
*/
public abstract int forEachByte(ByteProcessor processor);
/**
* Iterates over the specified area of this buffer with the specified {@code processor} in ascending order.
* (i.e. {@code index}, {@code (index + 1)}, .. {@code (index + length - 1)})
*
* @return {@code -1} if the processor iterated to or beyond the end of the specified area.
* The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
*/
public abstract int forEachByte(int index, int length, ByteProcessor processor);
/**
* Iterates over the readable bytes of this buffer with the specified {@code processor} in descending order.
*
* @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes.
* The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
*/
public abstract int forEachByteDesc(ByteProcessor processor);
/**
* Iterates over the specified area of this buffer with the specified {@code processor} in descending order.
* (i.e. {@code (index + length - 1)}, {@code (index + length - 2)}, ... {@code index})
*
*
* @return {@code -1} if the processor iterated to or beyond the beginning of the specified area.
* The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}.
*/
public abstract int forEachByteDesc(int index, int length, ByteProcessor processor);
2008-08-10 16:25:13 +02:00
/**
* Returns a copy of this buffer's readable bytes. Modifying the content
2008-11-14 08:45:53 +01:00
* of the returned buffer or this buffer does not affect each other at all.
2008-08-10 16:25:13 +02:00
* This method is identical to {@code buf.copy(buf.readerIndex(), buf.readableBytes())}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
public abstract ByteBuf copy();
2008-08-10 16:25:13 +02:00
/**
* Returns a copy of this buffer's sub-region. Modifying the content of
2008-11-14 08:45:53 +01:00
* the returned buffer or this buffer does not affect each other at all.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf copy(int index, int length);
2008-08-10 16:25:13 +02:00
/**
* Returns a slice of this buffer's readable bytes. Modifying the content
* of the returned buffer or this buffer affects each other's content
* while they maintain separate indexes. This method is
2008-08-10 16:25:13 +02:00
* identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
* <p>
* Also be aware that this method will NOT call {@link #retain()} and so the
* reference count will NOT be increased.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf slice();
2008-08-10 16:25:13 +02:00
/**
* Returns a retained slice of this buffer's readable bytes. Modifying the content
* of the returned buffer or this buffer affects each other's content
* while they maintain separate indexes. This method is
* identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
* <p>
* Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice()}.
* This method behaves similarly to {@code slice().retain()} except that this method may return
* a buffer implementation that produces less garbage.
*/
public abstract ByteBuf retainedSlice();
2008-08-10 16:25:13 +02:00
/**
* Returns a slice of this buffer's sub-region. Modifying the content of
* the returned buffer or this buffer affects each other's content while
* they maintain separate indexes.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
* <p>
* Also be aware that this method will NOT call {@link #retain()} and so the
* reference count will NOT be increased.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf slice(int index, int length);
2008-08-10 16:25:13 +02:00
/**
* Returns a retained slice of this buffer's sub-region. Modifying the content of
* the returned buffer or this buffer affects each other's content while
* they maintain separate indexes.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
* <p>
* Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}.
* This method behaves similarly to {@code slice(...).retain()} except that this method may return
* a buffer implementation that produces less garbage.
*/
public abstract ByteBuf retainedSlice(int index, int length);
2008-08-10 16:25:13 +02:00
/**
* Returns a buffer which shares the whole region of this buffer.
* Modifying the content of the returned buffer or this buffer affects
* each other's content while they maintain separate indexes.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
* <p>
* Be aware that this method will
* NOT call {@link #retain()} and so the reference count will NOT be increased.
* @return A buffer whose readable content is equivalent to the buffer returned by {@link #slice()}.
* However this buffer will share the capacity of the underlying buffer, and therefore allows access to all of the
* underlying content if necessary.
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuf duplicate();
/**
* Returns a retained buffer which shares the whole region of this buffer.
* Modifying the content of the returned buffer or this buffer affects
* each other's content while they maintain separate indexes.
* This method is identical to {@code buf.slice(0, buf.capacity())}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
* <p>
* Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}.
* This method behaves similarly to {@code duplicate().retain()} except that this method may return
* a buffer implementation that produces less garbage.
*/
public abstract ByteBuf retainedDuplicate();
2008-08-10 16:25:13 +02:00
/**
* Returns the maximum number of NIO {@link ByteBuffer}s that consist this buffer. Note that {@link #nioBuffers()}
* or {@link #nioBuffers(int, int)} might return a less number of {@link ByteBuffer}s.
*
* @return {@code -1} if this buffer has no underlying {@link ByteBuffer}.
2013-07-22 13:51:09 +02:00
* the number of the underlying {@link ByteBuffer}s if this buffer has at least one underlying
* {@link ByteBuffer}. Note that this method does not return {@code 0} to avoid confusion.
*
* @see #nioBuffer()
* @see #nioBuffer(int, int)
* @see #nioBuffers()
* @see #nioBuffers(int, int)
2008-08-10 16:25:13 +02:00
*/
public abstract int nioBufferCount();
2008-08-10 16:25:13 +02:00
/**
* Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}. The returned buffer
* either share or contains the copied content of this buffer, while changing the position
* and limit of the returned NIO buffer does not affect the indexes of this buffer.
* This method is identical to {@code buf.nioBuffer(buf.readerIndex(), buf.readableBytes())}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
* Please note that the returned NIO buffer will not see the changes of this buffer if this buffer
* is a dynamic buffer and it adjusted its capacity.
*
* @throws UnsupportedOperationException
* if this buffer cannot create a {@link ByteBuffer} that shares the content with itself
*
* @see #nioBufferCount()
* @see #nioBuffers()
* @see #nioBuffers(int, int)
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuffer nioBuffer();
2008-08-10 16:25:13 +02:00
/**
* Exposes this buffer's sub-region as an NIO {@link ByteBuffer}. The returned buffer
* either share or contains the copied content of this buffer, while changing the position
* and limit of the returned NIO buffer does not affect the indexes of this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
* Please note that the returned NIO buffer will not see the changes of this buffer if this buffer
* is a dynamic buffer and it adjusted its capacity.
*
* @throws UnsupportedOperationException
* if this buffer cannot create a {@link ByteBuffer} that shares the content with itself
*
* @see #nioBufferCount()
* @see #nioBuffers()
* @see #nioBuffers(int, int)
2008-08-10 16:25:13 +02:00
*/
public abstract ByteBuffer nioBuffer(int index, int length);
/**
* Internal use only: Exposes the internal NIO buffer.
*/
public abstract ByteBuffer internalNioBuffer(int index, int length);
/**
* Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}'s. The returned buffer
* either share or contains the copied content of this buffer, while changing the position
* and limit of the returned NIO buffer does not affect the indexes of this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer.
* Please note that the returned NIO buffer will not see the changes of this buffer if this buffer
* is a dynamic buffer and it adjusted its capacity.
*
*
* @throws UnsupportedOperationException
* if this buffer cannot create a {@link ByteBuffer} that shares the content with itself
*
* @see #nioBufferCount()
* @see #nioBuffer()
* @see #nioBuffer(int, int)
*/
public abstract ByteBuffer[] nioBuffers();
/**
* Exposes this buffer's bytes as an NIO {@link ByteBuffer}'s for the specified index and length
* The returned buffer either share or contains the copied content of this buffer, while changing
* the position and limit of the returned NIO buffer does not affect the indexes of this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of this buffer. Please note that the
* returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic
* buffer and it adjusted its capacity.
*
* @throws UnsupportedOperationException
* if this buffer cannot create a {@link ByteBuffer} that shares the content with itself
*
* @see #nioBufferCount()
* @see #nioBuffer()
* @see #nioBuffer(int, int)
*/
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()}.
*/
public abstract boolean hasArray();
/**
* Returns the backing byte array of this buffer.
*
* @throws UnsupportedOperationException
* if there no accessible backing byte array
*/
public abstract byte[] array();
/**
* Returns the offset of the first byte within the backing byte array of
* this buffer.
*
* @throws UnsupportedOperationException
* if there no accessible backing byte array
*/
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.
*/
public abstract boolean hasMemoryAddress();
/**
* Returns the low-level memory address that point to the first byte of ths backing data.
*
* @throws UnsupportedOperationException
* if this buffer does not support accessing the low-level memory address
*/
public abstract long memoryAddress();
/**
* Returns {@code true} if this {@link ByteBuf} implementation is backed by a single memory region.
* Composite buffer implementations must return false even if they currently hold &le; 1 components.
* For buffers that return {@code true}, it's guaranteed that a successful call to {@link #discardReadBytes()}
* will increase the value of {@link #maxFastWritableBytes()} by the current {@code readerIndex}.
* <p>
* This method will return {@code false} by default, and a {@code false} return value does not necessarily
* mean that the implementation is composite or that it is <i>not</i> backed by a single memory region.
*/
public boolean isContiguous() {
return false;
}
/**
* A {@code ByteBuf} can turn into itself.
* @return This {@code ByteBuf} instance.
*/
@Override
public final ByteBuf asByteBuf() {
return this;
}
2008-08-10 16:25:13 +02:00
/**
* Decodes this buffer's readable bytes into a string with the specified
* character set name. This method is identical to
* {@code buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName)}.
2009-04-24 15:56:35 +02:00
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
2008-08-10 16:25:13 +02:00
*
* @throws UnsupportedCharsetException
* if the specified character set name is not supported by the
* current VM
*/
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.
*/
public abstract String toString(int index, int length, Charset charset);
/**
* Returns a hash code which was calculated from the content of this
* buffer. If there's a byte array which is
* {@linkplain #equals(Object) equal to} this array, both arrays should
* return the same value.
*/
@Override
public abstract int hashCode();
/**
* Determines if the content of the specified buffer is identical to the
* content of this array. 'Identical' here means:
* <ul>
* <li>the size of the contents of the two buffers are same and</li>
* <li>every single byte of the content of the two buffers are same.</li>
* </ul>
2008-11-14 08:45:53 +01:00
* Please note that it does not compare {@link #readerIndex()} nor
* {@link #writerIndex()}. This method also returns {@code false} for
* {@code null} and an object which is not an instance of
* {@link ByteBuf} type.
*/
@Override
public abstract boolean equals(Object obj);
/**
* Compares the content of the specified buffer to the content of this
* buffer. Comparison is performed in the same manner with the string
* comparison functions of various languages such as {@code strcmp},
* {@code memcmp} and {@link String#compareTo(String)}.
*/
@Override
public abstract int compareTo(ByteBuf buffer);
/**
2008-11-14 08:45:53 +01:00
* Returns the string representation of this buffer. This method does not
* necessarily return the whole content of the buffer but returns
* the values of the key properties such as {@link #readerIndex()},
2008-08-10 17:43:04 +02:00
* {@link #writerIndex()} and {@link #capacity()}.
*/
@Override
public abstract String toString();
@Override
public abstract ByteBuf retain(int increment);
@Override
public abstract ByteBuf retain();
@Override
public abstract ByteBuf touch();
@Override
public abstract ByteBuf touch(Object hint);
Further reduce ensureAccessible() overhead (#8895) Motivation: This PR fixes some non-negligible overhead discovered in the ByteBuf accessibility (non-zero refcount) checking. The cause turned out to be mostly twofold: - Unnecessary operations used to calculate the refcount from the "raw" encoded int field value - Call stack depths exceeding the default limit for inlining, in some places (CompositeByteBuf in particular) It's a follow-on from #8882 which uses the maxCapacity field for a simpler non-negative check. The performance gap between these two variants appears to be _mostly_ closed, but there's one exception which may warrant further analysis. Modifications: - Replace ABB.internalRefCount() with ByteBuf.isAccessible(), the default still checks for non-zero refCnt() - Just test for parity of raw refCnt instead of converting to "real", with fast-path for specific small values - Make sure isAccessible() is delegated by derived/wrapper ByteBufs - Use existing freed flag in CompositeByteBuf for faster isAccessible() - Manually inline some calls in methods like CompositeByteBuf.setLong() and AbstractReferenceCountedByteBuf.isAccessible() to reduce stack depths (to ensure default inlining limit isn't hit) - Add ByteBufAccessBenchmark which is an extension of UnsafeByteBufBenchmark (maybe latter could now be removed) Results: Before: Benchmark (bufferType) (checkAccessible) (checkBounds) Mode Cnt Score Error Units readBatch UNSAFE true true thrpt 30 84524972.863 ± 518338.811 ops/s readBatch UNSAFE_SLICE true true thrpt 30 38608795.037 ± 298176.974 ops/s readBatch HEAP true true thrpt 30 80003697.649 ± 974674.119 ops/s readBatch COMPOSITE true true thrpt 30 18495554.788 ± 108075.023 ops/s setGetLong UNSAFE true true thrpt 30 247069881.578 ± 10839162.593 ops/s setGetLong UNSAFE_SLICE true true thrpt 30 196355905.206 ± 1802420.990 ops/s setGetLong HEAP true true thrpt 30 245686644.713 ± 11769311.527 ops/s setGetLong COMPOSITE true true thrpt 30 83170940.687 ± 657524.123 ops/s setLong UNSAFE true true thrpt 30 278940253.918 ± 1807265.259 ops/s setLong UNSAFE_SLICE true true thrpt 30 202556738.764 ± 11887973.563 ops/s setLong HEAP true true thrpt 30 280045958.053 ± 2719583.400 ops/s setLong COMPOSITE true true thrpt 30 121299806.002 ± 2155084.707 ops/s After: Benchmark (bufferType) (checkAccessible) (checkBounds) Mode Cnt Score Error Units readBatch UNSAFE true true thrpt 30 101641801.035 ± 3950050.059 ops/s readBatch UNSAFE_SLICE true true thrpt 30 84395902.846 ± 4339579.057 ops/s readBatch HEAP true true thrpt 30 100179060.207 ± 3222487.287 ops/s readBatch COMPOSITE true true thrpt 30 42288494.472 ± 294919.633 ops/s setGetLong UNSAFE true true thrpt 30 304530755.027 ± 6574163.899 ops/s setGetLong UNSAFE_SLICE true true thrpt 30 212028547.645 ± 14277828.768 ops/s setGetLong HEAP true true thrpt 30 309335422.609 ± 2272150.415 ops/s setGetLong COMPOSITE true true thrpt 30 160383609.236 ± 966484.033 ops/s setLong UNSAFE true true thrpt 30 298055969.747 ± 7437449.627 ops/s setLong UNSAFE_SLICE true true thrpt 30 223784178.650 ± 9869750.095 ops/s setLong HEAP true true thrpt 30 302543263.328 ± 8140104.706 ops/s setLong COMPOSITE true true thrpt 30 157083673.285 ± 3528779.522 ops/s There's also a similar knock-on improvement to other benchmarks (e.g. HPACK encoding/decoding) as shown in #8882. For sanity I did a final comparison of the "fast path" tweak using one of the HPACK benchmarks: (rawCnt & 1) == 0: Benchmark (limitToAscii) (sensitive) (size) Mode Cnt Score Error Units HpackDecoderBenchmark.decode true true MEDIUM thrpt 30 50914.479 ± 940.114 ops/s rawCnt == 2 || rawCnt == 4 || rawCnt == 6 || rawCnt == 8 || (rawCnt & 1) == 0: Benchmark (limitToAscii) (sensitive) (size) Mode Cnt Score Error Units HpackDecoderBenchmark.decode true true MEDIUM thrpt 30 60036.425 ± 1478.196 ops/s
2019-02-28 20:40:42 +01:00
/**
* Used internally by {@link AbstractByteBuf#ensureAccessible()} to try to guard
* against using the buffer after it was released (best-effort).
*/
boolean isAccessible() {
return refCnt() != 0;
}
}