-
- All Superinterfaces:
AutoCloseable
,BufferAccessor
,Resource<Buffer>
- All Known Subinterfaces:
CompositeBuffer
- All Known Implementing Classes:
AdaptableBuffer
,BufferStub
public interface Buffer extends Resource<Buffer>, BufferAccessor
A life cycled buffer of memory, with separate reader and writer offsets.A buffer is a logically sequential stretch of memory with a certain capacity, an offset for writing, and an offset for reading. Buffers may be composed of multiple components, where each component is a guaranteed contiguous chunk of memory.
Creating a buffer
Buffers are created by allocators, and theirallocate
family of methods. A number of standard allocators exist, and are available through static methods on theBufferAllocator
interface.Buffer life cycle
The buffer has a life cycle, where it is allocated, used, and deallocated. When the buffer is initially allocated, a pairingResource.close()
call will deallocate it. If a buffer is sent elsewhere, the close method on the given instance will become a no-op. The buffer can be thought of as a view onto memory, and callingResource.send()
on the buffer will effectively close that view, and recreate it upon reception at its destination.Thread-safety
Buffers are not thread-safe.Accessing data
Data access methods fall into two classes:- Access that are based on, and updates, the read or write offset positions.
- These accessor methods are typically called
readX
orwriteX
. - Access that take offsets as arguments, and do not update read or write offset positions.
- These accessor methods are typically called
getX
orsetX
.
0
, and the last byte in the buffer is at offsetcapacity - 1
. ThereaderOffset()
is the offset into the buffer from which the next read will take place, and is initially zero. The reader offset must always be less than or equal to thewriterOffset()
. ThewriterOffset()
is likewise the offset into the buffer where the next write will take place. The writer offset is also initially zero, and must be less than or equal to the capacity.This carves the buffer into three regions, as demonstrated by this diagram:
+-------------------+------------------+------------------+ | discardable bytes | readable bytes | writable bytes | | | (CONTENT) | | +-------------------+------------------+------------------+ | | | | 0 <= readerOffset <= writerOffset <= capacity
Byte Order
Buffers are always big endian, and this cannot be changed. Usages that need to get, set, read, or write, little-endian values will have to flip the byte order of the values they read and write.Splitting buffers
Thesplit()
method breaks a buffer into two. The two buffers will share the underlying memory, but their regions will not overlap, ensuring that the memory is safely shared between the two.Splitting a buffer is useful for when you want to hand over a region of a buffer to some other, perhaps unknown, piece of code, and relinquish your ownership of that buffer region in the process. Examples include aggregating messages into an accumulator buffer, and sending messages down the pipeline for further processing, as split buffer regions, once their data has been received in its entirety. If you instead wish to temporarily share a region of a buffer, you will have to pass offset and length along with the buffer, or you will have to make a copy of the region.
Buffers as constants
Sometimes, the same bit of data will be processed or transmitted over and over again. In such cases, it can be tempting to allocate and fill a buffer once, and then reuse it. Such reuse must be done carefully, however, to avoid a number of bugs. TheBufferAllocator
has aBufferAllocator.constBufferSupplier(byte[])
method that solves this, and prevents these bugs from occurring.
-
-
Method Summary
All Methods Instance Methods Abstract Methods Default Methods Modifier and Type Method Description int
bytesBefore(byte needle)
Get the number of readable bytes, until the givenneedle
is found in this buffer.int
bytesBefore(Buffer needle)
Get the number of readable bytes, until the givenneedle
is found in this buffer.int
capacity()
The capacity of this buffer, that is, the maximum number of bytes it can contain.Buffer
compact()
Discards the read bytes, and moves the buffer contents to the beginning of the buffer.default Buffer
copy()
Returns a copy of this buffer's readable bytes.default Buffer
copy(boolean readOnly)
Returns a copy of this buffer's readable bytes, with the given read-only setting.default Buffer
copy(int offset, int length)
Returns a copy of the given region of this buffer.Buffer
copy(int offset, int length, boolean readOnly)
Returns a copy of the given region of this buffer.void
copyInto(int srcPos, byte[] dest, int destPos, int length)
Copies the given length of data from this buffer into the given destination array, beginning at the given source position in this buffer, and the given destination position in the destination array.void
copyInto(int srcPos, Buffer dest, int destPos, int length)
Copies the given length of data from this buffer into the given destination buffer, beginning at the given source position in this buffer, and the given destination position in the destination buffer.void
copyInto(int srcPos, ByteBuffer dest, int destPos, int length)
Copies the given length of data from this buffer into the given destination byte buffer, beginning at the given source position in this buffer, and the given destination position in the destination byte buffer.int
countComponents()
Get the number of "components" in this buffer.int
countReadableComponents()
Get the number of "components" in this buffer, that are readable.int
countWritableComponents()
Get the number of "components" in this buffer, that are writable.default Buffer
ensureWritable(int size)
Ensures that this buffer has at least the given number of bytes of available space for writing.Buffer
ensureWritable(int size, int minimumGrowth, boolean allowCompaction)
Ensures that this buffer has at least the given number of bytes of available space for writing.Buffer
fill(byte value)
Fills the buffer with the given byte value.<T extends ReadableComponent & ComponentIterator.Next>
ComponentIterator<T>forEachReadable()
Create a component iterator for all readable components in this buffer.<E extends Exception>
intforEachReadable(int initialIndex, ReadableComponentProcessor<E> processor)
Processes all readable components of this buffer, and return the number of components processed.<T extends WritableComponent & ComponentIterator.Next>
ComponentIterator<T>forEachWritable()
Create a component iterator for all writable components in this buffer.<E extends Exception>
intforEachWritable(int initialIndex, WritableComponentProcessor<E> processor)
Process all writable components of this buffer, and return the number of components processed.int
implicitCapacityLimit()
Returns the implicit capacity limit of the buffer.Buffer
implicitCapacityLimit(int limit)
Set an upper limit to the implicit capacity growth.boolean
isDirect()
Queries if this buffer is backed by native memory, or not.Buffer
makeReadOnly()
Makes this buffer read-only.ByteCursor
openCursor()
Opens a cursor to iterate the readable bytes of this buffer.ByteCursor
openCursor(int fromOffset, int length)
Opens a cursor to iterate the given number bytes of this buffer, starting at the given offset.default ByteCursor
openReverseCursor()
Opens a cursor to iterate the readable bytes of this buffer, in reverse.ByteCursor
openReverseCursor(int fromOffset, int length)
Opens a cursor to iterate the given number bytes of this buffer, in reverse, starting at the given offset.default int
readableBytes()
Returns the number of readable bytes which is equal to(writerOffset() - readerOffset())
.default Buffer
readBytes(byte[] destination, int destPos, int length)
Read from this buffer, into the destination array, the given number of bytes.default Buffer
readBytes(ByteBuffer destination)
Read from this buffer, into the destinationByteBuffer
This updates the read offset of this buffer and also the position of the destinationByteBuffer
.default CharSequence
readCharSequence(int length, Charset charset)
int
readerOffset()
Get the current reader offset.Buffer
readerOffset(int offset)
Set the reader offset.boolean
readOnly()
Queries if this buffer is read-only or not.default Buffer
readSplit(int length)
Splits the buffer into two, atlength
number of bytes from the current readerOffset() reader offset} position.default Buffer
resetOffsets()
Resets the read offset and the write offset on this buffer to zero, and return this buffer.default Buffer
skipReadableBytes(int delta)
Move the reader offset forward by the given delta.default Buffer
skipWritableBytes(int delta)
Move the writer offset to ahead by the given delta.default Buffer
split()
Splits the buffer into two, at the write offset position.Buffer
split(int splitOffset)
Splits the buffer into two, at the givensplitOffset
.default String
toString(Charset charset)
Decodes this buffer's readable bytes into a string with the specified Charset.int
transferFrom(FileChannel channel, long position, int length)
Read from the given channel starting from the given position and write to this buffer.int
transferFrom(ReadableByteChannel channel, int length)
Read from the given channel and write to this buffer.int
transferTo(WritableByteChannel channel, int length)
Read from this buffer and write to the given channel.default int
writableBytes()
Returns the number of writable bytes which is equal to(capacity() - writerOffset())
.default Buffer
writeBytes(byte[] source)
Writes into this buffer, all the bytes from the given byte array.default Buffer
writeBytes(byte[] source, int srcPos, int length)
Writes into this buffer, the given number of bytes from the byte array.default Buffer
writeBytes(Buffer source)
Writes into this buffer, all the readable bytes from the given buffer.default Buffer
writeBytes(ByteBuffer source)
Writes into this buffer from the sourceByteBuffer
.default Buffer
writeCharSequence(CharSequence source, Charset charset)
Writes into this buffer, all the bytes from the givensource
using the passedcharset
.int
writerOffset()
Get the current writer offset.Buffer
writerOffset(int offset)
Set the writer offset.default Buffer
writeSplit(int length)
Splits the buffer into two, atlength
number of bytes from the current writerOffset() writer offset} position.-
Methods inherited from interface io.netty5.buffer.api.BufferAccessor
getBoolean, getByte, getChar, getDouble, getFloat, getInt, getLong, getMedium, getShort, getUnsignedByte, getUnsignedInt, getUnsignedMedium, getUnsignedShort, readBoolean, readByte, readChar, readDouble, readFloat, readInt, readLong, readMedium, readShort, readUnsignedByte, readUnsignedInt, readUnsignedMedium, readUnsignedShort, setBoolean, setByte, setChar, setDouble, setFloat, setInt, setLong, setMedium, setShort, setUnsignedByte, setUnsignedInt, setUnsignedMedium, setUnsignedShort, writeBoolean, writeByte, writeChar, writeDouble, writeFloat, writeInt, writeLong, writeMedium, writeShort, writeUnsignedByte, writeUnsignedInt, writeUnsignedMedium, writeUnsignedShort
-
Methods inherited from interface io.netty5.util.Resource
close, isAccessible, send, touch
-
-
-
-
Method Detail
-
capacity
int capacity()
The capacity of this buffer, that is, the maximum number of bytes it can contain.- Returns:
- The capacity in bytes.
-
readerOffset
int readerOffset()
Get the current reader offset. The next read will happen from this byte offset into the buffer.- Returns:
- The current reader offset.
-
skipReadableBytes
default Buffer skipReadableBytes(int delta)
Move the reader offset forward by the given delta.- Parameters:
delta
- to accumulate.- Returns:
- This buffer instance.
- Throws:
IndexOutOfBoundsException
- if the new reader offset is greater than the currentwriterOffset()
.IllegalArgumentException
- if the given delta is negative.BufferClosedException
- if this buffer is closed.
-
readerOffset
Buffer readerOffset(int offset)
Set the reader offset. Make the next read happen from the given offset into the buffer.- Parameters:
offset
- The reader offset to set.- Returns:
- This Buffer.
- Throws:
IndexOutOfBoundsException
- if the specifiedoffset
is less than zero or greater than the currentwriterOffset()
.BufferClosedException
- if this buffer is closed.
-
writerOffset
int writerOffset()
Get the current writer offset. The next write will happen at this byte offset into the buffer.- Returns:
- The current writer offset.
-
skipWritableBytes
default Buffer skipWritableBytes(int delta)
Move the writer offset to ahead by the given delta.- Parameters:
delta
- to accumulate.- Returns:
- This buffer instance.
- Throws:
IndexOutOfBoundsException
- if the new writer offset is greater thancapacity()
.IllegalArgumentException
- if the given delta is negative.BufferClosedException
- if this buffer is closed.BufferReadOnlyException
- if this buffer is read-only.
-
writerOffset
Buffer writerOffset(int offset)
Set the writer offset. Make the next write happen at the given offset.- Parameters:
offset
- The writer offset to set.- Returns:
- This Buffer.
- Throws:
IndexOutOfBoundsException
- if the specifiedoffset
is less than the currentreaderOffset()
or greater thancapacity()
.BufferClosedException
- if this buffer is closed.BufferReadOnlyException
- if this buffer is read-only.
-
readableBytes
default int readableBytes()
Returns the number of readable bytes which is equal to(writerOffset() - readerOffset())
.
-
writableBytes
default int writableBytes()
Returns the number of writable bytes which is equal to(capacity() - writerOffset())
.
-
fill
Buffer fill(byte value)
Fills the buffer with the given byte value. This method does not respect thereaderOffset()
orwriterOffset()
, but copies the full capacity of the buffer. ThereaderOffset()
andwriterOffset()
are not modified.- Parameters:
value
- The byte value to write at every offset in the buffer.- Returns:
- This Buffer.
- Throws:
BufferReadOnlyException
- if this buffer is read-only.
-
makeReadOnly
Buffer makeReadOnly()
Makes this buffer read-only. This is irreversible. This operation is also idempotent, so calling this method multiple times on the same buffer makes no difference.- Returns:
- This buffer instance.
-
readOnly
boolean readOnly()
Queries if this buffer is read-only or not.- Returns:
true
if this buffer is read-only,false
otherwise.
-
isDirect
boolean isDirect()
Queries if this buffer is backed by native memory, or not.- Returns:
true
if this buffer is backed by native, off-heap, memory. Otherwise,false
, if this buffer is backed by on-heap memory.
-
implicitCapacityLimit
Buffer implicitCapacityLimit(int limit)
Set an upper limit to the implicit capacity growth. Bufferwrite*
methods may implicitly grow the buffer capacity instead of throwing a bounds check exception. The implicit capacity limit restricts this growth so the buffer capacity does not automatically grow beyond the given limit. When the limit is reached, and there is no more writable space left, then thewrite*
methods will start throwing exceptions.The default limit is the maximum buffer size.
The limit is carried through
Resource.send()
calls, but the buffer instances returned from the varioussplit
andcopy
methods will have the default limit set.The limit is not impacted by calls to
split
methods on this buffer. In other words, even thoughsplit
methods reduce the capacity of this buffer, the set limit, if any, remains the same.- Parameters:
limit
- The maximum size this buffers capacity will implicitly grow to viawrite*
methods.- Returns:
- This buffer instance.
- Throws:
IndexOutOfBoundsException
- if the limit is negative, greater than the maximum buffer size, or if the capacity is already greater than the given limit.
-
implicitCapacityLimit
int implicitCapacityLimit()
Returns the implicit capacity limit of the buffer. If none was set before viaimplicitCapacityLimit(int)
this method will return the default value.- Returns:
- the limit.
-
copyInto
void copyInto(int srcPos, byte[] dest, int destPos, int length)
Copies the given length of data from this buffer into the given destination array, beginning at the given source position in this buffer, and the given destination position in the destination array.This method does not read or modify the write offset or the read offset.
- Parameters:
srcPos
- The byte offset into this buffer from where the copying should start; the byte at this offset in this buffer will be copied to thedestPos
index in thedest
array.dest
- The destination byte array.destPos
- The index into thedest
array from where the copying should start.length
- The number of bytes to copy.- Throws:
NullPointerException
- if the destination array is null.IndexOutOfBoundsException
- if the source or destination positions, or the length, are negative, or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.BufferClosedException
- if this buffer is closed.
-
copyInto
void copyInto(int srcPos, ByteBuffer dest, int destPos, int length)
Copies the given length of data from this buffer into the given destination byte buffer, beginning at the given source position in this buffer, and the given destination position in the destination byte buffer.This method does not read or modify the write offset or the read offset, nor is the position of the destination buffer changed.
The position and limit of the destination byte buffer are also ignored, and do not influence
destPos
orlength
.- Parameters:
srcPos
- The byte offset into this buffer from where the copying should start; the byte at this offset in this buffer will be copied to thedestPos
index in thedest
array.dest
- The destination byte buffer.destPos
- The index into thedest
array from where the copying should start.length
- The number of bytes to copy.- Throws:
NullPointerException
- if the destination buffer is null.IndexOutOfBoundsException
- if the source or destination positions, or the length, are negative, or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.ReadOnlyBufferException
- if the destination buffer is read-only.BufferClosedException
- if this buffer is closed.
-
copyInto
void copyInto(int srcPos, Buffer dest, int destPos, int length)
Copies the given length of data from this buffer into the given destination buffer, beginning at the given source position in this buffer, and the given destination position in the destination buffer.This method does not read or modify the write offset or the read offset on this buffer, nor on the destination buffer.
The read and write offsets of the destination buffer are also ignored, and do not influence
destPos
orlength
.- Parameters:
srcPos
- The byte offset into this buffer from where the copying should start; the byte at this offset in this buffer will be copied to thedestPos
index in thedest
array.dest
- The destination buffer.destPos
- The index into thedest
array from where the copying should start.length
- The number of bytes to copy.- Throws:
NullPointerException
- if the destination buffer is null.IndexOutOfBoundsException
- if the source or destination positions, or the length, are negative, or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.BufferReadOnlyException
- if the destination buffer is read-only.BufferClosedException
- if this or the destination buffer is closed.
-
transferTo
int transferTo(WritableByteChannel channel, int length) throws IOException
Read from this buffer and write to the given channel. The number of bytes actually written to the channel are returned. No more than the givenlength
of bytes, or the number of readable bytes, will be written to the channel, whichever is smaller. If the channel has a position, then it will be advanced by the number of bytes written. The reader-offset of this buffer will likewise be advanced by the number of bytes written.- Parameters:
channel
- The channel to write to.length
- The maximum number of bytes to write.- Returns:
- The actual number of bytes written, possibly zero.
- Throws:
IOException
- If the write-operation on the channel failed for some reason.
-
transferFrom
int transferFrom(FileChannel channel, long position, int length) throws IOException
Read from the given channel starting from the given position and write to this buffer. The number of bytes actually read from the channel are returned, or -1 is returned if the channel has reached the end-of-stream. No more than the givenlength
of bytes, or the number of writable bytes, will be read from the channel, whichever is smaller. The channel's position is not modified. The writer-offset of this buffer will likewise be advanced by the number of bytes read.- Parameters:
channel
- The channel to read from.position
- The file position.length
- The maximum number of bytes to read.- Returns:
- The actual number of bytes read, possibly zero, or -1 if the end-of-stream has been reached.
- Throws:
IOException
- If the read-operation on the channel failed for some reason.
-
transferFrom
int transferFrom(ReadableByteChannel channel, int length) throws IOException
Read from the given channel and write to this buffer. The number of bytes actually read from the channel are returned, or -1 is returned if the channel has reached the end-of-stream. No more than the givenlength
of bytes, or the number of writable bytes, will be read from the channel, whichever is smaller. If the channel has a position, then it will be advanced by the number of bytes read. The writer-offset of this buffer will likewise be advanced by the number of bytes read.- Parameters:
channel
- The channel to read from.length
- The maximum number of bytes to read.- Returns:
- The actual number of bytes read, possibly zero, or -1 if the end-of-stream has been reached.
- Throws:
IOException
- If the read-operation on the channel failed for some reason.
-
writeCharSequence
default Buffer writeCharSequence(CharSequence source, Charset charset)
Writes into this buffer, all the bytes from the givensource
using the passedcharset
. This updates the write offset of this buffer.- Parameters:
source
-CharSequence
to read from.charset
-Charset
to use for writing.- Returns:
- This buffer.
-
readCharSequence
default CharSequence readCharSequence(int length, Charset charset)
Reads aCharSequence
of the passedlength
using the passedCharset
. This updates the readerOffset() reader offset} of this buffer.- Parameters:
length
- ofCharSequence
to read.charset
- of the bytes to be read.- Returns:
CharSequence
read from this buffer.- Throws:
IndexOutOfBoundsException
- if the passedlength
is more than the readableBytes() of this buffer.
-
writeBytes
default Buffer writeBytes(Buffer source)
Writes into this buffer, all the readable bytes from the given buffer. This updates the write offset of this buffer, and the reader offset of the given buffer.- Parameters:
source
- The buffer to read from.- Returns:
- This buffer.
- Throws:
NullPointerException
- If the source buffer isnull
.
-
writeBytes
default Buffer writeBytes(byte[] source)
Writes into this buffer, all the bytes from the given byte array. This updates the write offset of this buffer by the length of the array.- Parameters:
source
- The byte array to read from.- Returns:
- This buffer.
-
writeBytes
default Buffer writeBytes(byte[] source, int srcPos, int length)
Writes into this buffer, the given number of bytes from the byte array. This updates the write offset of this buffer by the length argument.- Parameters:
source
- The byte array to read from.srcPos
- Position in thesource
from where bytes should be written to this buffer.length
- The number of bytes to copy.- Returns:
- This buffer.
-
writeBytes
default Buffer writeBytes(ByteBuffer source)
Writes into this buffer from the sourceByteBuffer
. This updates the write offset of this buffer and also the position of the sourceByteBuffer
.Note: the behaviour is undefined if the given
ByteBuffer
is an alias for the memory in this buffer.- Parameters:
source
- TheByteBuffer
to read from.- Returns:
- This buffer.
-
readBytes
default Buffer readBytes(ByteBuffer destination)
Read from this buffer, into the destinationByteBuffer
This updates the read offset of this buffer and also the position of the destinationByteBuffer
.Note: the behaviour is undefined if the given
ByteBuffer
is an alias for the memory in this buffer.- Parameters:
destination
- TheByteBuffer
to write into.- Returns:
- This buffer.
-
readBytes
default Buffer readBytes(byte[] destination, int destPos, int length)
Read from this buffer, into the destination array, the given number of bytes. This updates the read offset of this buffer by the length argument.- Parameters:
destination
- The byte array to write into.destPos
- Position in thedestination
to where bytes should be written from this buffer.length
- The number of bytes to copy.- Returns:
- This buffer.
-
resetOffsets
default Buffer resetOffsets()
Resets the read offset and the write offset on this buffer to zero, and return this buffer.- Returns:
- This buffer instance.
-
bytesBefore
int bytesBefore(byte needle)
Get the number of readable bytes, until the givenneedle
is found in this buffer. If the needle is not found,-1
is returned.This method does not modify the reader-offset or the write-offset.
- Parameters:
needle
- The byte value to search for.- Returns:
- The offset, relative to the current
readerOffset()
, of the found value, or-1
if none was found.
-
bytesBefore
int bytesBefore(Buffer needle)
Get the number of readable bytes, until the givenneedle
is found in this buffer. The found offset will be the offset into this buffer, relative to its reader-offset, of the first byte of a sequence that matches all readable bytes in the givenneedle
buffer. If the needle is not found,-1
is returned.This method does not modify the reader-offset or the write-offset.
- Parameters:
needle
- The buffer value to search for.- Returns:
- The offset, relative to the current
readerOffset()
, of the found value, or-1
if none was found.
-
openCursor
ByteCursor openCursor()
Opens a cursor to iterate the readable bytes of this buffer. The reader offset and writer offset are not modified by the cursor.Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that the reader offset and writer offset are not modified while the iteration takes place. Otherwise, unpredictable behaviour might result.
- Returns:
- A
ByteCursor
for iterating the readable bytes of this buffer.
-
openCursor
ByteCursor openCursor(int fromOffset, int length)
Opens a cursor to iterate the given number bytes of this buffer, starting at the given offset. The reader offset and writer offset are not modified by the cursor.Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that the reader offset and writer offset are not modified while the iteration takes place. Otherwise, unpredictable behaviour might result.
- Parameters:
fromOffset
- The offset into the buffer where iteration should start. The first byte read from the iterator will be the byte at this offset.length
- The number of bytes to iterate.- Returns:
- A
ByteCursor
for the given stretch of bytes of this buffer. - Throws:
IllegalArgumentException
- if the length is negative, or if the region given by thefromOffset
and thelength
reaches outside the bounds of this buffer.
-
openReverseCursor
default ByteCursor openReverseCursor()
Opens a cursor to iterate the readable bytes of this buffer, in reverse. The reader offset and writer offset are not modified by the cursor.Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that the reader offset and writer offset are not modified while the iteration takes place. Otherwise, unpredictable behaviour might result.
- Returns:
- A
ByteCursor
for the readable bytes of this buffer.
-
openReverseCursor
ByteCursor openReverseCursor(int fromOffset, int length)
Opens a cursor to iterate the given number bytes of this buffer, in reverse, starting at the given offset. The reader offset and writer offset are not modified by the cursor.Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that the reader offset and writer offset are not modified while the iteration takes place. Otherwise, unpredictable behaviour might result.
- Parameters:
fromOffset
- The offset into the buffer where iteration should start. The first byte read from the iterator will be the byte at this offset.length
- The number of bytes to iterate.- Returns:
- A
ByteCursor
for the given stretch of bytes of this buffer. - Throws:
IllegalArgumentException
- if the length is negative, or if the region given by thefromOffset
and thelength
reaches outside the bounds of this buffer.
-
ensureWritable
default Buffer ensureWritable(int size)
Ensures that this buffer has at least the given number of bytes of available space for writing. If this buffer already has the necessary space, then this method returns immediately. If this buffer does not already have the necessary space, then it will be expanded using theBufferAllocator
the buffer was created with. This method is the same as callingensureWritable(int, int, boolean)
whereallowCompaction
istrue
.- Parameters:
size
- The requested number of bytes of space that should be available for writing.- Returns:
- This buffer instance.
- Throws:
IllegalStateException
- if this buffer is in a bad state.BufferClosedException
- if this buffer is closed.BufferReadOnlyException
- if this buffer is read-only.
-
ensureWritable
Buffer ensureWritable(int size, int minimumGrowth, boolean allowCompaction)
Ensures that this buffer has at least the given number of bytes of available space for writing. If this buffer already has the necessary space, then this method returns immediately. If this buffer does not already have the necessary space, then space will be made available in one or all of the following available ways:-
If
allowCompaction
istrue
, and sum of the read and writable bytes would be enough to satisfy the request, and it (depending on the buffer implementation) seems faster and easier to compact the existing buffer rather than allocation a new buffer, then the requested bytes will be made available that way. The compaction will not necessarily work the same way as thecompact()
method, as the implementation may be able to make the requested bytes available with less effort than is strictly mandated by thecompact()
method. -
Regardless of the value of the
allowCompaction
, the implementation may make more space available by just allocating more or larger buffers. This allocation would use the sameBufferAllocator
that this buffer was created with. -
If
allowCompaction
istrue
, then the implementation may choose to do a combination of compaction and allocation.
- Parameters:
size
- The requested number of bytes of space that should be available for writing.minimumGrowth
- The minimum number of bytes to grow by. If it is determined that memory should be allocated and copied, make sure that the new memory allocation is bigger than the old one by at least this many bytes. This way, the buffer can grow by more than what is immediately necessary, thus amortising the costs of allocating and copying.allowCompaction
-true
if the method is allowed to modify the reader offset and writer offset, otherwisefalse
.- Returns:
- This buffer instance.
- Throws:
BufferReadOnlyException
- if this buffer is read-only.IllegalArgumentException
- ifsize
orminimumGrowth
are negative.IllegalStateException
- if this buffer is in a bad state.
-
If
-
copy
default Buffer copy()
Returns a copy of this buffer's readable bytes. Modifying the content of the returned buffer will not affect this buffers contents. The two buffers will maintain separate offsets. This method is identical tobuf.copy(buf.readerOffset(), buf.readableBytes())
. This method does not modifyreaderOffset()
orwriterOffset()
of this buffer.The copy is created with a write offset equal to the length of the copied data, so that the entire contents of the copy is ready to be read.
The returned buffer will not be read-only, regardless of the read-only state of this buffer.
- Returns:
- A new buffer instance, with independent
readerOffset()
andwriterOffset()
, that contains a copy of the readable region of this buffer. - Throws:
BufferClosedException
- if this buffer is closed.
-
copy
default Buffer copy(int offset, int length)
Returns a copy of the given region of this buffer. Modifying the content of the returned buffer will not affect this buffers contents. The two buffers will maintain separate offsets. This method does not modifyreaderOffset()
orwriterOffset()
of this buffer.The copy is created with a write offset equal to the length of the copy, so that the entire contents of the copy is ready to be read.
The returned buffer will not be read-only, regardless of the read-only state of this buffer. This has the same effect as calling
copy(int, int, boolean)
with afalse
read-only argument.- Parameters:
offset
- The offset where copying should start from. This is the offset of the first byte copied.length
- The number of bytes to copy, and the capacity of the returned buffer.- Returns:
- A new buffer instance, with independent
readerOffset()
andwriterOffset()
, that contains a copy of the given region of this buffer. - Throws:
IllegalArgumentException
- if theoffset
orlength
reaches outside the bounds of the buffer.BufferClosedException
- if this buffer is closed.
-
copy
default Buffer copy(boolean readOnly)
Returns a copy of this buffer's readable bytes, with the given read-only setting. Modifying the content of the returned buffer will not affect this buffers contents. The two buffers will maintain separate offsets. This method does not modifyreaderOffset()
orwriterOffset()
of this buffer.The copy is created with a write offset equal to the length of the copy, so that the entire contents of the copy is ready to be read.
The returned buffer will be read-only if, and only if, the
readOnly
argument istrue
, and it will not be read-only if the argument isfalse
. This is the case regardless of the read-only state of this buffer.If this buffer is read-only, and a read-only copy is requested, then implementations may use structural sharing and have both buffers backed by the same underlying memory.
- Parameters:
readOnly
- The desiredreadOnly()
state of the returned buffer.- Returns:
- A new buffer instance, with independent
readerOffset()
andwriterOffset()
, that contains a copy of the given region of this buffer. - Throws:
IllegalArgumentException
- if theoffset
orlength
reaches outside the bounds of the buffer.BufferClosedException
- if this buffer is closed.
-
copy
Buffer copy(int offset, int length, boolean readOnly)
Returns a copy of the given region of this buffer. Modifying the content of the returned buffer will not affect this buffers contents. The two buffers will maintain separate offsets. This method does not modifyreaderOffset()
orwriterOffset()
of this buffer.The copy is created with a write offset equal to the length of the copy, so that the entire contents of the copy is ready to be read.
The returned buffer will be read-only if, and only if, the
readOnly
argument istrue
, and it will not be read-only if the argument isfalse
. This is the case regardless of the read-only state of this buffer.If this buffer is read-only, and a read-only copy is requested, then implementations may use structural sharing and have both buffers backed by the same underlying memory.
- Parameters:
offset
- The offset where copying should start from. This is the offset of the first byte copied.length
- The number of bytes to copy, and the capacity of the returned buffer.readOnly
- The desiredreadOnly()
state of the returned buffer.- Returns:
- A new buffer instance, with independent
readerOffset()
andwriterOffset()
, that contains a copy of the given region of this buffer. - Throws:
IllegalArgumentException
- if theoffset
orlength
reaches outside the bounds of the buffer.BufferClosedException
- if this buffer is closed.
-
readSplit
default Buffer readSplit(int length)
Splits the buffer into two, atlength
number of bytes from the current readerOffset() reader offset} position.The region of this buffer that contain the previously read and readable bytes till the
readerOffset() + length
position, will be captured and returned in a new buffer, that will hold its own ownership of that region. This allows the returned buffer to be independently sent to other threads.The returned buffer will change its
readerOffset()
toreaderOffset() + length
, and have itswriterOffset()
andcapacity()
both set to thereaderOffset() + length
position.The memory region in the returned buffer will become inaccessible through this buffer. This buffer will have its capacity reduced by the capacity of the returned buffer, read offset will become zero and relative position of write offset will be preserved from the provided
readerOffset() + length
position, even though their position in memory remain unchanged.Effectively, the following transformation takes place:
When the buffers are in this state, both of the split parts retain an atomic reference count on the underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until all the split parts have been closed.This buffer, where offset = readerOffset() + length: +------------------------------------------+ 0| |r/o offset |w/o |cap +---+---------+-----------+----------------+ / / / \ \ \ / / / \ \ \ / / / \ \ \ / / / \ \ \ / / / \ \ \ +---+---------+ +----------+----------------+ | |r/o |w/o & cap |r/o w/o |cap +---+---------+ +---------------------------+ Returned buffer. This buffer.
Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be split. If the split point lands perfectly between two constituent buffers, then a composite buffer can simply split its internal array in two.
Split buffers support all operations that normal buffers do, including
ensureWritable(int)
.See the Splitting buffers section for details.
- Returns:
- A new buffer with independent and exclusive ownership over the previously read and readable bytes from this buffer.
-
writeSplit
default Buffer writeSplit(int length)
Splits the buffer into two, atlength
number of bytes from the current writerOffset() writer offset} position.The region of this buffer that contain the previously read and readable bytes till the
writerOffset() + length
position, will be captured and returned in a new buffer, that will hold its own ownership of that region. This allows the returned buffer to be independently sent to other threads.The returned buffer will change its
writerOffset()
towriterOffset() + length
, and have itswriterOffset()
andcapacity()
both set to thewriterOffset() + length
.The memory region in the returned buffer will become inaccessible through this buffer. This buffer will have its capacity reduced by the capacity of the returned buffer, read offset will become zero and relative position of write offset will be preserved from the provided
writerOffset() + length
position, even though their position in memory remain unchanged.Effectively, the following transformation takes place:
When the buffers are in this state, both of the split parts retain an atomic reference count on the underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until all the split parts have been closed.This buffer, where offset = writerOffset() + length: +------------------------------------------+ 0| |r/o |w/o offset |cap +---+----+-------+-------------------------+ / / / / \ \ / / / / \ \ / / / / \ \ / / / / \ \ / / / / \ \ +---+----+-------+ +------------------------+ | |r/o |w/o | cap |r/o & w/o |cap +---+----+-------+ +------------------------+ Returned buffer. This buffer.
Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be split. If the split point lands perfectly between two constituent buffers, then a composite buffer can simply split its internal array in two.
Split buffers support all operations that normal buffers do, including
ensureWritable(int)
.See the Splitting buffers section for details.
- Returns:
- A new buffer with independent and exclusive ownership over the previously read and readable bytes from this buffer.
-
split
default Buffer split()
Splits the buffer into two, at the write offset position.The region of this buffer that contain the previously read and readable bytes, will be captured and returned in a new buffer, that will hold its own ownership of that region. This allows the returned buffer to be independently sent to other threads.
The returned buffer will adopt the
readerOffset()
of this buffer, and have itswriterOffset()
andcapacity()
both set to the equal to the write-offset of this buffer.The memory region in the returned buffer will become inaccessible through this buffer. This buffer will have its capacity reduced by the capacity of the returned buffer, and the read and write offsets of this buffer will both become zero, even though their position in memory remain unchanged.
Effectively, the following transformation takes place:
When the buffers are in this state, both of the split parts retain an atomic reference count on the underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until all the split parts have been closed.This buffer: +------------------------------------------+ 0| |r/o |w/o |cap +---+---------------------+----------------+ / / / \ \ / / / \ \ / / / \ \ / / / \ \ / / / \ \ +---+---------------------+ +---------------+ | |r/o |w/o & cap |r/o & w/o |cap +---+---------------------+ +---------------+ Returned buffer. This buffer.
Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be split. If the split point lands perfectly between two constituent buffers, then a composite buffer can simply split its internal array in two.
Split buffers support all operations that normal buffers do, including
ensureWritable(int)
.See the Splitting buffers section for details.
- Returns:
- A new buffer with independent and exclusive ownership over the previously read and readable bytes from this buffer.
-
split
Buffer split(int splitOffset)
Splits the buffer into two, at the givensplitOffset
.The region of this buffer that precede the
splitOffset
, will be captured and returned in a new buffer, that will hold its own ownership of that region. This allows the returned buffer to be independently sent to other threads.The returned buffer will adopt the
readerOffset()
andwriterOffset()
of this buffer, but truncated to fit within the capacity dictated by thesplitOffset
.The memory region in the returned buffer will become inaccessible through this buffer. If the
readerOffset()
orwriterOffset()
of this buffer lie prior to thesplitOffset
, then those offsets will be moved forward, so they land on offset 0 after the split.Effectively, the following transformation takes place:
When the buffers are in this state, both of the split parts retain an atomic reference count on the underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until all the split parts have been closed.This buffer: +--------------------------------+ 0| |splitOffset |cap +---------------+----------------+ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ +---------------+ +---------------+ | |cap | |cap +---------------+ +---------------+ Returned buffer. This buffer.
Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be split. If the split point lands perfectly between two constituent buffers, then a composite buffer can simply split its internal array in two.
Split buffers support all operations that normal buffers do, including
ensureWritable(int)
.See the Splitting buffers section for details.
- Parameters:
splitOffset
- The offset into this buffer where it should be split. After the split, the data at this offset will be at offset zero in this buffer.- Returns:
- A new buffer with independent and exclusive ownership over the bytes from the beginning to the given offset of this buffer.
-
compact
Buffer compact()
Discards the read bytes, and moves the buffer contents to the beginning of the buffer.- Returns:
- This buffer instance.
- Throws:
BufferReadOnlyException
- if this buffer is read-only.IllegalStateException
- if this buffer is in a bad state.
-
countComponents
int countComponents()
Get the number of "components" in this buffer. For composite buffers, this is the number of transitive constituent buffers, while non-composite buffers only have one component.- Returns:
- The number of components in this buffer.
-
countReadableComponents
int countReadableComponents()
Get the number of "components" in this buffer, that are readable. These are the components that would be processed byforEachReadable(int, ReadableComponentProcessor)
. For composite buffers, this is the number of transitive constituent buffers that are readable, while non-composite buffers only have at most one readable component.The number of readable components may be less than the
component count
, if not all of them have readable data.- Returns:
- The number of readable components in this buffer.
-
countWritableComponents
int countWritableComponents()
Get the number of "components" in this buffer, that are writable. These are the components that would be processed byforEachWritable(int, WritableComponentProcessor)
. For composite buffers, this is the number of transitive constituent buffers that are writable, while non-composite buffers only have at most one writable component.The number of writable components may be less than the
component count
, if not all of them have space for writing.- Returns:
- The number of writable components in this buffer.
-
forEachReadable
<E extends Exception> int forEachReadable(int initialIndex, ReadableComponentProcessor<E> processor) throws E extends Exception
Processes all readable components of this buffer, and return the number of components processed.The given processor is called for each readable component in this buffer, and passed a component index, for the given component in the iteration, and a
ReadableComponent
object for accessing the data within the given component.The component index is specific to the particular invocation of this method. The first call to the consumer will be passed the given initial index, and the next call will be passed the initial index plus one, and so on.
The component processor may stop the iteration at any time by returning
false
. This will cause the number of components processed to be returned as a negative number (to signal early return), and the number of components processed may then be less than the readable component count.Note that the
ReadableComponent
instance passed to the consumer could be reused for multiple calls, so the data must be extracted from the component in the context of the iteration.The
ByteBuffer
instances obtained from the component, share lifetime with that internal component. This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause such changes aresplit(int)
,split()
,readSplit(int)
,writeSplit(int)
,compact()
,ensureWritable(int)
,ensureWritable(int, int, boolean)
, andResource.send()
.The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration.
Note that the arrays, memory addresses, and byte buffers exposed as components by this method, should not be used for changing the buffer contents. Doing so may cause undefined behaviour.
Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to this buffer instance.
- Parameters:
initialIndex
- The initial index of the component for iteration, and the index that will be passed to the first call to the processor.processor
- The processor that will be used to process the buffer components.- Returns:
- The number of readable components processed, as a positive number if all readable components were
processed, or as a negative number if the iteration was stopped because
ReadableComponentProcessor.process(int, ReadableComponent)
returnedfalse
. In any case, the number of components processed may be less thancountComponents()
. - Throws:
E extends Exception
-
forEachReadable
<T extends ReadableComponent & ComponentIterator.Next> ComponentIterator<T> forEachReadable()
Create a component iterator for all readable components in this buffer.Unlike the
forEachReadable(int, ReadableComponentProcessor)
method, this API permits external iteration of the components, while at the same time protecting the life-cycle of the buffer.The typical code pattern for using this API looks like the following:
Note the use of thetry (var iteration = buffer.forEachReadable()) { for (var c = iteration.first(); c != null; c = c.next()) { ByteBuffer componentBuffer = c.readableBuffer(); // ... } }
var
keyword for local variables, which are required for correctly expressing the generic types used in the iteration. Following this code pattern will ensure that the components, and their parent buffer, will be correctly life-cycled.Note that the
ReadableComponent
instances exposed by the iterator could be reused for multiple calls, so the data must be extracted from the component in the context of the iteration.The
ByteBuffer
instances obtained from the component, share lifetime with that internal component. This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause such changes aresplit(int)
,split()
,readSplit(int)
,writeSplit(int)
,compact()
,ensureWritable(int)
,ensureWritable(int, int, boolean)
, andResource.send()
.The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration.
Note that the arrays, memory addresses, and byte buffers exposed as components by this method, should not be used for changing the buffer contents. Doing so may cause undefined behaviour.
Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to this buffer instance.
- Type Parameters:
T
- An intersection type that presents both theReadableComponent
interface, and the ability to progress the iteration via theComponentIterator.Next.next()
method.- Returns:
- A component iterator of readable components.
-
forEachWritable
<E extends Exception> int forEachWritable(int initialIndex, WritableComponentProcessor<E> processor) throws E extends Exception
Process all writable components of this buffer, and return the number of components processed.The given processor is called for each writable component in this buffer, and passed a component index, for the given component in the iteration, and a
WritableComponent
object for accessing the data within the given component.The component index is specific to the particular invocation of this method. The first call to the consumer will be passed the given initial index, and the next call will be passed the initial index plus one, and so on.
The
component processor
may stop the iteration at any time by returningfalse
. This will cause the number of components processed to be returned as a negative number (to signal early return), and the number of components processed may then be less than the readable component count.Note that the
WritableComponent
instance passed to the consumer could be reused for multiple calls, so the data must be extracted from the component in the context of the iteration.The
ByteBuffer
instances obtained from the component, share lifetime with that internal component. This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause such changes aresplit(int)
,split()
,readSplit(int)
,writeSplit(int)
,compact()
,ensureWritable(int)
,ensureWritable(int, int, boolean)
, andResource.send()
.The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration.
Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to this buffer instance.
- Parameters:
initialIndex
- The initial index of the component for iteration, and the index that will be passed to the first call to the processor.processor
- The processor that will be used to process the buffer components.- Returns:
- The number of writable components processed, as a positive number if all writable components were
processed, or as a negative number if the iteration was stopped because
WritableComponentProcessor.process(int, WritableComponent)
returnedfalse
. In any case, the number of components processed may be less thancountComponents()
. - Throws:
E extends Exception
-
forEachWritable
<T extends WritableComponent & ComponentIterator.Next> ComponentIterator<T> forEachWritable()
Create a component iterator for all writable components in this buffer.Unlike the
forEachWritable(int, WritableComponentProcessor)
method, this API permits external iteration of the components, while at the same time protecting the life-cycle of the buffer.The typical code pattern for using this API looks like the following:
Note the use of thetry (var iteration = buffer.forEachWritable()) { for (var c = iteration.first(); c != null; c = c.next()) { ByteBuffer componentBuffer = c.writableBuffer(); // ... } }
var
keyword for local variables, which are required for correctly expressing the generic types used in the iteration. Following this code pattern will ensure that the components, and their parent buffer, will be correctly life-cycled.Note that the
WritableComponent
instances exposed by the iterator could be reused for multiple calls, so the data must be extracted from the component in the context of the iteration.The
ByteBuffer
instances obtained from the component, share lifetime with that internal component. This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause such changes aresplit(int)
,split()
,readSplit(int)
,writeSplit(int)
,compact()
,ensureWritable(int)
,ensureWritable(int, int, boolean)
, andResource.send()
.The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration.
Note that the arrays, memory addresses, and byte buffers exposed as components by this method, should not be used for changing the buffer contents beyond the respective array offset and length, or buffer position and limit. Doing so may cause undefined behaviour.
Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to this buffer instance.
- Type Parameters:
T
- An intersection type that presents both theReadableComponent
interface, and the ability to progress the iteration via theComponentIterator.Next.next()
method.- Returns:
- A component iterator of readable components.
-
-