[prev in list] [next in list] [prev in thread] [next in thread]
List: mina-commits
Subject: [mina] branch 2.1.X updated: Adds DIRMINA-1133 Pretty Hex Dumps
From: johnnyv () apache ! org
Date: 2020-09-21 17:20:04
Message-ID: 160070880437.21378.9162514666781274632 () gitbox ! apache ! org
[Download RAW message or body]
This is an automated email from the ASF dual-hosted git repository.
johnnyv pushed a commit to branch 2.1.X
in repository https://gitbox.apache.org/repos/asf/mina.git
The following commit(s) were added to refs/heads/2.1.X by this push:
new 393ad9b Adds DIRMINA-1133 Pretty Hex Dumps
393ad9b is described below
commit 393ad9bf4e93236b5195189b773dc550e8aa469f
Author: Jonathan Valliere <johnnyv@apache.org>
AuthorDate: Mon Sep 21 13:19:19 2020 -0400
Adds DIRMINA-1133 Pretty Hex Dumps
---
.../apache/mina/core/buffer/AbstractIoBuffer.java | 5429 ++++++++++----------
.../java/org/apache/mina/core/buffer/IoBuffer.java | 4019 +++++++--------
.../apache/mina/core/buffer/IoBufferHexDumper.java | 253 +-
.../apache/mina/core/buffer/IoBufferWrapper.java | 3020 +++++------
.../mina/core/buffer/IoBufferHexDumperTest.java | 70 +-
5 files changed, 6475 insertions(+), 6316 deletions(-)
diff --git a/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java \
b/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java index \
aa46c83..e725f08 100644
--- a/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
+++ b/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
@@ -47,2723 +47,2724 @@ import java.util.EnumSet;
import java.util.Set;
/**
- * A base implementation of {@link IoBuffer}. This implementation
- * assumes that {@link IoBuffer#buf()} always returns a correct NIO
- * {@link ByteBuffer} instance. Most implementations could
- * extend this class and implement their own buffer management mechanism.
+ * A base implementation of {@link IoBuffer}. This implementation assumes that
+ * {@link IoBuffer#buf()} always returns a correct NIO {@link ByteBuffer}
+ * instance. Most implementations could extend this class and implement their
+ * own buffer management mechanism.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
* @see IoBufferAllocator
*/
public abstract class AbstractIoBuffer extends IoBuffer {
- /** Tells if a buffer has been created from an existing buffer */
- private final boolean derived;
-
- /** A flag set to true if the buffer can extend automatically */
- private boolean autoExpand;
-
- /** A flag set to true if the buffer can shrink automatically */
- private boolean autoShrink;
-
- /** Tells if a buffer can be expanded */
- private boolean recapacityAllowed = true;
-
- /** The minimum number of bytes the IoBuffer can hold */
- private int minimumCapacity;
-
- /** A mask for a byte */
- private static final long BYTE_MASK = 0xFFL;
-
- /** A mask for a short */
- private static final long SHORT_MASK = 0xFFFFL;
-
- /** A mask for an int */
- private static final long INT_MASK = 0xFFFFFFFFL;
-
- /**
- * We don't have any access to Buffer.markValue(), so we need to track it down,
- * which will cause small extra overhead.
- */
- private int mark = -1;
-
- /**
- * Creates a new parent buffer.
- *
- * @param allocator The allocator to use to create new buffers
- * @param initialCapacity The initial buffer capacity when created
- */
- protected AbstractIoBuffer(IoBufferAllocator allocator, int initialCapacity) {
- setAllocator(allocator);
- this.recapacityAllowed = true;
- this.derived = false;
- this.minimumCapacity = initialCapacity;
- }
-
- /**
- * Creates a new derived buffer. A derived buffer uses an existing
- * buffer properties - the allocator and capacity -.
- *
- * @param parent The buffer we get the properties from
- */
- protected AbstractIoBuffer(AbstractIoBuffer parent) {
- setAllocator(IoBuffer.getAllocator());
- this.recapacityAllowed = false;
- this.derived = true;
- this.minimumCapacity = parent.minimumCapacity;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final boolean isDirect() {
- return buf().isDirect();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final boolean isReadOnly() {
- return buf().isReadOnly();
- }
-
- /**
- * Sets the underlying NIO buffer instance.
- *
- * @param newBuf The buffer to store within this IoBuffer
- */
- protected abstract void buf(ByteBuffer newBuf);
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final int minimumCapacity() {
- return minimumCapacity;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer minimumCapacity(int minimumCapacity) {
- if (minimumCapacity < 0) {
- throw new IllegalArgumentException("minimumCapacity: " + \
minimumCapacity);
- }
- this.minimumCapacity = minimumCapacity;
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final int capacity() {
- return buf().capacity();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer capacity(int newCapacity) {
- if (!recapacityAllowed) {
- throw new IllegalStateException("Derived buffers and their parent can't \
be expanded.");
- }
-
- // Allocate a new buffer and transfer all settings to it.
- if (newCapacity > capacity()) {
- // Expand:
- //// Save the state.
- int pos = position();
- int limit = limit();
- ByteOrder bo = order();
-
- //// Reallocate.
- ByteBuffer oldBuf = buf();
- ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, \
isDirect());
- oldBuf.clear();
- newBuf.put(oldBuf);
- buf(newBuf);
-
- //// Restore the state.
- buf().limit(limit);
- if (mark >= 0) {
- buf().position(mark);
- buf().mark();
- }
- buf().position(pos);
- buf().order(bo);
- }
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final boolean isAutoExpand() {
- return autoExpand && recapacityAllowed;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final boolean isAutoShrink() {
- return autoShrink && recapacityAllowed;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final boolean isDerived() {
- return derived;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer setAutoExpand(boolean autoExpand) {
- if (!recapacityAllowed) {
- throw new IllegalStateException("Derived buffers and their parent can't \
be expanded.");
- }
- this.autoExpand = autoExpand;
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer setAutoShrink(boolean autoShrink) {
- if (!recapacityAllowed) {
- throw new IllegalStateException("Derived buffers and their parent can't \
be shrinked.");
- }
- this.autoShrink = autoShrink;
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer expand(int expectedRemaining) {
- return expand(position(), expectedRemaining, false);
- }
-
- private IoBuffer expand(int expectedRemaining, boolean autoExpand) {
- return expand(position(), expectedRemaining, autoExpand);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer expand(int pos, int expectedRemaining) {
- return expand(pos, expectedRemaining, false);
- }
-
- private IoBuffer expand(int pos, int expectedRemaining, boolean autoExpand) {
- if (!recapacityAllowed) {
- throw new IllegalStateException("Derived buffers and their parent can't \
be expanded.");
- }
-
- int end = pos + expectedRemaining;
- int newCapacity;
-
- if (autoExpand) {
- newCapacity = IoBuffer.normalizeCapacity(end);
- } else {
- newCapacity = end;
- }
- if (newCapacity > capacity()) {
- // The buffer needs expansion.
- capacity(newCapacity);
- }
-
- if (end > limit()) {
- // We call limit() directly to prevent StackOverflowError
- buf().limit(end);
- }
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer shrink() {
-
- if (!recapacityAllowed) {
- throw new IllegalStateException("Derived buffers and their parent can't \
be expanded.");
- }
-
- int position = position();
- int capacity = capacity();
- int limit = limit();
-
- if (capacity == limit) {
- return this;
- }
-
- int newCapacity = capacity;
- int minCapacity = Math.max(minimumCapacity, limit);
-
- for (;;) {
- if (newCapacity >>> 1 < minCapacity) {
- break;
- }
-
- newCapacity >>>= 1;
-
- if (minCapacity == 0) {
- break;
- }
- }
-
- newCapacity = Math.max(minCapacity, newCapacity);
-
- if (newCapacity == capacity) {
- return this;
- }
-
- // Shrink and compact:
- //// Save the state.
- ByteOrder bo = order();
-
- //// Reallocate.
- ByteBuffer oldBuf = buf();
- ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, \
isDirect());
- oldBuf.position(0);
- oldBuf.limit(limit);
- newBuf.put(oldBuf);
- buf(newBuf);
-
- //// Restore the state.
- buf().position(position);
- buf().limit(limit);
- buf().order(bo);
- mark = -1;
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final int position() {
- return buf().position();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer position(int newPosition) {
- autoExpand(newPosition, 0);
- buf().position(newPosition);
-
- if (mark > newPosition) {
- mark = -1;
- }
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final int limit() {
- return buf().limit();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer limit(int newLimit) {
- autoExpand(newLimit, 0);
- buf().limit(newLimit);
- if (mark > newLimit) {
- mark = -1;
- }
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer mark() {
- ByteBuffer byteBuffer = buf();
- byteBuffer.mark();
- mark = byteBuffer.position();
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final int markValue() {
- return mark;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer reset() {
- buf().reset();
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer clear() {
- buf().clear();
- mark = -1;
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer sweep() {
- clear();
- return fillAndReset(remaining());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer sweep(byte value) {
- clear();
- return fillAndReset(value, remaining());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer flip() {
- buf().flip();
- mark = -1;
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer rewind() {
- buf().rewind();
- mark = -1;
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final int remaining() {
- ByteBuffer byteBuffer = buf();
-
- return byteBuffer.limit() - byteBuffer.position();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final boolean hasRemaining() {
- ByteBuffer byteBuffer = buf();
-
- return byteBuffer.limit() > byteBuffer.position();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final byte get() {
- return buf().get();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final short getUnsigned() {
- return (short) (get() & 0xff);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer put(byte b) {
- autoExpand(1);
- buf().put(b);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putUnsigned(byte value) {
- autoExpand(1);
- buf().put((byte) (value & 0xff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putUnsigned(int index, byte value) {
- autoExpand(index, 1);
- buf().put(index, (byte) (value & 0xff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putUnsigned(short value) {
- autoExpand(1);
- buf().put((byte) (value & 0x00ff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putUnsigned(int index, short value) {
- autoExpand(index, 1);
- buf().put(index, (byte) (value & 0x00ff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putUnsigned(int value) {
- autoExpand(1);
- buf().put((byte) (value & 0x000000ff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putUnsigned(int index, int value) {
- autoExpand(index, 1);
- buf().put(index, (byte) (value & 0x000000ff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putUnsigned(long value) {
- autoExpand(1);
- buf().put((byte) (value & 0x00000000000000ffL));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putUnsigned(int index, long value) {
- autoExpand(index, 1);
- buf().put(index, (byte) (value & 0x00000000000000ffL));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final byte get(int index) {
- return buf().get(index);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final short getUnsigned(int index) {
- return (short) (get(index) & 0xff);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer put(int index, byte b) {
- autoExpand(index, 1);
- buf().put(index, b);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer get(byte[] dst, int offset, int length) {
- buf().get(dst, offset, length);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer put(ByteBuffer src) {
- autoExpand(src.remaining());
- buf().put(src);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer put(byte[] src, int offset, int length) {
- autoExpand(length);
- buf().put(src, offset, length);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer compact() {
- int remaining = remaining();
- int capacity = capacity();
-
- if (capacity == 0) {
- return this;
- }
-
- if (isAutoShrink() && remaining <= capacity >>> 2 && capacity > \
minimumCapacity) {
- int newCapacity = capacity;
- int minCapacity = Math.max(minimumCapacity, remaining << 1);
- for (;;) {
- if (newCapacity >>> 1 < minCapacity) {
- break;
- }
- newCapacity >>>= 1;
- }
-
- newCapacity = Math.max(minCapacity, newCapacity);
-
- if (newCapacity == capacity) {
- return this;
- }
-
- // Shrink and compact:
- //// Save the state.
- ByteOrder bo = order();
-
- //// Sanity check.
- if (remaining > newCapacity) {
- throw new IllegalStateException("The amount of the remaining bytes \
is greater than "
- + "the new capacity.");
- }
-
- //// Reallocate.
- ByteBuffer oldBuf = buf();
- ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, \
isDirect());
- newBuf.put(oldBuf);
- buf(newBuf);
-
- //// Restore the state.
- buf().order(bo);
- } else {
- buf().compact();
- }
- mark = -1;
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final ByteOrder order() {
- return buf().order();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer order(ByteOrder bo) {
- buf().order(bo);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final char getChar() {
- return buf().getChar();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putChar(char value) {
- autoExpand(2);
- buf().putChar(value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final char getChar(int index) {
- return buf().getChar(index);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putChar(int index, char value) {
- autoExpand(index, 2);
- buf().putChar(index, value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final CharBuffer asCharBuffer() {
- return buf().asCharBuffer();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final short getShort() {
- return buf().getShort();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putShort(short value) {
- autoExpand(2);
- buf().putShort(value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final short getShort(int index) {
- return buf().getShort(index);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putShort(int index, short value) {
- autoExpand(index, 2);
- buf().putShort(index, value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final ShortBuffer asShortBuffer() {
- return buf().asShortBuffer();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final int getInt() {
- return buf().getInt();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putInt(int value) {
- autoExpand(4);
- buf().putInt(value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedInt(byte value) {
- autoExpand(4);
- buf().putInt(value & 0x00ff);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedInt(int index, byte value) {
- autoExpand(index, 4);
- buf().putInt(index, value & 0x00ff);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedInt(short value) {
- autoExpand(4);
- buf().putInt(value & 0x0000ffff);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedInt(int index, short value) {
- autoExpand(index, 4);
- buf().putInt(index, value & 0x0000ffff);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedInt(int value) {
- return putInt(value);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedInt(int index, int value) {
- return putInt(index, value);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedInt(long value) {
- autoExpand(4);
- buf().putInt((int) (value & 0x00000000ffffffff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedInt(int index, long value) {
- autoExpand(index, 4);
- buf().putInt(index, (int) (value & 0x00000000ffffffffL));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedShort(byte value) {
- autoExpand(2);
- buf().putShort((short) (value & 0x00ff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedShort(int index, byte value) {
- autoExpand(index, 2);
- buf().putShort(index, (short) (value & 0x00ff));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedShort(short value) {
- return putShort(value);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedShort(int index, short value) {
- return putShort(index, value);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedShort(int value) {
- autoExpand(2);
- buf().putShort((short) value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedShort(int index, int value) {
- autoExpand(index, 2);
- buf().putShort(index, (short) value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedShort(long value) {
- autoExpand(2);
- buf().putShort((short) (value));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putUnsignedShort(int index, long value) {
- autoExpand(index, 2);
- buf().putShort(index, (short) (value));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final int getInt(int index) {
- return buf().getInt(index);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putInt(int index, int value) {
- autoExpand(index, 4);
- buf().putInt(index, value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IntBuffer asIntBuffer() {
- return buf().asIntBuffer();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final long getLong() {
- return buf().getLong();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putLong(long value) {
- autoExpand(8);
- buf().putLong(value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final long getLong(int index) {
- return buf().getLong(index);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putLong(int index, long value) {
- autoExpand(index, 8);
- buf().putLong(index, value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final LongBuffer asLongBuffer() {
- return buf().asLongBuffer();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final float getFloat() {
- return buf().getFloat();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putFloat(float value) {
- autoExpand(4);
- buf().putFloat(value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final float getFloat(int index) {
- return buf().getFloat(index);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putFloat(int index, float value) {
- autoExpand(index, 4);
- buf().putFloat(index, value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final FloatBuffer asFloatBuffer() {
- return buf().asFloatBuffer();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final double getDouble() {
- return buf().getDouble();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putDouble(double value) {
- autoExpand(8);
- buf().putDouble(value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final double getDouble(int index) {
- return buf().getDouble(index);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer putDouble(int index, double value) {
- autoExpand(index, 8);
- buf().putDouble(index, value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final DoubleBuffer asDoubleBuffer() {
- return buf().asDoubleBuffer();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer asReadOnlyBuffer() {
- recapacityAllowed = false;
- return asReadOnlyBuffer0();
- }
-
- /**
- * Implement this method to return the unexpandable read only version of
- * this buffer.
- *
- * @return the IoBoffer instance
- */
- protected abstract IoBuffer asReadOnlyBuffer0();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer duplicate() {
- recapacityAllowed = false;
- return duplicate0();
- }
-
- /**
- * Implement this method to return the unexpandable duplicate of this
- * buffer.
- *
- * @return the IoBoffer instance
- */
- protected abstract IoBuffer duplicate0();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer slice() {
- recapacityAllowed = false;
- return slice0();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer getSlice(int index, int length) {
- if (length < 0) {
- throw new IllegalArgumentException("length: " + length);
- }
-
- int pos = position();
- int limit = limit();
-
- if (index > limit) {
- throw new IllegalArgumentException("index: " + index);
- }
-
- int endIndex = index + length;
-
- if (endIndex > limit) {
- throw new IndexOutOfBoundsException("index + length (" + endIndex + ") \
is greater " + "than limit ("
- + limit + ").");
- }
-
- clear();
- limit(endIndex);
- position(index);
-
- IoBuffer slice = slice();
- limit(limit);
- position(pos);
-
- return slice;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final IoBuffer getSlice(int length) {
- if (length < 0) {
- throw new IllegalArgumentException("length: " + length);
- }
- int pos = position();
- int limit = limit();
- int nextPos = pos + length;
- if (limit < nextPos) {
- throw new IndexOutOfBoundsException("position + length (" + nextPos + ") \
is greater " + "than limit ("
- + limit + ").");
- }
-
- limit(pos + length);
- IoBuffer slice = slice();
- position(nextPos);
- limit(limit);
- return slice;
- }
-
- /**
- * Implement this method to return the unexpandable slice of this
- * buffer.
- *
- * @return the IoBoffer instance
- */
- protected abstract IoBuffer slice0();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- int h = 1;
- int p = position();
- for (int i = limit() - 1; i >= p; i--) {
- h = 31 * h + get(i);
- }
- return h;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof IoBuffer)) {
- return false;
- }
-
- IoBuffer that = (IoBuffer) o;
- if (this.remaining() != that.remaining()) {
- return false;
- }
-
- int p = this.position();
- for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
- byte v1 = this.get(i);
- byte v2 = that.get(j);
- if (v1 != v2) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int compareTo(IoBuffer that) {
- int n = this.position() + Math.min(this.remaining(), that.remaining());
- for (int i = this.position(), j = that.position(); i < n; i++, j++) {
- byte v1 = this.get(i);
- byte v2 = that.get(j);
- if (v1 == v2) {
- continue;
- }
- if (v1 < v2) {
- return -1;
- }
-
- return +1;
- }
- return this.remaining() - that.remaining();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- StringBuilder buf = new StringBuilder();
- if (isDirect()) {
- buf.append("DirectBuffer");
- } else {
- buf.append("HeapBuffer");
- }
- buf.append("[pos=");
- buf.append(position());
- buf.append(" lim=");
- buf.append(limit());
- buf.append(" cap=");
- buf.append(capacity());
- buf.append(": ");
- buf.append(getHexDump(16));
- buf.append(']');
- return buf.toString();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer get(byte[] dst) {
- return get(dst, 0, dst.length);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer put(IoBuffer src) {
- return put(src.buf());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer put(byte[] src) {
- return put(src, 0, src.length);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getUnsignedShort() {
- return getShort() & 0xffff;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getUnsignedShort(int index) {
- return getShort(index) & 0xffff;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public long getUnsignedInt() {
- return getInt() & 0xffffffffL;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getMediumInt() {
- byte b1 = get();
- byte b2 = get();
- byte b3 = get();
- if (ByteOrder.BIG_ENDIAN.equals(order())) {
- return getMediumInt(b1, b2, b3);
- }
-
- return getMediumInt(b3, b2, b1);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getUnsignedMediumInt() {
- int b1 = getUnsigned();
- int b2 = getUnsigned();
- int b3 = getUnsigned();
- if (ByteOrder.BIG_ENDIAN.equals(order())) {
- return b1 << 16 | b2 << 8 | b3;
- }
-
- return b3 << 16 | b2 << 8 | b1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getMediumInt(int index) {
- byte b1 = get(index);
- byte b2 = get(index + 1);
- byte b3 = get(index + 2);
- if (ByteOrder.BIG_ENDIAN.equals(order())) {
- return getMediumInt(b1, b2, b3);
- }
-
- return getMediumInt(b3, b2, b1);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getUnsignedMediumInt(int index) {
- int b1 = getUnsigned(index);
- int b2 = getUnsigned(index + 1);
- int b3 = getUnsigned(index + 2);
-
- if (ByteOrder.BIG_ENDIAN.equals(order())) {
- return b1 << 16 | b2 << 8 | b3;
- }
-
- return b3 << 16 | b2 << 8 | b1;
- }
-
- private int getMediumInt(byte b1, byte b2, byte b3) {
- int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff;
- // Check to see if the medium int is negative (high bit in b1 set)
- if ((b1 & 0x80) == 0x80) {
- // Make the the whole int negative
- ret |= 0xff000000;
- }
- return ret;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putMediumInt(int value) {
- byte b1 = (byte) (value >> 16);
- byte b2 = (byte) (value >> 8);
- byte b3 = (byte) value;
-
- if (ByteOrder.BIG_ENDIAN.equals(order())) {
- put(b1).put(b2).put(b3);
- } else {
- put(b3).put(b2).put(b1);
- }
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putMediumInt(int index, int value) {
- byte b1 = (byte) (value >> 16);
- byte b2 = (byte) (value >> 8);
- byte b3 = (byte) value;
-
- if (ByteOrder.BIG_ENDIAN.equals(order())) {
- put(index, b1).put(index + 1, b2).put(index + 2, b3);
- } else {
- put(index, b3).put(index + 1, b2).put(index + 2, b1);
- }
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public long getUnsignedInt(int index) {
- return getInt(index) & 0xffffffffL;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public InputStream asInputStream() {
- return new InputStream() {
- @Override
- public int available() {
- return AbstractIoBuffer.this.remaining();
- }
-
- @Override
- public synchronized void mark(int readlimit) {
- AbstractIoBuffer.this.mark();
- }
-
- @Override
- public boolean markSupported() {
- return true;
- }
-
- @Override
- public int read() {
- if (AbstractIoBuffer.this.hasRemaining()) {
- return AbstractIoBuffer.this.get() & 0xff;
- }
-
- return -1;
- }
-
- @Override
- public int read(byte[] b, int off, int len) {
- int remaining = AbstractIoBuffer.this.remaining();
- if (remaining > 0) {
- int readBytes = Math.min(remaining, len);
- AbstractIoBuffer.this.get(b, off, readBytes);
- return readBytes;
- }
-
- return -1;
- }
-
- @Override
- public synchronized void reset() {
- AbstractIoBuffer.this.reset();
- }
-
- @Override
- public long skip(long n) {
- int bytes;
- if (n > Integer.MAX_VALUE) {
- bytes = AbstractIoBuffer.this.remaining();
- } else {
- bytes = Math.min(AbstractIoBuffer.this.remaining(), (int) n);
- }
- AbstractIoBuffer.this.skip(bytes);
- return bytes;
- }
- };
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public OutputStream asOutputStream() {
- return new OutputStream() {
- @Override
- public void write(byte[] b, int off, int len) {
- AbstractIoBuffer.this.put(b, off, len);
- }
-
- @Override
- public void write(int b) {
- AbstractIoBuffer.this.put((byte) b);
- }
- };
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getHexDump() {
- return this.getHexDump(Integer.MAX_VALUE);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getHexDump(int lengthLimit) {
- return IoBufferHexDumper.getHexdump(this, lengthLimit);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getString(CharsetDecoder decoder) throws CharacterCodingException \
{
- if (!hasRemaining()) {
- return "";
- }
-
- boolean utf16 =
- decoder.charset().equals(StandardCharsets.UTF_16) ||
- decoder.charset().equals(StandardCharsets.UTF_16BE) ||
- decoder.charset().equals(StandardCharsets.UTF_16LE);
-
- int oldPos = position();
- int oldLimit = limit();
- int end = -1;
- int newPos;
-
- if (!utf16) {
- end = indexOf((byte) 0x00);
- if (end < 0) {
- newPos = end = oldLimit;
- } else {
- newPos = end + 1;
- }
- } else {
- int i = oldPos;
- for (;;) {
- boolean wasZero = get(i) == 0;
- i++;
-
- if (i >= oldLimit) {
- break;
- }
-
- if (get(i) != 0) {
- i++;
- if (i >= oldLimit) {
- break;
- }
-
- continue;
- }
-
- if (wasZero) {
- end = i - 1;
- break;
- }
- }
-
- if (end < 0) {
- newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE);
- } else {
- if (end + 2 <= oldLimit) {
- newPos = end + 2;
- } else {
- newPos = end;
- }
- }
- }
-
- if (oldPos == end) {
- position(newPos);
- return "";
- }
-
- limit(end);
- decoder.reset();
-
- int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + \
1;
- CharBuffer out = CharBuffer.allocate(expectedLength);
- for (;;) {
- CoderResult cr;
- if (hasRemaining()) {
- cr = decoder.decode(buf(), out, true);
- } else {
- cr = decoder.flush(out);
- }
-
- if (cr.isUnderflow()) {
- break;
- }
-
- if (cr.isOverflow()) {
- CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
- out.flip();
- o.put(out);
- out = o;
- continue;
- }
-
- if (cr.isError()) {
- // Revert the buffer back to the previous state.
- limit(oldLimit);
- position(oldPos);
- cr.throwException();
- }
- }
-
- limit(oldLimit);
- position(newPos);
- return out.flip().toString();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getString(int fieldSize, CharsetDecoder decoder) throws \
CharacterCodingException {
- checkFieldSize(fieldSize);
-
- if (fieldSize == 0) {
- return "";
- }
-
- if (!hasRemaining()) {
- return "";
- }
-
- boolean utf16 = decoder.charset().equals(StandardCharsets.UTF_16) ||
- decoder.charset().equals(StandardCharsets.UTF_16BE) ||
- decoder.charset().equals(StandardCharsets.UTF_16LE);
-
- if (utf16 && (fieldSize & 1) != 0) {
- throw new IllegalArgumentException("fieldSize is not even.");
- }
-
- int oldPos = position();
- int oldLimit = limit();
- int end = oldPos + fieldSize;
-
- if (oldLimit < end) {
- throw new BufferUnderflowException();
- }
-
- int i;
-
- if (!utf16) {
- for (i = oldPos; i < end; i++) {
- if (get(i) == 0) {
- break;
- }
- }
-
- if (i == end) {
- limit(end);
- } else {
- limit(i);
- }
- } else {
- for (i = oldPos; i < end; i += 2) {
- if (get(i) == 0 && get(i + 1) == 0) {
- break;
- }
- }
-
- if (i == end) {
- limit(end);
- } else {
- limit(i);
- }
- }
-
- if (!hasRemaining()) {
- limit(oldLimit);
- position(end);
- return "";
- }
- decoder.reset();
-
- int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + \
1;
- CharBuffer out = CharBuffer.allocate(expectedLength);
- for (;;) {
- CoderResult cr;
- if (hasRemaining()) {
- cr = decoder.decode(buf(), out, true);
- } else {
- cr = decoder.flush(out);
- }
-
- if (cr.isUnderflow()) {
- break;
- }
-
- if (cr.isOverflow()) {
- CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
- out.flip();
- o.put(out);
- out = o;
- continue;
- }
-
- if (cr.isError()) {
- // Revert the buffer back to the previous state.
- limit(oldLimit);
- position(oldPos);
- cr.throwException();
- }
- }
-
- limit(oldLimit);
- position(end);
- return out.flip().toString();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putString(CharSequence val, CharsetEncoder encoder) throws \
CharacterCodingException {
- if (val.length() == 0) {
- return this;
- }
-
- CharBuffer in = CharBuffer.wrap(val);
- encoder.reset();
-
- int expandedState = 0;
-
- for (;;) {
- CoderResult cr;
- if (in.hasRemaining()) {
- cr = encoder.encode(in, buf(), true);
- } else {
- cr = encoder.flush(buf());
- }
-
- if (cr.isUnderflow()) {
- break;
- }
- if (cr.isOverflow()) {
- if (isAutoExpand()) {
- switch (expandedState) {
- case 0:
- autoExpand((int) Math.ceil(in.remaining() * \
encoder.averageBytesPerChar()));
- expandedState++;
- break;
- case 1:
- autoExpand((int) Math.ceil(in.remaining() * \
encoder.maxBytesPerChar()));
- expandedState++;
- break;
- default:
- throw new RuntimeException("Expanded by "
- + (int) Math.ceil(in.remaining() * \
encoder.maxBytesPerChar())
- + " but that wasn't enough for '" + val + "'");
- }
- continue;
- }
- } else {
- expandedState = 0;
- }
- cr.throwException();
- }
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder \
encoder) throws CharacterCodingException {
- checkFieldSize(fieldSize);
-
- if (fieldSize == 0) {
- return this;
- }
-
- autoExpand(fieldSize);
-
- boolean utf16 = encoder.charset().equals(StandardCharsets.UTF_16) ||
- encoder.charset().equals(StandardCharsets.UTF_16BE) ||
- encoder.charset().equals(StandardCharsets.UTF_16LE);
-
-
- if (utf16 && (fieldSize & 1) != 0) {
- throw new IllegalArgumentException("fieldSize is not even.");
- }
-
- int oldLimit = limit();
- int end = position() + fieldSize;
-
- if (oldLimit < end) {
- throw new BufferOverflowException();
- }
-
- if (val.length() == 0) {
- if (!utf16) {
- put((byte) 0x00);
- } else {
- put((byte) 0x00);
- put((byte) 0x00);
- }
- position(end);
- return this;
- }
-
- CharBuffer in = CharBuffer.wrap(val);
- limit(end);
- encoder.reset();
-
- for (;;) {
- CoderResult cr;
- if (in.hasRemaining()) {
- cr = encoder.encode(in, buf(), true);
- } else {
- cr = encoder.flush(buf());
- }
-
- if (cr.isUnderflow() || cr.isOverflow()) {
- break;
- }
- cr.throwException();
- }
-
- limit(oldLimit);
-
- if (position() < end) {
- if (!utf16) {
- put((byte) 0x00);
- } else {
- put((byte) 0x00);
- put((byte) 0x00);
- }
- }
-
- position(end);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getPrefixedString(CharsetDecoder decoder) throws \
CharacterCodingException {
- return getPrefixedString(2, decoder);
- }
-
- /**
- * Reads a string which has a length field before the actual
- * encoded string, using the specified <code>decoder</code> and returns it.
- *
- * @param prefixLength the length of the length field (1, 2, or 4)
- * @param decoder the decoder to use for decoding the string
- * @return the prefixed string
- * @throws CharacterCodingException when decoding fails
- * @throws BufferUnderflowException when there is not enough data available
- */
- @Override
- public String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws \
CharacterCodingException {
- if (!prefixedDataAvailable(prefixLength)) {
- throw new BufferUnderflowException();
- }
-
- int fieldSize = 0;
-
- switch (prefixLength) {
- case 1:
- fieldSize = getUnsigned();
- break;
- case 2:
- fieldSize = getUnsignedShort();
- break;
- case 4:
- fieldSize = getInt();
- break;
- }
-
- if (fieldSize == 0) {
- return "";
- }
-
- boolean utf16 = decoder.charset().equals(StandardCharsets.UTF_16) ||
- decoder.charset().equals(StandardCharsets.UTF_16BE) ||
- decoder.charset().equals(StandardCharsets.UTF_16LE);
-
-
- if (utf16 && (fieldSize & 1) != 0) {
- throw new BufferDataException("fieldSize is not even for a UTF-16 \
string.");
- }
-
- int oldLimit = limit();
- int end = position() + fieldSize;
-
- if (oldLimit < end) {
- throw new BufferUnderflowException();
- }
-
- limit(end);
- decoder.reset();
-
- int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + \
1;
- CharBuffer out = CharBuffer.allocate(expectedLength);
- for (;;) {
- CoderResult cr;
- if (hasRemaining()) {
- cr = decoder.decode(buf(), out, true);
- } else {
- cr = decoder.flush(out);
- }
-
- if (cr.isUnderflow()) {
- break;
- }
-
- if (cr.isOverflow()) {
- CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
- out.flip();
- o.put(out);
- out = o;
- continue;
- }
-
- cr.throwException();
- }
-
- limit(oldLimit);
- position(end);
- return out.flip().toString();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) \
throws CharacterCodingException {
- return putPrefixedString(in, 2, 0, encoder);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putPrefixedString(CharSequence in, int prefixLength, \
CharsetEncoder encoder)
- throws CharacterCodingException {
- return putPrefixedString(in, prefixLength, 0, encoder);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int \
padding, CharsetEncoder encoder)
- throws CharacterCodingException {
- return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putPrefixedString(CharSequence val, int prefixLength, int \
padding, byte padValue,
- CharsetEncoder encoder) throws CharacterCodingException {
- int maxLength;
- switch (prefixLength) {
- case 1:
- maxLength = 255;
- break;
- case 2:
- maxLength = 65535;
- break;
- case 4:
- maxLength = Integer.MAX_VALUE;
- break;
- default:
- throw new IllegalArgumentException("prefixLength: " + prefixLength);
- }
-
- if (val.length() > maxLength) {
- throw new IllegalArgumentException("The specified string is too long.");
- }
- if (val.length() == 0) {
- switch (prefixLength) {
- case 1:
- put((byte) 0);
- break;
- case 2:
- putShort((short) 0);
- break;
- case 4:
- putInt(0);
- break;
- }
- return this;
- }
-
- int padMask;
- switch (padding) {
- case 0:
- case 1:
- padMask = 0;
- break;
- case 2:
- padMask = 1;
- break;
- case 4:
- padMask = 3;
- break;
- default:
- throw new IllegalArgumentException("padding: " + padding);
- }
-
- CharBuffer in = CharBuffer.wrap(val);
- skip(prefixLength); // make a room for the length field
- int oldPos = position();
- encoder.reset();
-
- int expandedState = 0;
-
- for (;;) {
- CoderResult cr;
- if (in.hasRemaining()) {
- cr = encoder.encode(in, buf(), true);
- } else {
- cr = encoder.flush(buf());
- }
-
- if (position() - oldPos > maxLength) {
- throw new IllegalArgumentException("The specified string is too \
long.");
- }
-
- if (cr.isUnderflow()) {
- break;
- }
- if (cr.isOverflow()) {
- if (isAutoExpand()) {
- switch (expandedState) {
- case 0:
- autoExpand((int) Math.ceil(in.remaining() * \
encoder.averageBytesPerChar()));
- expandedState++;
- break;
- case 1:
- autoExpand((int) Math.ceil(in.remaining() * \
encoder.maxBytesPerChar()));
- expandedState++;
- break;
- default:
- throw new RuntimeException("Expanded by "
- + (int) Math.ceil(in.remaining() * \
encoder.maxBytesPerChar())
- + " but that wasn't enough for '" + val + "'");
- }
- continue;
- }
- } else {
- expandedState = 0;
- }
- cr.throwException();
- }
-
- // Write the length field
- fill(padValue, padding - (position() - oldPos & padMask));
- int length = position() - oldPos;
- switch (prefixLength) {
- case 1:
- put(oldPos - 1, (byte) length);
- break;
- case 2:
- putShort(oldPos - 2, (short) length);
- break;
- case 4:
- putInt(oldPos - 4, length);
- break;
- }
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Object getObject() throws ClassNotFoundException {
- return getObject(Thread.currentThread().getContextClassLoader());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Object getObject(final ClassLoader classLoader) throws \
ClassNotFoundException {
- if (!prefixedDataAvailable(4)) {
- throw new BufferUnderflowException();
- }
-
- int length = getInt();
- if (length <= 4) {
- throw new BufferDataException("Object length should be greater than 4: " \
+ length);
- }
-
- int oldLimit = limit();
- limit(position() + length);
-
- try (ObjectInputStream in = new ObjectInputStream(asInputStream()) {
- @Override
- protected ObjectStreamClass readClassDescriptor() throws \
IOException, ClassNotFoundException {
- int type = read();
- if (type < 0) {
- throw new EOFException();
- }
- switch (type) {
- case 0: // NON-Serializable class or Primitive types
- return super.readClassDescriptor();
- case 1: // Serializable class
- String className = readUTF();
- Class<?> clazz = Class.forName(className, true, \
classLoader);
- return ObjectStreamClass.lookup(clazz);
- default:
- throw new StreamCorruptedException("Unexpected class \
descriptor type: " + type);
- }
- }
-
- @Override
- protected Class<?> resolveClass(ObjectStreamClass desc) throws \
IOException, ClassNotFoundException {
- Class<?> clazz = desc.forClass();
-
- if (clazz == null) {
- String name = desc.getName();
- try {
- return Class.forName(name, false, classLoader);
- } catch (ClassNotFoundException ex) {
- return super.resolveClass(desc);
- }
- } else {
- return clazz;
- }
- }
- }) {
- return in.readObject();
- } catch (IOException e) {
- throw new BufferDataException(e);
- } finally {
- limit(oldLimit);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putObject(Object o) {
- int oldPos = position();
- skip(4); // Make a room for the length field.
-
- try (ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) {
- @Override
- protected void writeClassDescriptor(ObjectStreamClass desc) throws \
IOException {
- Class<?> clazz = desc.forClass();
-
- if (clazz.isArray() || clazz.isPrimitive() || \
!Serializable.class.isAssignableFrom(clazz)) {
- write(0);
- super.writeClassDescriptor(desc);
- } else {
- // Serializable class
- write(1);
- writeUTF(desc.getName());
- }
- }
- }) {
- out.writeObject(o);
- out.flush();
- } catch (IOException e) {
- throw new BufferDataException(e);
- }
-
- // Fill the length field
- int newPos = position();
- position(oldPos);
- putInt(newPos - oldPos - 4);
- position(newPos);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean prefixedDataAvailable(int prefixLength) {
- return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
- if (remaining() < prefixLength) {
- return false;
- }
-
- int dataLength;
- switch (prefixLength) {
- case 1:
- dataLength = getUnsigned(position());
- break;
- case 2:
- dataLength = getUnsignedShort(position());
- break;
- case 4:
- dataLength = getInt(position());
- break;
- default:
- throw new IllegalArgumentException("prefixLength: " + prefixLength);
- }
-
- if (dataLength < 0 || dataLength > maxDataLength) {
- throw new BufferDataException("dataLength: " + dataLength);
- }
-
- return remaining() - prefixLength >= dataLength;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int indexOf(byte b) {
- if (hasArray()) {
- int arrayOffset = arrayOffset();
- int beginPos = arrayOffset + position();
- int limit = arrayOffset + limit();
- byte[] array = array();
-
- for (int i = beginPos; i < limit; i++) {
- if (array[i] == b) {
- return i - arrayOffset;
- }
- }
- } else {
- int beginPos = position();
- int limit = limit();
-
- for (int i = beginPos; i < limit; i++) {
- if (get(i) == b) {
- return i;
- }
- }
- }
-
- return -1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer skip(int size) {
- autoExpand(size);
- return position(position() + size);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer fill(byte value, int size) {
- autoExpand(size);
- int q = size >>> 3;
- int r = size & 7;
-
- if (q > 0) {
- int intValue = value & 0x000000FF | ( value << 8 ) & 0x0000FF00 | ( \
value << 16 ) & 0x00FF0000 | value << 24;
- long longValue = intValue & 0x00000000FFFFFFFFL | (long)intValue << \
32;
-
- for (int i = q; i > 0; i--) {
- putLong(longValue);
- }
- }
-
- q = r >>> 2;
- r = r & 3;
-
- if (q > 0) {
- int intValue = value & 0x000000FF | ( value << 8 ) & 0x0000FF00 \
| ( value << 16 ) & 0x00FF0000 | value << 24;
- putInt(intValue);
- }
-
- q = r >> 1;
- r = r & 1;
-
- if (q > 0) {
- short shortValue = (short) (value & 0x000FF | value << 8);
- putShort(shortValue);
- }
-
- if (r > 0) {
- put(value);
- }
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer fillAndReset(byte value, int size) {
- autoExpand(size);
- int pos = position();
- try {
- fill(value, size);
- } finally {
- position(pos);
- }
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer fill(int size) {
- autoExpand(size);
- int q = size >>> 3;
- int r = size & 7;
-
- for (int i = q; i > 0; i--) {
- putLong(0L);
- }
-
- q = r >>> 2;
- r = r & 3;
-
- if (q > 0) {
- putInt(0);
- }
-
- q = r >> 1;
- r = r & 1;
-
- if (q > 0) {
- putShort((short) 0);
- }
-
- if (r > 0) {
- put((byte) 0);
- }
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer fillAndReset(int size) {
- autoExpand(size);
- int pos = position();
- try {
- fill(size);
- } finally {
- position(pos);
- }
-
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> E getEnum(Class<E> enumClass) {
- return toEnum(enumClass, getUnsigned());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> E getEnum(int index, Class<E> enumClass) {
- return toEnum(enumClass, getUnsigned(index));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> E getEnumShort(Class<E> enumClass) {
- return toEnum(enumClass, getUnsignedShort());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> E getEnumShort(int index, Class<E> enumClass) {
- return toEnum(enumClass, getUnsignedShort(index));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> E getEnumInt(Class<E> enumClass) {
- return toEnum(enumClass, getInt());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> E getEnumInt(int index, Class<E> enumClass) {
- return toEnum(enumClass, getInt(index));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putEnum(Enum<?> e) {
- if (e.ordinal() > BYTE_MASK) {
- throw new IllegalArgumentException(enumConversionErrorMessage(e, \
"byte"));
- }
- return put((byte) e.ordinal());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putEnum(int index, Enum<?> e) {
- if (e.ordinal() > BYTE_MASK) {
- throw new IllegalArgumentException(enumConversionErrorMessage(e, \
"byte"));
- }
- return put(index, (byte) e.ordinal());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putEnumShort(Enum<?> e) {
- if (e.ordinal() > SHORT_MASK) {
- throw new IllegalArgumentException(enumConversionErrorMessage(e, \
"short"));
- }
- return putShort((short) e.ordinal());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putEnumShort(int index, Enum<?> e) {
- if (e.ordinal() > SHORT_MASK) {
- throw new IllegalArgumentException(enumConversionErrorMessage(e, \
"short"));
- }
- return putShort(index, (short) e.ordinal());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putEnumInt(Enum<?> e) {
- return putInt(e.ordinal());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer putEnumInt(int index, Enum<?> e) {
- return putInt(index, e.ordinal());
- }
-
- private <E> E toEnum(Class<E> enumClass, int i) {
- E[] enumConstants = enumClass.getEnumConstants();
- if (i > enumConstants.length) {
- throw new IndexOutOfBoundsException(String.format(
- "%d is too large of an ordinal to convert to the enum %s", i, \
enumClass.getName()));
- }
- return enumConstants[i];
- }
-
- private String enumConversionErrorMessage(Enum<?> e, String type) {
- return String.format("%s.%s has an ordinal value too large for a %s", \
e.getClass().getName(), e.name(), type);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> Set<E> getEnumSet(Class<E> enumClass) {
- return toEnumSet(enumClass, get() & BYTE_MASK);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> Set<E> getEnumSet(int index, Class<E> enumClass) {
- return toEnumSet(enumClass, get(index) & BYTE_MASK);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> Set<E> getEnumSetShort(Class<E> enumClass) {
- return toEnumSet(enumClass, getShort() & SHORT_MASK);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> Set<E> getEnumSetShort(int index, Class<E> enumClass) \
{
- return toEnumSet(enumClass, getShort(index) & SHORT_MASK);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> Set<E> getEnumSetInt(Class<E> enumClass) {
- return toEnumSet(enumClass, getInt() & INT_MASK);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> Set<E> getEnumSetInt(int index, Class<E> enumClass) {
- return toEnumSet(enumClass, getInt(index) & INT_MASK);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> Set<E> getEnumSetLong(Class<E> enumClass) {
- return toEnumSet(enumClass, getLong());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> Set<E> getEnumSetLong(int index, Class<E> enumClass) \
{
- return toEnumSet(enumClass, getLong(index));
- }
-
- private <E extends Enum<E>> EnumSet<E> toEnumSet(Class<E> clazz, long vector) {
- EnumSet<E> set = EnumSet.noneOf(clazz);
- long mask = 1;
- for (E e : clazz.getEnumConstants()) {
- if ((mask & vector) == mask) {
- set.add(e);
- }
- mask <<= 1;
- }
- return set;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set) {
- long vector = toLong(set);
- if ((vector & ~BYTE_MASK) != 0) {
- throw new IllegalArgumentException("The enum set is too large to fit in \
a byte: " + set);
- }
- return put((byte) vector);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set) {
- long vector = toLong(set);
- if ((vector & ~BYTE_MASK) != 0) {
- throw new IllegalArgumentException("The enum set is too large to fit in \
a byte: " + set);
- }
- return put(index, (byte) vector);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set) {
- long vector = toLong(set);
- if ((vector & ~SHORT_MASK) != 0) {
- throw new IllegalArgumentException("The enum set is too large to fit in \
a short: " + set);
- }
- return putShort((short) vector);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> IoBuffer putEnumSetShort(int index, Set<E> set) {
- long vector = toLong(set);
- if ((vector & ~SHORT_MASK) != 0) {
- throw new IllegalArgumentException("The enum set is too large to fit in \
a short: " + set);
- }
- return putShort(index, (short) vector);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set) {
- long vector = toLong(set);
- if ((vector & ~INT_MASK) != 0) {
- throw new IllegalArgumentException("The enum set is too large to fit in \
an int: " + set);
- }
- return putInt((int) vector);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> IoBuffer putEnumSetInt(int index, Set<E> set) {
- long vector = toLong(set);
- if ((vector & ~INT_MASK) != 0) {
- throw new IllegalArgumentException("The enum set is too large to fit in \
an int: " + set);
- }
- return putInt(index, (int) vector);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set) {
- return putLong(toLong(set));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <E extends Enum<E>> IoBuffer putEnumSetLong(int index, Set<E> set) {
- return putLong(index, toLong(set));
- }
-
- private <E extends Enum<E>> long toLong(Set<E> set) {
- long vector = 0;
- for (E e : set) {
- if (e.ordinal() >= Long.SIZE) {
- throw new IllegalArgumentException("The enum set is too large to fit \
in a bit vector: " + set);
- }
- vector |= 1L << e.ordinal();
- }
- return vector;
- }
-
- /**
- * This method forwards the call to {@link #expand(int)} only when
- * <tt>autoExpand</tt> property is <tt>true</tt>.
- */
- private IoBuffer autoExpand(int expectedRemaining) {
- if (isAutoExpand()) {
- expand(expectedRemaining, true);
- }
- return this;
- }
-
- /**
- * This method forwards the call to {@link #expand(int)} only when
- * <tt>autoExpand</tt> property is <tt>true</tt>.
- */
- private IoBuffer autoExpand(int pos, int expectedRemaining) {
- if (isAutoExpand()) {
- expand(pos, expectedRemaining, true);
- }
- return this;
- }
-
- private static void checkFieldSize(int fieldSize) {
- if (fieldSize < 0) {
- throw new IllegalArgumentException("fieldSize cannot be negative: " + \
fieldSize);
- }
- }
+ /** Tells if a buffer has been created from an existing buffer */
+ private final boolean derived;
+
+ /** A flag set to true if the buffer can extend automatically */
+ private boolean autoExpand;
+
+ /** A flag set to true if the buffer can shrink automatically */
+ private boolean autoShrink;
+
+ /** Tells if a buffer can be expanded */
+ private boolean recapacityAllowed = true;
+
+ /** The minimum number of bytes the IoBuffer can hold */
+ private int minimumCapacity;
+
+ /** A mask for a byte */
+ private static final long BYTE_MASK = 0xFFL;
+
+ /** A mask for a short */
+ private static final long SHORT_MASK = 0xFFFFL;
+
+ /** A mask for an int */
+ private static final long INT_MASK = 0xFFFFFFFFL;
+
+ /**
+ * We don't have any access to Buffer.markValue(), so we need to track it down,
+ * which will cause small extra overhead.
+ */
+ private int mark = -1;
+
+ /**
+ * Creates a new parent buffer.
+ *
+ * @param allocator The allocator to use to create new buffers
+ * @param initialCapacity The initial buffer capacity when created
+ */
+ protected AbstractIoBuffer(IoBufferAllocator allocator, int initialCapacity) {
+ setAllocator(allocator);
+ this.recapacityAllowed = true;
+ this.derived = false;
+ this.minimumCapacity = initialCapacity;
+ }
+
+ /**
+ * Creates a new derived buffer. A derived buffer uses an existing buffer
+ * properties - the allocator and capacity -.
+ *
+ * @param parent The buffer we get the properties from
+ */
+ protected AbstractIoBuffer(AbstractIoBuffer parent) {
+ setAllocator(IoBuffer.getAllocator());
+ this.recapacityAllowed = false;
+ this.derived = true;
+ this.minimumCapacity = parent.minimumCapacity;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final boolean isDirect() {
+ return buf().isDirect();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final boolean isReadOnly() {
+ return buf().isReadOnly();
+ }
+
+ /**
+ * Sets the underlying NIO buffer instance.
+ *
+ * @param newBuf The buffer to store within this IoBuffer
+ */
+ protected abstract void buf(ByteBuffer newBuf);
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int minimumCapacity() {
+ return minimumCapacity;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer minimumCapacity(int minimumCapacity) {
+ if (minimumCapacity < 0) {
+ throw new IllegalArgumentException("minimumCapacity: " + minimumCapacity);
+ }
+ this.minimumCapacity = minimumCapacity;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int capacity() {
+ return buf().capacity();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer capacity(int newCapacity) {
+ if (!recapacityAllowed) {
+ throw new IllegalStateException("Derived buffers and their parent can't be \
expanded."); + }
+
+ // Allocate a new buffer and transfer all settings to it.
+ if (newCapacity > capacity()) {
+ // Expand:
+ //// Save the state.
+ int pos = position();
+ int limit = limit();
+ ByteOrder bo = order();
+
+ //// Reallocate.
+ ByteBuffer oldBuf = buf();
+ ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect());
+ oldBuf.clear();
+ newBuf.put(oldBuf);
+ buf(newBuf);
+
+ //// Restore the state.
+ buf().limit(limit);
+ if (mark >= 0) {
+ buf().position(mark);
+ buf().mark();
+ }
+ buf().position(pos);
+ buf().order(bo);
+ }
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final boolean isAutoExpand() {
+ return autoExpand && recapacityAllowed;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final boolean isAutoShrink() {
+ return autoShrink && recapacityAllowed;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final boolean isDerived() {
+ return derived;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer setAutoExpand(boolean autoExpand) {
+ if (!recapacityAllowed) {
+ throw new IllegalStateException("Derived buffers and their parent can't be \
expanded."); + }
+ this.autoExpand = autoExpand;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer setAutoShrink(boolean autoShrink) {
+ if (!recapacityAllowed) {
+ throw new IllegalStateException("Derived buffers and their parent can't be \
shrinked."); + }
+ this.autoShrink = autoShrink;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer expand(int expectedRemaining) {
+ return expand(position(), expectedRemaining, false);
+ }
+
+ private IoBuffer expand(int expectedRemaining, boolean autoExpand) {
+ return expand(position(), expectedRemaining, autoExpand);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer expand(int pos, int expectedRemaining) {
+ return expand(pos, expectedRemaining, false);
+ }
+
+ private IoBuffer expand(int pos, int expectedRemaining, boolean autoExpand) {
+ if (!recapacityAllowed) {
+ throw new IllegalStateException("Derived buffers and their parent can't be \
expanded."); + }
+
+ int end = pos + expectedRemaining;
+ int newCapacity;
+
+ if (autoExpand) {
+ newCapacity = IoBuffer.normalizeCapacity(end);
+ } else {
+ newCapacity = end;
+ }
+ if (newCapacity > capacity()) {
+ // The buffer needs expansion.
+ capacity(newCapacity);
+ }
+
+ if (end > limit()) {
+ // We call limit() directly to prevent StackOverflowError
+ buf().limit(end);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer shrink() {
+
+ if (!recapacityAllowed) {
+ throw new IllegalStateException("Derived buffers and their parent can't be \
expanded."); + }
+
+ int position = position();
+ int capacity = capacity();
+ int limit = limit();
+
+ if (capacity == limit) {
+ return this;
+ }
+
+ int newCapacity = capacity;
+ int minCapacity = Math.max(minimumCapacity, limit);
+
+ for (;;) {
+ if (newCapacity >>> 1 < minCapacity) {
+ break;
+ }
+
+ newCapacity >>>= 1;
+
+ if (minCapacity == 0) {
+ break;
+ }
+ }
+
+ newCapacity = Math.max(minCapacity, newCapacity);
+
+ if (newCapacity == capacity) {
+ return this;
+ }
+
+ // Shrink and compact:
+ //// Save the state.
+ ByteOrder bo = order();
+
+ //// Reallocate.
+ ByteBuffer oldBuf = buf();
+ ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect());
+ oldBuf.position(0);
+ oldBuf.limit(limit);
+ newBuf.put(oldBuf);
+ buf(newBuf);
+
+ //// Restore the state.
+ buf().position(position);
+ buf().limit(limit);
+ buf().order(bo);
+ mark = -1;
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int position() {
+ return buf().position();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer position(int newPosition) {
+ autoExpand(newPosition, 0);
+ buf().position(newPosition);
+
+ if (mark > newPosition) {
+ mark = -1;
+ }
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int limit() {
+ return buf().limit();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer limit(int newLimit) {
+ autoExpand(newLimit, 0);
+ buf().limit(newLimit);
+ if (mark > newLimit) {
+ mark = -1;
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer mark() {
+ ByteBuffer byteBuffer = buf();
+ byteBuffer.mark();
+ mark = byteBuffer.position();
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int markValue() {
+ return mark;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer reset() {
+ buf().reset();
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer clear() {
+ buf().clear();
+ mark = -1;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer sweep() {
+ clear();
+ return fillAndReset(remaining());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer sweep(byte value) {
+ clear();
+ return fillAndReset(value, remaining());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer flip() {
+ buf().flip();
+ mark = -1;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer rewind() {
+ buf().rewind();
+ mark = -1;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int remaining() {
+ ByteBuffer byteBuffer = buf();
+
+ return byteBuffer.limit() - byteBuffer.position();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final boolean hasRemaining() {
+ ByteBuffer byteBuffer = buf();
+
+ return byteBuffer.limit() > byteBuffer.position();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final byte get() {
+ return buf().get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final short getUnsigned() {
+ return (short) (get() & 0xff);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer put(byte b) {
+ autoExpand(1);
+ buf().put(b);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putUnsigned(byte value) {
+ autoExpand(1);
+ buf().put((byte) (value & 0xff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putUnsigned(int index, byte value) {
+ autoExpand(index, 1);
+ buf().put(index, (byte) (value & 0xff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putUnsigned(short value) {
+ autoExpand(1);
+ buf().put((byte) (value & 0x00ff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putUnsigned(int index, short value) {
+ autoExpand(index, 1);
+ buf().put(index, (byte) (value & 0x00ff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putUnsigned(int value) {
+ autoExpand(1);
+ buf().put((byte) (value & 0x000000ff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putUnsigned(int index, int value) {
+ autoExpand(index, 1);
+ buf().put(index, (byte) (value & 0x000000ff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putUnsigned(long value) {
+ autoExpand(1);
+ buf().put((byte) (value & 0x00000000000000ffL));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putUnsigned(int index, long value) {
+ autoExpand(index, 1);
+ buf().put(index, (byte) (value & 0x00000000000000ffL));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final byte get(int index) {
+ return buf().get(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final short getUnsigned(int index) {
+ return (short) (get(index) & 0xff);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer put(int index, byte b) {
+ autoExpand(index, 1);
+ buf().put(index, b);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer get(byte[] dst, int offset, int length) {
+ buf().get(dst, offset, length);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer put(ByteBuffer src) {
+ autoExpand(src.remaining());
+ buf().put(src);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer put(byte[] src, int offset, int length) {
+ autoExpand(length);
+ buf().put(src, offset, length);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer compact() {
+ int remaining = remaining();
+ int capacity = capacity();
+
+ if (capacity == 0) {
+ return this;
+ }
+
+ if (isAutoShrink() && remaining <= capacity >>> 2 && capacity > minimumCapacity) {
+ int newCapacity = capacity;
+ int minCapacity = Math.max(minimumCapacity, remaining << 1);
+ for (;;) {
+ if (newCapacity >>> 1 < minCapacity) {
+ break;
+ }
+ newCapacity >>>= 1;
+ }
+
+ newCapacity = Math.max(minCapacity, newCapacity);
+
+ if (newCapacity == capacity) {
+ return this;
+ }
+
+ // Shrink and compact:
+ //// Save the state.
+ ByteOrder bo = order();
+
+ //// Sanity check.
+ if (remaining > newCapacity) {
+ throw new IllegalStateException(
+ "The amount of the remaining bytes is greater than " + "the new capacity.");
+ }
+
+ //// Reallocate.
+ ByteBuffer oldBuf = buf();
+ ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect());
+ newBuf.put(oldBuf);
+ buf(newBuf);
+
+ //// Restore the state.
+ buf().order(bo);
+ } else {
+ buf().compact();
+ }
+ mark = -1;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final ByteOrder order() {
+ return buf().order();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer order(ByteOrder bo) {
+ buf().order(bo);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final char getChar() {
+ return buf().getChar();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putChar(char value) {
+ autoExpand(2);
+ buf().putChar(value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final char getChar(int index) {
+ return buf().getChar(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putChar(int index, char value) {
+ autoExpand(index, 2);
+ buf().putChar(index, value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final CharBuffer asCharBuffer() {
+ return buf().asCharBuffer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final short getShort() {
+ return buf().getShort();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putShort(short value) {
+ autoExpand(2);
+ buf().putShort(value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final short getShort(int index) {
+ return buf().getShort(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putShort(int index, short value) {
+ autoExpand(index, 2);
+ buf().putShort(index, value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final ShortBuffer asShortBuffer() {
+ return buf().asShortBuffer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int getInt() {
+ return buf().getInt();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putInt(int value) {
+ autoExpand(4);
+ buf().putInt(value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedInt(byte value) {
+ autoExpand(4);
+ buf().putInt(value & 0x00ff);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedInt(int index, byte value) {
+ autoExpand(index, 4);
+ buf().putInt(index, value & 0x00ff);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedInt(short value) {
+ autoExpand(4);
+ buf().putInt(value & 0x0000ffff);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedInt(int index, short value) {
+ autoExpand(index, 4);
+ buf().putInt(index, value & 0x0000ffff);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedInt(int value) {
+ return putInt(value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedInt(int index, int value) {
+ return putInt(index, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedInt(long value) {
+ autoExpand(4);
+ buf().putInt((int) (value & 0x00000000ffffffff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedInt(int index, long value) {
+ autoExpand(index, 4);
+ buf().putInt(index, (int) (value & 0x00000000ffffffffL));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedShort(byte value) {
+ autoExpand(2);
+ buf().putShort((short) (value & 0x00ff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedShort(int index, byte value) {
+ autoExpand(index, 2);
+ buf().putShort(index, (short) (value & 0x00ff));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedShort(short value) {
+ return putShort(value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedShort(int index, short value) {
+ return putShort(index, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedShort(int value) {
+ autoExpand(2);
+ buf().putShort((short) value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedShort(int index, int value) {
+ autoExpand(index, 2);
+ buf().putShort(index, (short) value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedShort(long value) {
+ autoExpand(2);
+ buf().putShort((short) (value));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putUnsignedShort(int index, long value) {
+ autoExpand(index, 2);
+ buf().putShort(index, (short) (value));
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int getInt(int index) {
+ return buf().getInt(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putInt(int index, int value) {
+ autoExpand(index, 4);
+ buf().putInt(index, value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IntBuffer asIntBuffer() {
+ return buf().asIntBuffer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final long getLong() {
+ return buf().getLong();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putLong(long value) {
+ autoExpand(8);
+ buf().putLong(value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final long getLong(int index) {
+ return buf().getLong(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putLong(int index, long value) {
+ autoExpand(index, 8);
+ buf().putLong(index, value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final LongBuffer asLongBuffer() {
+ return buf().asLongBuffer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final float getFloat() {
+ return buf().getFloat();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putFloat(float value) {
+ autoExpand(4);
+ buf().putFloat(value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final float getFloat(int index) {
+ return buf().getFloat(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putFloat(int index, float value) {
+ autoExpand(index, 4);
+ buf().putFloat(index, value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final FloatBuffer asFloatBuffer() {
+ return buf().asFloatBuffer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final double getDouble() {
+ return buf().getDouble();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putDouble(double value) {
+ autoExpand(8);
+ buf().putDouble(value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final double getDouble(int index) {
+ return buf().getDouble(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer putDouble(int index, double value) {
+ autoExpand(index, 8);
+ buf().putDouble(index, value);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final DoubleBuffer asDoubleBuffer() {
+ return buf().asDoubleBuffer();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer asReadOnlyBuffer() {
+ recapacityAllowed = false;
+ return asReadOnlyBuffer0();
+ }
+
+ /**
+ * Implement this method to return the unexpandable read only version of this
+ * buffer.
+ *
+ * @return the IoBoffer instance
+ */
+ protected abstract IoBuffer asReadOnlyBuffer0();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer duplicate() {
+ recapacityAllowed = false;
+ return duplicate0();
+ }
+
+ /**
+ * Implement this method to return the unexpandable duplicate of this buffer.
+ *
+ * @return the IoBoffer instance
+ */
+ protected abstract IoBuffer duplicate0();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer slice() {
+ recapacityAllowed = false;
+ return slice0();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer getSlice(int index, int length) {
+ if (length < 0) {
+ throw new IllegalArgumentException("length: " + length);
+ }
+
+ int pos = position();
+ int limit = limit();
+
+ if (index > limit) {
+ throw new IllegalArgumentException("index: " + index);
+ }
+
+ int endIndex = index + length;
+
+ if (endIndex > limit) {
+ throw new IndexOutOfBoundsException(
+ "index + length (" + endIndex + ") is greater " + "than limit (" + limit + \
")."); + }
+
+ clear();
+ limit(endIndex);
+ position(index);
+
+ IoBuffer slice = slice();
+ limit(limit);
+ position(pos);
+
+ return slice;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IoBuffer getSlice(int length) {
+ if (length < 0) {
+ throw new IllegalArgumentException("length: " + length);
+ }
+ int pos = position();
+ int limit = limit();
+ int nextPos = pos + length;
+ if (limit < nextPos) {
+ throw new IndexOutOfBoundsException(
+ "position + length (" + nextPos + ") is greater " + "than limit (" + limit + \
")."); + }
+
+ limit(pos + length);
+ IoBuffer slice = slice();
+ position(nextPos);
+ limit(limit);
+ return slice;
+ }
+
+ /**
+ * Implement this method to return the unexpandable slice of this buffer.
+ *
+ * @return the IoBoffer instance
+ */
+ protected abstract IoBuffer slice0();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ int h = 1;
+ int p = position();
+ for (int i = limit() - 1; i >= p; i--) {
+ h = 31 * h + get(i);
+ }
+ return h;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof IoBuffer)) {
+ return false;
+ }
+
+ IoBuffer that = (IoBuffer) o;
+ if (this.remaining() != that.remaining()) {
+ return false;
+ }
+
+ int p = this.position();
+ for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
+ byte v1 = this.get(i);
+ byte v2 = that.get(j);
+ if (v1 != v2) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(IoBuffer that) {
+ int n = this.position() + Math.min(this.remaining(), that.remaining());
+ for (int i = this.position(), j = that.position(); i < n; i++, j++) {
+ byte v1 = this.get(i);
+ byte v2 = that.get(j);
+ if (v1 == v2) {
+ continue;
+ }
+ if (v1 < v2) {
+ return -1;
+ }
+
+ return +1;
+ }
+ return this.remaining() - that.remaining();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ if (isDirect()) {
+ buf.append("DirectBuffer");
+ } else {
+ buf.append("HeapBuffer");
+ }
+ buf.append("[pos=");
+ buf.append(position());
+ buf.append(" lim=");
+ buf.append(limit());
+ buf.append(" cap=");
+ buf.append(capacity());
+ buf.append(": ");
+ buf.append(getHexDump(16));
+ buf.append(']');
+ return buf.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer get(byte[] dst) {
+ return get(dst, 0, dst.length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer put(IoBuffer src) {
+ return put(src.buf());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer put(byte[] src) {
+ return put(src, 0, src.length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getUnsignedShort() {
+ return getShort() & 0xffff;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getUnsignedShort(int index) {
+ return getShort(index) & 0xffff;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getUnsignedInt() {
+ return getInt() & 0xffffffffL;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getMediumInt() {
+ byte b1 = get();
+ byte b2 = get();
+ byte b3 = get();
+ if (ByteOrder.BIG_ENDIAN.equals(order())) {
+ return getMediumInt(b1, b2, b3);
+ }
+
+ return getMediumInt(b3, b2, b1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getUnsignedMediumInt() {
+ int b1 = getUnsigned();
+ int b2 = getUnsigned();
+ int b3 = getUnsigned();
+ if (ByteOrder.BIG_ENDIAN.equals(order())) {
+ return b1 << 16 | b2 << 8 | b3;
+ }
+
+ return b3 << 16 | b2 << 8 | b1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getMediumInt(int index) {
+ byte b1 = get(index);
+ byte b2 = get(index + 1);
+ byte b3 = get(index + 2);
+ if (ByteOrder.BIG_ENDIAN.equals(order())) {
+ return getMediumInt(b1, b2, b3);
+ }
+
+ return getMediumInt(b3, b2, b1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getUnsignedMediumInt(int index) {
+ int b1 = getUnsigned(index);
+ int b2 = getUnsigned(index + 1);
+ int b3 = getUnsigned(index + 2);
+
+ if (ByteOrder.BIG_ENDIAN.equals(order())) {
+ return b1 << 16 | b2 << 8 | b3;
+ }
+
+ return b3 << 16 | b2 << 8 | b1;
+ }
+
+ private int getMediumInt(byte b1, byte b2, byte b3) {
+ int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff;
+ // Check to see if the medium int is negative (high bit in b1 set)
+ if ((b1 & 0x80) == 0x80) {
+ // Make the the whole int negative
+ ret |= 0xff000000;
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putMediumInt(int value) {
+ byte b1 = (byte) (value >> 16);
+ byte b2 = (byte) (value >> 8);
+ byte b3 = (byte) value;
+
+ if (ByteOrder.BIG_ENDIAN.equals(order())) {
+ put(b1).put(b2).put(b3);
+ } else {
+ put(b3).put(b2).put(b1);
+ }
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putMediumInt(int index, int value) {
+ byte b1 = (byte) (value >> 16);
+ byte b2 = (byte) (value >> 8);
+ byte b3 = (byte) value;
+
+ if (ByteOrder.BIG_ENDIAN.equals(order())) {
+ put(index, b1).put(index + 1, b2).put(index + 2, b3);
+ } else {
+ put(index, b3).put(index + 1, b2).put(index + 2, b1);
+ }
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getUnsignedInt(int index) {
+ return getInt(index) & 0xffffffffL;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public InputStream asInputStream() {
+ return new InputStream() {
+ @Override
+ public int available() {
+ return AbstractIoBuffer.this.remaining();
+ }
+
+ @Override
+ public synchronized void mark(int readlimit) {
+ AbstractIoBuffer.this.mark();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ @Override
+ public int read() {
+ if (AbstractIoBuffer.this.hasRemaining()) {
+ return AbstractIoBuffer.this.get() & 0xff;
+ }
+
+ return -1;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) {
+ int remaining = AbstractIoBuffer.this.remaining();
+ if (remaining > 0) {
+ int readBytes = Math.min(remaining, len);
+ AbstractIoBuffer.this.get(b, off, readBytes);
+ return readBytes;
+ }
+
+ return -1;
+ }
+
+ @Override
+ public synchronized void reset() {
+ AbstractIoBuffer.this.reset();
+ }
+
+ @Override
+ public long skip(long n) {
+ int bytes;
+ if (n > Integer.MAX_VALUE) {
+ bytes = AbstractIoBuffer.this.remaining();
+ } else {
+ bytes = Math.min(AbstractIoBuffer.this.remaining(), (int) n);
+ }
+ AbstractIoBuffer.this.skip(bytes);
+ return bytes;
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public OutputStream asOutputStream() {
+ return new OutputStream() {
+ @Override
+ public void write(byte[] b, int off, int len) {
+ AbstractIoBuffer.this.put(b, off, len);
+ }
+
+ @Override
+ public void write(int b) {
+ AbstractIoBuffer.this.put((byte) b);
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getHexDump() {
+ return this.getHexDump(Integer.MAX_VALUE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getHexDump(int lengthLimit) {
+ return getHexDump(lengthLimit, false);
+ }
+
+ @Override
+ public String getHexDump(int lengthLimit, boolean pretty) {
+ return (pretty) ? IoBufferHexDumper.getPrettyHexDump(this, this.position(), \
lengthLimit) + : IoBufferHexDumper.getHexdump(this, lengthLimit);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getString(CharsetDecoder decoder) throws CharacterCodingException {
+ if (!hasRemaining()) {
+ return "";
+ }
+
+ boolean utf16 = decoder.charset().equals(StandardCharsets.UTF_16)
+ || decoder.charset().equals(StandardCharsets.UTF_16BE)
+ || decoder.charset().equals(StandardCharsets.UTF_16LE);
+
+ int oldPos = position();
+ int oldLimit = limit();
+ int end = -1;
+ int newPos;
+
+ if (!utf16) {
+ end = indexOf((byte) 0x00);
+ if (end < 0) {
+ newPos = end = oldLimit;
+ } else {
+ newPos = end + 1;
+ }
+ } else {
+ int i = oldPos;
+ for (;;) {
+ boolean wasZero = get(i) == 0;
+ i++;
+
+ if (i >= oldLimit) {
+ break;
+ }
+
+ if (get(i) != 0) {
+ i++;
+ if (i >= oldLimit) {
+ break;
+ }
+
+ continue;
+ }
+
+ if (wasZero) {
+ end = i - 1;
+ break;
+ }
+ }
+
+ if (end < 0) {
+ newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE);
+ } else {
+ if (end + 2 <= oldLimit) {
+ newPos = end + 2;
+ } else {
+ newPos = end;
+ }
+ }
+ }
+
+ if (oldPos == end) {
+ position(newPos);
+ return "";
+ }
+
+ limit(end);
+ decoder.reset();
+
+ int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
+ CharBuffer out = CharBuffer.allocate(expectedLength);
+ for (;;) {
+ CoderResult cr;
+ if (hasRemaining()) {
+ cr = decoder.decode(buf(), out, true);
+ } else {
+ cr = decoder.flush(out);
+ }
+
+ if (cr.isUnderflow()) {
+ break;
+ }
+
+ if (cr.isOverflow()) {
+ CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
+ out.flip();
+ o.put(out);
+ out = o;
+ continue;
+ }
+
+ if (cr.isError()) {
+ // Revert the buffer back to the previous state.
+ limit(oldLimit);
+ position(oldPos);
+ cr.throwException();
+ }
+ }
+
+ limit(oldLimit);
+ position(newPos);
+ return out.flip().toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getString(int fieldSize, CharsetDecoder decoder) throws \
CharacterCodingException { + checkFieldSize(fieldSize);
+
+ if (fieldSize == 0) {
+ return "";
+ }
+
+ if (!hasRemaining()) {
+ return "";
+ }
+
+ boolean utf16 = decoder.charset().equals(StandardCharsets.UTF_16)
+ || decoder.charset().equals(StandardCharsets.UTF_16BE)
+ || decoder.charset().equals(StandardCharsets.UTF_16LE);
+
+ if (utf16 && (fieldSize & 1) != 0) {
+ throw new IllegalArgumentException("fieldSize is not even.");
+ }
+
+ int oldPos = position();
+ int oldLimit = limit();
+ int end = oldPos + fieldSize;
+
+ if (oldLimit < end) {
+ throw new BufferUnderflowException();
+ }
+
+ int i;
+
+ if (!utf16) {
+ for (i = oldPos; i < end; i++) {
+ if (get(i) == 0) {
+ break;
+ }
+ }
+
+ if (i == end) {
+ limit(end);
+ } else {
+ limit(i);
+ }
+ } else {
+ for (i = oldPos; i < end; i += 2) {
+ if (get(i) == 0 && get(i + 1) == 0) {
+ break;
+ }
+ }
+
+ if (i == end) {
+ limit(end);
+ } else {
+ limit(i);
+ }
+ }
+
+ if (!hasRemaining()) {
+ limit(oldLimit);
+ position(end);
+ return "";
+ }
+ decoder.reset();
+
+ int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
+ CharBuffer out = CharBuffer.allocate(expectedLength);
+ for (;;) {
+ CoderResult cr;
+ if (hasRemaining()) {
+ cr = decoder.decode(buf(), out, true);
+ } else {
+ cr = decoder.flush(out);
+ }
+
+ if (cr.isUnderflow()) {
+ break;
+ }
+
+ if (cr.isOverflow()) {
+ CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
+ out.flip();
+ o.put(out);
+ out = o;
+ continue;
+ }
+
+ if (cr.isError()) {
+ // Revert the buffer back to the previous state.
+ limit(oldLimit);
+ position(oldPos);
+ cr.throwException();
+ }
+ }
+
+ limit(oldLimit);
+ position(end);
+ return out.flip().toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putString(CharSequence val, CharsetEncoder encoder) throws \
CharacterCodingException { + if (val.length() == 0) {
+ return this;
+ }
+
+ CharBuffer in = CharBuffer.wrap(val);
+ encoder.reset();
+
+ int expandedState = 0;
+
+ for (;;) {
+ CoderResult cr;
+ if (in.hasRemaining()) {
+ cr = encoder.encode(in, buf(), true);
+ } else {
+ cr = encoder.flush(buf());
+ }
+
+ if (cr.isUnderflow()) {
+ break;
+ }
+ if (cr.isOverflow()) {
+ if (isAutoExpand()) {
+ switch (expandedState) {
+ case 0:
+ autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar()));
+ expandedState++;
+ break;
+ case 1:
+ autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()));
+ expandedState++;
+ break;
+ default:
+ throw new RuntimeException(
+ "Expanded by " + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())
+ + " but that wasn't enough for '" + val + "'");
+ }
+ continue;
+ }
+ } else {
+ expandedState = 0;
+ }
+ cr.throwException();
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder) \
throws CharacterCodingException { + checkFieldSize(fieldSize);
+
+ if (fieldSize == 0) {
+ return this;
+ }
+
+ autoExpand(fieldSize);
+
+ boolean utf16 = encoder.charset().equals(StandardCharsets.UTF_16)
+ || encoder.charset().equals(StandardCharsets.UTF_16BE)
+ || encoder.charset().equals(StandardCharsets.UTF_16LE);
+
+ if (utf16 && (fieldSize & 1) != 0) {
+ throw new IllegalArgumentException("fieldSize is not even.");
+ }
+
+ int oldLimit = limit();
+ int end = position() + fieldSize;
+
+ if (oldLimit < end) {
+ throw new BufferOverflowException();
+ }
+
+ if (val.length() == 0) {
+ if (!utf16) {
+ put((byte) 0x00);
+ } else {
+ put((byte) 0x00);
+ put((byte) 0x00);
+ }
+ position(end);
+ return this;
+ }
+
+ CharBuffer in = CharBuffer.wrap(val);
+ limit(end);
+ encoder.reset();
+
+ for (;;) {
+ CoderResult cr;
+ if (in.hasRemaining()) {
+ cr = encoder.encode(in, buf(), true);
+ } else {
+ cr = encoder.flush(buf());
+ }
+
+ if (cr.isUnderflow() || cr.isOverflow()) {
+ break;
+ }
+ cr.throwException();
+ }
+
+ limit(oldLimit);
+
+ if (position() < end) {
+ if (!utf16) {
+ put((byte) 0x00);
+ } else {
+ put((byte) 0x00);
+ put((byte) 0x00);
+ }
+ }
+
+ position(end);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getPrefixedString(CharsetDecoder decoder) throws \
CharacterCodingException { + return getPrefixedString(2, decoder);
+ }
+
+ /**
+ * Reads a string which has a length field before the actual encoded string,
+ * using the specified <code>decoder</code> and returns it.
+ *
+ * @param prefixLength the length of the length field (1, 2, or 4)
+ * @param decoder the decoder to use for decoding the string
+ * @return the prefixed string
+ * @throws CharacterCodingException when decoding fails
+ * @throws BufferUnderflowException when there is not enough data available
+ */
+ @Override
+ public String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws \
CharacterCodingException { + if (!prefixedDataAvailable(prefixLength)) {
+ throw new BufferUnderflowException();
+ }
+
+ int fieldSize = 0;
+
+ switch (prefixLength) {
+ case 1:
+ fieldSize = getUnsigned();
+ break;
+ case 2:
+ fieldSize = getUnsignedShort();
+ break;
+ case 4:
+ fieldSize = getInt();
+ break;
+ }
+
+ if (fieldSize == 0) {
+ return "";
+ }
+
+ boolean utf16 = decoder.charset().equals(StandardCharsets.UTF_16)
+ || decoder.charset().equals(StandardCharsets.UTF_16BE)
+ || decoder.charset().equals(StandardCharsets.UTF_16LE);
+
+ if (utf16 && (fieldSize & 1) != 0) {
+ throw new BufferDataException("fieldSize is not even for a UTF-16 string.");
+ }
+
+ int oldLimit = limit();
+ int end = position() + fieldSize;
+
+ if (oldLimit < end) {
+ throw new BufferUnderflowException();
+ }
+
+ limit(end);
+ decoder.reset();
+
+ int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
+ CharBuffer out = CharBuffer.allocate(expectedLength);
+ for (;;) {
+ CoderResult cr;
+ if (hasRemaining()) {
+ cr = decoder.decode(buf(), out, true);
+ } else {
+ cr = decoder.flush(out);
+ }
+
+ if (cr.isUnderflow()) {
+ break;
+ }
+
+ if (cr.isOverflow()) {
+ CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
+ out.flip();
+ o.put(out);
+ out = o;
+ continue;
+ }
+
+ cr.throwException();
+ }
+
+ limit(oldLimit);
+ position(end);
+ return out.flip().toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) throws \
CharacterCodingException { + return putPrefixedString(in, 2, 0, encoder);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder \
encoder) + throws CharacterCodingException {
+ return putPrefixedString(in, prefixLength, 0, encoder);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, \
CharsetEncoder encoder) + throws CharacterCodingException {
+ return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putPrefixedString(CharSequence val, int prefixLength, int padding, \
byte padValue, + CharsetEncoder encoder) throws CharacterCodingException {
+ int maxLength;
+ switch (prefixLength) {
+ case 1:
+ maxLength = 255;
+ break;
+ case 2:
+ maxLength = 65535;
+ break;
+ case 4:
+ maxLength = Integer.MAX_VALUE;
+ break;
+ default:
+ throw new IllegalArgumentException("prefixLength: " + prefixLength);
+ }
+
+ if (val.length() > maxLength) {
+ throw new IllegalArgumentException("The specified string is too long.");
+ }
+ if (val.length() == 0) {
+ switch (prefixLength) {
+ case 1:
+ put((byte) 0);
+ break;
+ case 2:
+ putShort((short) 0);
+ break;
+ case 4:
+ putInt(0);
+ break;
+ }
+ return this;
+ }
+
+ int padMask;
+ switch (padding) {
+ case 0:
+ case 1:
+ padMask = 0;
+ break;
+ case 2:
+ padMask = 1;
+ break;
+ case 4:
+ padMask = 3;
+ break;
+ default:
+ throw new IllegalArgumentException("padding: " + padding);
+ }
+
+ CharBuffer in = CharBuffer.wrap(val);
+ skip(prefixLength); // make a room for the length field
+ int oldPos = position();
+ encoder.reset();
+
+ int expandedState = 0;
+
+ for (;;) {
+ CoderResult cr;
+ if (in.hasRemaining()) {
+ cr = encoder.encode(in, buf(), true);
+ } else {
+ cr = encoder.flush(buf());
+ }
+
+ if (position() - oldPos > maxLength) {
+ throw new IllegalArgumentException("The specified string is too long.");
+ }
+
+ if (cr.isUnderflow()) {
+ break;
+ }
+ if (cr.isOverflow()) {
+ if (isAutoExpand()) {
+ switch (expandedState) {
+ case 0:
+ autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar()));
+ expandedState++;
+ break;
+ case 1:
+ autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()));
+ expandedState++;
+ break;
+ default:
+ throw new RuntimeException(
+ "Expanded by " + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())
+ + " but that wasn't enough for '" + val + "'");
+ }
+ continue;
+ }
+ } else {
+ expandedState = 0;
+ }
+ cr.throwException();
+ }
+
+ // Write the length field
+ fill(padValue, padding - (position() - oldPos & padMask));
+ int length = position() - oldPos;
+ switch (prefixLength) {
+ case 1:
+ put(oldPos - 1, (byte) length);
+ break;
+ case 2:
+ putShort(oldPos - 2, (short) length);
+ break;
+ case 4:
+ putInt(oldPos - 4, length);
+ break;
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object getObject() throws ClassNotFoundException {
+ return getObject(Thread.currentThread().getContextClassLoader());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object getObject(final ClassLoader classLoader) throws \
ClassNotFoundException { + if (!prefixedDataAvailable(4)) {
+ throw new BufferUnderflowException();
+ }
+
+ int length = getInt();
+ if (length <= 4) {
+ throw new BufferDataException("Object length should be greater than 4: " + \
length); + }
+
+ int oldLimit = limit();
+ limit(position() + length);
+
+ try (ObjectInputStream in = new ObjectInputStream(asInputStream()) {
+ @Override
+ protected ObjectStreamClass readClassDescriptor() throws IOException, \
ClassNotFoundException { + int type = read();
+ if (type < 0) {
+ throw new EOFException();
+ }
+ switch (type) {
+ case 0: // NON-Serializable class or Primitive types
+ return super.readClassDescriptor();
+ case 1: // Serializable class
+ String className = readUTF();
+ Class<?> clazz = Class.forName(className, true, classLoader);
+ return ObjectStreamClass.lookup(clazz);
+ default:
+ throw new StreamCorruptedException("Unexpected class descriptor type: " + \
type); + }
+ }
+
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, \
ClassNotFoundException { + Class<?> clazz = desc.forClass();
+
+ if (clazz == null) {
+ String name = desc.getName();
+ try {
+ return Class.forName(name, false, classLoader);
+ } catch (ClassNotFoundException ex) {
+ return super.resolveClass(desc);
+ }
+ } else {
+ return clazz;
+ }
+ }
+ }) {
+ return in.readObject();
+ } catch (IOException e) {
+ throw new BufferDataException(e);
+ } finally {
+ limit(oldLimit);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putObject(Object o) {
+ int oldPos = position();
+ skip(4); // Make a room for the length field.
+
+ try (ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) {
+ @Override
+ protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException {
+ Class<?> clazz = desc.forClass();
+
+ if (clazz.isArray() || clazz.isPrimitive() || \
!Serializable.class.isAssignableFrom(clazz)) { + write(0);
+ super.writeClassDescriptor(desc);
+ } else {
+ // Serializable class
+ write(1);
+ writeUTF(desc.getName());
+ }
+ }
+ }) {
+ out.writeObject(o);
+ out.flush();
+ } catch (IOException e) {
+ throw new BufferDataException(e);
+ }
+
+ // Fill the length field
+ int newPos = position();
+ position(oldPos);
+ putInt(newPos - oldPos - 4);
+ position(newPos);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean prefixedDataAvailable(int prefixLength) {
+ return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
+ if (remaining() < prefixLength) {
+ return false;
+ }
+
+ int dataLength;
+ switch (prefixLength) {
+ case 1:
+ dataLength = getUnsigned(position());
+ break;
+ case 2:
+ dataLength = getUnsignedShort(position());
+ break;
+ case 4:
+ dataLength = getInt(position());
+ break;
+ default:
+ throw new IllegalArgumentException("prefixLength: " + prefixLength);
+ }
+
+ if (dataLength < 0 || dataLength > maxDataLength) {
+ throw new BufferDataException("dataLength: " + dataLength);
+ }
+
+ return remaining() - prefixLength >= dataLength;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int indexOf(byte b) {
+ if (hasArray()) {
+ int arrayOffset = arrayOffset();
+ int beginPos = arrayOffset + position();
+ int limit = arrayOffset + limit();
+ byte[] array = array();
+
+ for (int i = beginPos; i < limit; i++) {
+ if (array[i] == b) {
+ return i - arrayOffset;
+ }
+ }
+ } else {
+ int beginPos = position();
+ int limit = limit();
+
+ for (int i = beginPos; i < limit; i++) {
+ if (get(i) == b) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer skip(int size) {
+ autoExpand(size);
+ return position(position() + size);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer fill(byte value, int size) {
+ autoExpand(size);
+ int q = size >>> 3;
+ int r = size & 7;
+
+ if (q > 0) {
+ int intValue = value & 0x000000FF | (value << 8) & 0x0000FF00 | (value << 16) & \
0x00FF0000 | value << 24; + long longValue = intValue & 0x00000000FFFFFFFFL | \
(long) intValue << 32; +
+ for (int i = q; i > 0; i--) {
+ putLong(longValue);
+ }
+ }
+
+ q = r >>> 2;
+ r = r & 3;
+
+ if (q > 0) {
+ int intValue = value & 0x000000FF | (value << 8) & 0x0000FF00 | (value << 16) & \
0x00FF0000 | value << 24; + putInt(intValue);
+ }
+
+ q = r >> 1;
+ r = r & 1;
+
+ if (q > 0) {
+ short shortValue = (short) (value & 0x000FF | value << 8);
+ putShort(shortValue);
+ }
+
+ if (r > 0) {
+ put(value);
+ }
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer fillAndReset(byte value, int size) {
+ autoExpand(size);
+ int pos = position();
+ try {
+ fill(value, size);
+ } finally {
+ position(pos);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer fill(int size) {
+ autoExpand(size);
+ int q = size >>> 3;
+ int r = size & 7;
+
+ for (int i = q; i > 0; i--) {
+ putLong(0L);
+ }
+
+ q = r >>> 2;
+ r = r & 3;
+
+ if (q > 0) {
+ putInt(0);
+ }
+
+ q = r >> 1;
+ r = r & 1;
+
+ if (q > 0) {
+ putShort((short) 0);
+ }
+
+ if (r > 0) {
+ put((byte) 0);
+ }
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer fillAndReset(int size) {
+ autoExpand(size);
+ int pos = position();
+ try {
+ fill(size);
+ } finally {
+ position(pos);
+ }
+
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> E getEnum(Class<E> enumClass) {
+ return toEnum(enumClass, getUnsigned());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> E getEnum(int index, Class<E> enumClass) {
+ return toEnum(enumClass, getUnsigned(index));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> E getEnumShort(Class<E> enumClass) {
+ return toEnum(enumClass, getUnsignedShort());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> E getEnumShort(int index, Class<E> enumClass) {
+ return toEnum(enumClass, getUnsignedShort(index));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> E getEnumInt(Class<E> enumClass) {
+ return toEnum(enumClass, getInt());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> E getEnumInt(int index, Class<E> enumClass) {
+ return toEnum(enumClass, getInt(index));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putEnum(Enum<?> e) {
+ if (e.ordinal() > BYTE_MASK) {
+ throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte"));
+ }
+ return put((byte) e.ordinal());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putEnum(int index, Enum<?> e) {
+ if (e.ordinal() > BYTE_MASK) {
+ throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte"));
+ }
+ return put(index, (byte) e.ordinal());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putEnumShort(Enum<?> e) {
+ if (e.ordinal() > SHORT_MASK) {
+ throw new IllegalArgumentException(enumConversionErrorMessage(e, "short"));
+ }
+ return putShort((short) e.ordinal());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putEnumShort(int index, Enum<?> e) {
+ if (e.ordinal() > SHORT_MASK) {
+ throw new IllegalArgumentException(enumConversionErrorMessage(e, "short"));
+ }
+ return putShort(index, (short) e.ordinal());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putEnumInt(Enum<?> e) {
+ return putInt(e.ordinal());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IoBuffer putEnumInt(int index, Enum<?> e) {
+ return putInt(index, e.ordinal());
+ }
+
+ private <E> E toEnum(Class<E> enumClass, int i) {
+ E[] enumConstants = enumClass.getEnumConstants();
+ if (i > enumConstants.length) {
+ throw new IndexOutOfBoundsException(
+ String.format("%d is too large of an ordinal to convert to the enum %s", i, \
enumClass.getName())); + }
+ return enumConstants[i];
+ }
+
+ private String enumConversionErrorMessage(Enum<?> e, String type) {
+ return String.format("%s.%s has an ordinal value too large for a %s", \
e.getClass().getName(), e.name(), type); + }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> Set<E> getEnumSet(Class<E> enumClass) {
+ return toEnumSet(enumClass, get() & BYTE_MASK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> Set<E> getEnumSet(int index, Class<E> enumClass) {
+ return toEnumSet(enumClass, get(index) & BYTE_MASK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> Set<E> getEnumSetShort(Class<E> enumClass) {
+ return toEnumSet(enumClass, getShort() & SHORT_MASK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> Set<E> getEnumSetShort(int index, Class<E> enumClass) {
+ return toEnumSet(enumClass, getShort(index) & SHORT_MASK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> Set<E> getEnumSetInt(Class<E> enumClass) {
+ return toEnumSet(enumClass, getInt() & INT_MASK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> Set<E> getEnumSetInt(int index, Class<E> enumClass) {
+ return toEnumSet(enumClass, getInt(index) & INT_MASK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> Set<E> getEnumSetLong(Class<E> enumClass) {
+ return toEnumSet(enumClass, getLong());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> Set<E> getEnumSetLong(int index, Class<E> enumClass) {
+ return toEnumSet(enumClass, getLong(index));
+ }
+
+ private <E extends Enum<E>> EnumSet<E> toEnumSet(Class<E> clazz, long vector) {
+ EnumSet<E> set = EnumSet.noneOf(clazz);
+ long mask = 1;
+ for (E e : clazz.getEnumConstants()) {
+ if ((mask & vector) == mask) {
+ set.add(e);
+ }
+ mask <<= 1;
+ }
+ return set;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set) {
+ long vector = toLong(set);
+ if ((vector & ~BYTE_MASK) != 0) {
+ throw new IllegalArgumentException("The enum set is too large to fit in a byte: " \
+ set); + }
+ return put((byte) vector);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set) {
+ long vector = toLong(set);
+ if ((vector & ~BYTE_MASK) != 0) {
+ throw new IllegalArgumentException("The enum set is too large to fit in a byte: " \
+ set); + }
+ return put(index, (byte) vector);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set) {
+ long vector = toLong(set);
+ if ((vector & ~SHORT_MASK) != 0) {
+ throw new IllegalArgumentException("The enum set is too large to fit in a short: \
" + set); + }
+ return putShort((short) vector);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> IoBuffer putEnumSetShort(int index, Set<E> set) {
+ long vector = toLong(set);
+ if ((vector & ~SHORT_MASK) != 0) {
+ throw new IllegalArgumentException("The enum set is too large to fit in a short: \
" + set); + }
+ return putShort(index, (short) vector);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set) {
+ long vector = toLong(set);
+ if ((vector & ~INT_MASK) != 0) {
+ throw new IllegalArgumentException("The enum set is too large to fit in an int: " \
+ set); + }
+ return putInt((int) vector);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> IoBuffer putEnumSetInt(int index, Set<E> set) {
+ long vector = toLong(set);
+ if ((vector & ~INT_MASK) != 0) {
+ throw new IllegalArgumentException("The enum set is too large to fit in an int: " \
+ set); + }
+ return putInt(index, (int) vector);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set) {
+ return putLong(toLong(set));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <E extends Enum<E>> IoBuffer putEnumSetLong(int index, Set<E> set) {
+ return putLong(index, toLong(set));
+ }
+
+ private <E extends Enum<E>> long toLong(Set<E> set) {
+ long vector = 0;
+ for (E e : set) {
+ if (e.ordinal() >= Long.SIZE) {
+ throw new IllegalArgumentException("The enum set is too large to fit in a bit \
vector: " + set); + }
+ vector |= 1L << e.ordinal();
+ }
+ return vector;
+ }
+
+ /**
+ * This method forwards the call to {@link #expand(int)} only when
+ * <tt>autoExpand</tt> property is <tt>true</tt>.
+ */
+ private IoBuffer autoExpand(int expectedRemaining) {
+ if (isAutoExpand()) {
+ expand(expectedRemaining, true);
+ }
+ return this;
+ }
+
+ /**
+ * This method forwards the call to {@link #expand(int)} only when
+ * <tt>autoExpand</tt> property is <tt>true</tt>.
+ */
+ private IoBuffer autoExpand(int pos, int expectedRemaining) {
+ if (isAutoExpand()) {
+ expand(pos, expectedRemaining, true);
+ }
+ return this;
+ }
+
+ private static void checkFieldSize(int fieldSize) {
+ if (fieldSize < 0) {
+ throw new IllegalArgumentException("fieldSize cannot be negative: " + fieldSize);
+ }
+ }
}
diff --git a/mina-core/src/main/java/org/apache/mina/core/buffer/IoBuffer.java \
b/mina-core/src/main/java/org/apache/mina/core/buffer/IoBuffer.java index \
882ca9c..648d56d 100644
--- a/mina-core/src/main/java/org/apache/mina/core/buffer/IoBuffer.java
+++ b/mina-core/src/main/java/org/apache/mina/core/buffer/IoBuffer.java
@@ -46,2043 +46,2050 @@ import org.apache.mina.core.session.IoSession;
* {@link ByteBuffer} documentation for preliminary usage. MINA does not use NIO
* {@link ByteBuffer} directly for two reasons:
* <ul>
- * <li>It doesn't provide useful getters and putters such as <code>fill</code>,
- * <code>get/putString</code>, and <code>get/putAsciiInt()</code> enough.</li>
- * <li>It is difficult to write variable-length data due to its fixed \
capacity</li> + * <li>It doesn't provide useful getters and putters such as \
<code>fill</code>, + * <code>get/putString</code>, and <code>get/putAsciiInt()</code> \
enough.</li> + * <li>It is difficult to write variable-length data due to its fixed
+ * capacity</li>
* </ul>
*
* <h2>Allocation</h2>
* <p>
- * You can allocate a new heap buffer.
+ * You can allocate a new heap buffer.
*
- * <pre>
- * IoBuffer buf = IoBuffer.allocate(1024, false);
- * </pre>
+ * <pre>
+ * IoBuffer buf = IoBuffer.allocate(1024, false);
+ * </pre>
*
- * You can also allocate a new direct buffer:
+ * You can also allocate a new direct buffer:
*
- * <pre>
- * IoBuffer buf = IoBuffer.allocate(1024, true);
- * </pre>
+ * <pre>
+ * IoBuffer buf = IoBuffer.allocate(1024, true);
+ * </pre>
*
- * or you can set the default buffer type.
+ * or you can set the default buffer type.
*
- * <pre>
- * // Allocate heap buffer by default.
- * IoBuffer.setUseDirectBuffer(false);
+ * <pre>
+ * // Allocate heap buffer by default.
+ * IoBuffer.setUseDirectBuffer(false);
*
- * // A new heap buffer is returned.
- * IoBuffer buf = IoBuffer.allocate(1024);
- * </pre>
+ * // A new heap buffer is returned.
+ * IoBuffer buf = IoBuffer.allocate(1024);
+ * </pre>
*
* <h2>Wrapping existing NIO buffers and arrays</h2>
* <p>
- * This class provides a few <tt>wrap(...)</tt> methods that wraps any NIO
- * buffers and byte arrays.
+ * This class provides a few <tt>wrap(...)</tt> methods that wraps any NIO
+ * buffers and byte arrays.
*
* <h2>AutoExpand</h2>
* <p>
- * Writing variable-length data using NIO <tt>ByteBuffers</tt> is not really
- * easy, and it is because its size is fixed at allocation. {@link IoBuffer} \
introduces
- * the <tt>autoExpand</tt> property. If <tt>autoExpand</tt> property is set to \
true,
- * you never get a {@link BufferOverflowException} or
- * an {@link IndexOutOfBoundsException} (except when index is negative). It
- * automatically expands its capacity. For instance:
+ * Writing variable-length data using NIO <tt>ByteBuffers</tt> is not really
+ * easy, and it is because its size is fixed at allocation. {@link IoBuffer}
+ * introduces the <tt>autoExpand</tt> property. If <tt>autoExpand</tt> property
+ * is set to true, you never get a {@link BufferOverflowException} or an
+ * {@link IndexOutOfBoundsException} (except when index is negative). It
+ * automatically expands its capacity. For instance:
*
- * <pre>
- * String greeting = messageBundle.getMessage("hello");
- * IoBuffer buf = IoBuffer.allocate(16);
- * // Turn on autoExpand (it is off by default)
- * buf.setAutoExpand(true);
- * buf.putString(greeting, utf8encoder);
- * </pre>
+ * <pre>
+ * String greeting = messageBundle.getMessage("hello");
+ * IoBuffer buf = IoBuffer.allocate(16);
+ * // Turn on autoExpand (it is off by default)
+ * buf.setAutoExpand(true);
+ * buf.putString(greeting, utf8encoder);
+ * </pre>
*
- * The underlying {@link ByteBuffer} is reallocated by {@link IoBuffer} behind
- * the scene if the encoded data is larger than 16 bytes in the example above.
- * Its capacity will double, and its limit will increase to the last position
- * the string is written.
+ * The underlying {@link ByteBuffer} is reallocated by {@link IoBuffer} behind
+ * the scene if the encoded data is larger than 16 bytes in the example above.
+ * Its capacity will double, and its limit will increase to the last position
+ * the string is written.
*
* <h2>AutoShrink</h2>
* <p>
- * You might also want to decrease the capacity of the buffer when most of the
- * allocated memory area is not being used. {@link IoBuffer} provides
- * <tt>autoShrink</tt> property to take care of this issue. If
- * <tt>autoShrink</tt> is turned on, {@link IoBuffer} halves the capacity of the
- * buffer when {@link #compact()} is invoked and only 1/4 or less of the current
- * capacity is being used.
+ * You might also want to decrease the capacity of the buffer when most of the
+ * allocated memory area is not being used. {@link IoBuffer} provides
+ * <tt>autoShrink</tt> property to take care of this issue. If
+ * <tt>autoShrink</tt> is turned on, {@link IoBuffer} halves the capacity of the
+ * buffer when {@link #compact()} is invoked and only 1/4 or less of the current
+ * capacity is being used.
* <p>
- * You can also call the {@link #shrink()} method manually to shrink the capacity \
of the
- * buffer.
+ * You can also call the {@link #shrink()} method manually to shrink the
+ * capacity of the buffer.
* <p>
- * The underlying {@link ByteBuffer} is reallocated by the {@link IoBuffer} behind
- * the scene, and therefore {@link #buf()} will return a different
- * {@link ByteBuffer} instance once capacity changes. Please also note
- * that the {@link #compact()} method or the {@link #shrink()} method
- * will not decrease the capacity if the new capacity is less than the
- * {@link #minimumCapacity()} of the buffer.
+ * The underlying {@link ByteBuffer} is reallocated by the {@link IoBuffer}
+ * behind the scene, and therefore {@link #buf()} will return a different
+ * {@link ByteBuffer} instance once capacity changes. Please also note that the
+ * {@link #compact()} method or the {@link #shrink()} method will not decrease
+ * the capacity if the new capacity is less than the {@link #minimumCapacity()}
+ * of the buffer.
*
* <h2>Derived Buffers</h2>
* <p>
- * Derived buffers are the buffers which were created by the {@link #duplicate()},
- * {@link #slice()}, or {@link #asReadOnlyBuffer()} methods. They are useful \
especially
- * when you broadcast the same messages to multiple {@link IoSession}s. Please
- * note that the buffer derived from and its derived buffers are not
- * auto-expandable nor auto-shrinkable. Trying to call
- * {@link #setAutoExpand(boolean)} or {@link #setAutoShrink(boolean)} with
- * <tt>true</tt> parameter will raise an {@link IllegalStateException}.
+ * Derived buffers are the buffers which were created by the
+ * {@link #duplicate()}, {@link #slice()}, or {@link #asReadOnlyBuffer()}
+ * methods. They are useful especially when you broadcast the same messages to
+ * multiple {@link IoSession}s. Please note that the buffer derived from and its
+ * derived buffers are not auto-expandable nor auto-shrinkable. Trying to call
+ * {@link #setAutoExpand(boolean)} or {@link #setAutoShrink(boolean)} with
+ * <tt>true</tt> parameter will raise an {@link IllegalStateException}.
*
* <h2>Changing Buffer Allocation Policy</h2>
* <p>
- * The {@link IoBufferAllocator} interface lets you override the default buffer
- * management behavior. There are two allocators provided out-of-the-box:
- * <ul>
- * <li>{@link SimpleBufferAllocator} (default)</li>
- * <li>{@link CachedBufferAllocator}</li>
- * </ul>
- * You can implement your own allocator and use it by calling
- * {@link #setAllocator(IoBufferAllocator)}.
+ * The {@link IoBufferAllocator} interface lets you override the default buffer
+ * management behavior. There are two allocators provided out-of-the-box:
+ * <ul>
+ * <li>{@link SimpleBufferAllocator} (default)</li>
+ * <li>{@link CachedBufferAllocator}</li>
+ * </ul>
+ * You can implement your own allocator and use it by calling
+ * {@link #setAllocator(IoBufferAllocator)}.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public abstract class IoBuffer implements Comparable<IoBuffer> {
- /** The allocator used to create new buffers */
- private static IoBufferAllocator allocator = new SimpleBufferAllocator();
-
- /** A flag indicating which type of buffer we are using : heap or direct */
- private static boolean useDirectBuffer = false;
-
- /**
- * Creates a new instance. This is an empty constructor. It's protected,
- * to forbid its usage by the users.
- */
- protected IoBuffer() {
- // Do nothing
- }
-
- /**
- * @return the allocator used by existing and new buffers
- */
- public static IoBufferAllocator getAllocator() {
- return allocator;
- }
-
- /**
- * Sets the allocator used by existing and new buffers
- *
- * @param newAllocator the new allocator to use
- */
- public static void setAllocator(IoBufferAllocator newAllocator) {
- if (newAllocator == null) {
- throw new IllegalArgumentException("allocator");
- }
-
- IoBufferAllocator oldAllocator = allocator;
-
- allocator = newAllocator;
-
- if (null != oldAllocator) {
- oldAllocator.dispose();
- }
- }
-
- /**
- * @return <tt>true</tt> if and only if a direct buffer is allocated by
- * default when the type of the new buffer is not specified. The default
- * value is <tt>false</tt>.
- */
- public static boolean isUseDirectBuffer() {
- return useDirectBuffer;
- }
-
- /**
- * Sets if a direct buffer should be allocated by default when the type of
- * the new buffer is not specified. The default value is <tt>false</tt>.
- *
- * @param useDirectBuffer Tells if direct buffers should be allocated
- */
- public static void setUseDirectBuffer(boolean useDirectBuffer) {
- IoBuffer.useDirectBuffer = useDirectBuffer;
- }
-
- /**
- * Returns the direct or heap buffer which is capable to store the specified
- * amount of bytes.
- *
- * @param capacity the capacity of the buffer
- * @return a IoBuffer which can hold up to capacity bytes
- *
- * @see #setUseDirectBuffer(boolean)
- */
- public static IoBuffer allocate(int capacity) {
- return allocate(capacity, useDirectBuffer);
- }
-
- /**
- * Returns a direct or heap IoBuffer which can contain the specified number of \
bytes.
- *
- * @param capacity the capacity of the buffer
- * @param useDirectBuffer <tt>true</tt> to get a direct buffer, <tt>false</tt> \
to get a
- * heap buffer.
- * @return a direct or heap IoBuffer which can hold up to capacity bytes
- */
- public static IoBuffer allocate(int capacity, boolean useDirectBuffer) {
- if (capacity < 0) {
- throw new IllegalArgumentException("capacity: " + capacity);
- }
-
- return allocator.allocate(capacity, useDirectBuffer);
- }
-
- /**
- * Wraps the specified NIO {@link ByteBuffer} into a MINA buffer (either direct \
or heap).
- *
- * @param nioBuffer The {@link ByteBuffer} to wrap
- * @return a IoBuffer containing the bytes stored in the {@link ByteBuffer}
- */
- public static IoBuffer wrap(ByteBuffer nioBuffer) {
- return allocator.wrap(nioBuffer);
- }
-
- /**
- * Wraps the specified byte array into a MINA heap buffer. Note that
- * the byte array is not copied, so any modification done on it will
- * be visible by both sides.
- *
- * @param byteArray The byte array to wrap
- * @return a heap IoBuffer containing the byte array
- */
- public static IoBuffer wrap(byte[] byteArray) {
- return wrap(ByteBuffer.wrap(byteArray));
- }
-
- /**
- * Wraps the specified byte array into MINA heap buffer. We just wrap the
- * bytes starting from offset up to offset + length. Note that
- * the byte array is not copied, so any modification done on it will
- * be visible by both sides.
- *
- * @param byteArray The byte array to wrap
- * @param offset The starting point in the byte array
- * @param length The number of bytes to store
- * @return a heap IoBuffer containing the selected part of the byte array
- */
- public static IoBuffer wrap(byte[] byteArray, int offset, int length) {
- return wrap(ByteBuffer.wrap(byteArray, offset, length));
- }
-
- /**
- * Normalizes the specified capacity of the buffer to power of 2, which is
- * often helpful for optimal memory usage and performance. If it is greater
- * than or equal to {@link Integer#MAX_VALUE}, it returns
- * {@link Integer#MAX_VALUE}. If it is zero, it returns zero.
- *
- * @param requestedCapacity The IoBuffer capacity we want to be able to store
- * @return The power of 2 strictly superior to the requested capacity
- */
- protected static int normalizeCapacity(int requestedCapacity) {
- if (requestedCapacity < 0) {
- return Integer.MAX_VALUE;
- }
-
- int newCapacity = Integer.highestOneBit(requestedCapacity);
- newCapacity <<= (newCapacity < requestedCapacity ? 1 : 0);
-
- return newCapacity < 0 ? Integer.MAX_VALUE : newCapacity;
- }
-
- /**
- * Declares this buffer and all its derived buffers are not used anymore so
- * that it can be reused by some {@link IoBufferAllocator} implementations.
- * It is not mandatory to call this method, but you might want to invoke
- * this method for maximum performance.
- */
- public abstract void free();
-
- /**
- * @return the underlying NIO {@link ByteBuffer} instance.
- */
- public abstract ByteBuffer buf();
-
- /**
- * @see ByteBuffer#isDirect()
- *
- * @return <tt>True</tt> if this is a direct buffer
- */
- public abstract boolean isDirect();
-
- /**
- * @return <tt>true</tt> if and only if this buffer is derived from another
- * buffer via one of the {@link #duplicate()}, {@link #slice()} or
- * {@link #asReadOnlyBuffer()} methods.
- */
- public abstract boolean isDerived();
-
- /**
- * @see ByteBuffer#isReadOnly()
- *
- * @return <tt>true</tt> if the buffer is readOnly
- */
- public abstract boolean isReadOnly();
-
- /**
- * @return the minimum capacity of this buffer which is used to determine
- * the new capacity of the buffer shrunk by the {@link #compact()} and
- * {@link #shrink()} operation. The default value is the initial capacity of
- * the buffer.
- */
- public abstract int minimumCapacity();
-
- /**
- * Sets the minimum capacity of this buffer which is used to determine the
- * new capacity of the buffer shrunk by {@link #compact()} and
- * {@link #shrink()} operation. The default value is the initial capacity of
- * the buffer.
- *
- * @param minimumCapacity the wanted minimum capacity
- * @return the underlying NIO {@link ByteBuffer} instance.
- */
- public abstract IoBuffer minimumCapacity(int minimumCapacity);
-
- /**
- * @see ByteBuffer#capacity()
- *
- * @return the buffer capacity
- */
- public abstract int capacity();
-
- /**
- * Increases the capacity of this buffer. If the new capacity is less than
- * or equal to the current capacity, this method returns the original buffer.
- * If the new capacity is greater than the current capacity, the buffer is
- * reallocated while retaining the position, limit, mark and the content of
- * the buffer.
- * <br>
- * Note that the IoBuffer is replaced, it's not copied.
- * <br>
- * Assuming a buffer contains N bytes, its position is 0 and its current \
capacity is C,
- * here are the resulting buffer if we set the new capacity to a value V < C \
and V > C :
- *
- * <pre>
- * Initial buffer :
- *
- * 0 L C
- * +--------+----------+
- * |XXXXXXXX| |
- * +--------+----------+
- * ^ ^ ^
- * | | |
- * pos limit capacity
- *
- * V <= C :
- *
- * 0 L C
- * +--------+----------+
- * |XXXXXXXX| |
- * +--------+----------+
- * ^ ^ ^
- * | | |
- * pos limit newCapacity
- *
- * V > C :
- *
- * 0 L C V
- * +--------+-----------------------+
- * |XXXXXXXX| : |
- * +--------+-----------------------+
- * ^ ^ ^ ^
- * | | | |
- * pos limit oldCapacity newCapacity
- *
- * The buffer has been increased.
- *
- * </pre>
- *
- * @param newCapacity the wanted capacity
- * @return the underlying NIO {@link ByteBuffer} instance.
- */
- public abstract IoBuffer capacity(int newCapacity);
-
- /**
- * @return <tt>true</tt> if and only if <tt>autoExpand</tt> is turned on.
- */
- public abstract boolean isAutoExpand();
-
- /**
- * Turns on or off <tt>autoExpand</tt>.
- *
- * @param autoExpand The flag value to set
- * @return The modified IoBuffer instance
- */
- public abstract IoBuffer setAutoExpand(boolean autoExpand);
-
- /**
- * @return <tt>true</tt> if and only if <tt>autoShrink</tt> is turned on.
- */
- public abstract boolean isAutoShrink();
-
- /**
- * Turns on or off <tt>autoShrink</tt>.
- *
- * @param autoShrink The flag value to set
- * @return The modified IoBuffer instance
- */
- public abstract IoBuffer setAutoShrink(boolean autoShrink);
-
- /**
- * Changes the capacity and limit of this buffer so this buffer get the
- * specified <tt>expectedRemaining</tt> room from the current position. This
- * method works even if you didn't set <tt>autoExpand</tt> to <tt>true</tt>.
- * <br>
- * Assuming a buffer contains N bytes, its position is P and its current \
capacity is C,
- * here are the resulting buffer if we call the expand method with a \
expectedRemaining
- * value V :
- *
- * <pre>
- * Initial buffer :
- *
- * 0 L C
- * +--------+----------+
- * |XXXXXXXX| |
- * +--------+----------+
- * ^ ^ ^
- * | | |
- * pos limit capacity
- *
- * ( pos + V ) <= L, no change :
- *
- * 0 L C
- * +--------+----------+
- * |XXXXXXXX| |
- * +--------+----------+
- * ^ ^ ^
- * | | |
- * pos limit newCapacity
- *
- * You can still put ( L - pos ) bytes in the buffer
- *
- * ( pos + V ) > L & ( pos + V ) <= C :
- *
- * 0 L C
- * +------------+------+
- * |XXXXXXXX:...| |
- * +------------+------+
- * ^ ^ ^
- * | | |
- * pos newlimit newCapacity
- *
- * You can now put ( L - pos + V ) bytes in the buffer.
- *
- *
- * ( pos + V ) > C
- *
- * 0 L C
- * +-------------------+----+
- * |XXXXXXXX:..........:....|
- * +------------------------+
- * ^ ^
- * | |
- * pos +-- newlimit
- * |
- * +-- newCapacity
- *
- * You can now put ( L - pos + V ) bytes in the buffer, which limit is now
- * equals to the capacity.
- * </pre>
- *
- * Note that the expecting remaining bytes starts at the current position. In \
all
- * those examples, the position is 0.
- *
- * @param expectedRemaining The expected remaining bytes in the buffer
- * @return The modified IoBuffer instance
- */
- public abstract IoBuffer expand(int expectedRemaining);
-
- /**
- * Changes the capacity and limit of this buffer so this buffer get the
- * specified <tt>expectedRemaining</tt> room from the specified
- * <tt>position</tt>. This method works even if you didn't set
- * <tt>autoExpand</tt> to <tt>true</tt>.
- * Assuming a buffer contains N bytes, its position is P and its current \
capacity is C,
- * here are the resulting buffer if we call the expand method with a \
expectedRemaining
- * value V :
- *
- * <pre>
- * Initial buffer :
- *
- * P L C
- * +--------+----------+
- * |XXXXXXXX| |
- * +--------+----------+
- * ^ ^ ^
- * | | |
- * pos limit capacity
- *
- * ( pos + V ) <= L, no change :
- *
- * P L C
- * +--------+----------+
- * |XXXXXXXX| |
- * +--------+----------+
- * ^ ^ ^
- * | | |
- * pos limit newCapacity
- *
- * You can still put ( L - pos ) bytes in the buffer
- *
- * ( pos + V ) > L & ( pos + V ) <= C :
- *
- * P L C
- * +------------+------+
- * |XXXXXXXX:...| |
- * +------------+------+
- * ^ ^ ^
- * | | |
- * pos newlimit newCapacity
- *
- * You can now put ( L - pos + V) bytes in the buffer.
- *
- *
- * ( pos + V ) > C
- *
- * P L C
- * +-------------------+----+
- * |XXXXXXXX:..........:....|
- * +------------------------+
- * ^ ^
- * | |
- * pos +-- newlimit
- * |
- * +-- newCapacity
- *
- * You can now put ( L - pos + V ) bytes in the buffer, which limit is now
- * equals to the capacity.
- * </pre>
- *
- * Note that the expecting remaining bytes starts at the current position. In \
all
- * those examples, the position is P.
- *
- * @param position The starting position from which we want to define a \
remaining
- * number of bytes
- * @param expectedRemaining The expected remaining bytes in the buffer
- * @return The modified IoBuffer instance
- */
- public abstract IoBuffer expand(int position, int expectedRemaining);
-
- /**
- * Changes the capacity of this buffer so this buffer occupies as less
- * memory as possible while retaining the position, limit and the buffer
- * content between the position and limit.
- * <br>
- * <b>The capacity of the buffer never becomes less than {@link \
#minimumCapacity()}</b>
- * <br>.
- * The mark is discarded once the capacity changes.
- * <br>
- * Typically, a call to this method tries to remove as much unused bytes
- * as possible, dividing by two the initial capacity until it can't without
- * obtaining a new capacity lower than the {@link #minimumCapacity()}. For \
instance, if
- * the limit is 7 and the capacity is 36, with a minimum capacity of 8,
- * shrinking the buffer will left a capacity of 9 (we go down from 36 to 18, \
then from 18 to 9).
- *
- * <pre>
- * Initial buffer :
- *
- * +--------+----------+
- * |XXXXXXXX| |
- * +--------+----------+
- * ^ ^ ^ ^
- * | | | |
- * pos | | capacity
- * | |
- * | +-- minimumCapacity
- * |
- * +-- limit
- *
- * Resulting buffer :
- *
- * +--------+--+-+
- * |XXXXXXXX| | |
- * +--------+--+-+
- * ^ ^ ^ ^
- * | | | |
- * | | | +-- new capacity
- * | | |
- * pos | +-- minimum capacity
- * |
- * +-- limit
- * </pre>
- *
- * @return The modified IoBuffer instance
- */
- public abstract IoBuffer shrink();
-
- /**
- * @see java.nio.Buffer#position()
- * @return The current position in the buffer
- */
- public abstract int position();
-
- /**
- * @see java.nio.Buffer#position(int)
- *
- * @param newPosition Sets the new position in the buffer
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer position(int newPosition);
-
- /**
- * @see java.nio.Buffer#limit()
- *
- * @return the modified IoBuffer
-'s limit
- */
- public abstract int limit();
-
- /**
- * @see java.nio.Buffer#limit(int)
- *
- * @param newLimit The new buffer's limit
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer limit(int newLimit);
-
- /**
- * @see java.nio.Buffer#mark()
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer mark();
-
- /**
- * @return the position of the current mark. This method returns <tt>-1</tt>
- * if no mark is set.
- */
- public abstract int markValue();
-
- /**
- * @see java.nio.Buffer#reset()
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer reset();
-
- /**
- * @see java.nio.Buffer#clear()
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer clear();
-
- /**
- * Clears this buffer and fills its content with <tt>NUL</tt>. The position
- * is set to zero, the limit is set to the capacity, and the mark is
- * discarded.
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer sweep();
-
- /**
- * double Clears this buffer and fills its content with <tt>value</tt>. The
- * position is set to zero, the limit is set to the capacity, and the mark
- * is discarded.
- *
- * @param value The value to put in the buffer
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer sweep(byte value);
-
- /**
- * @see java.nio.Buffer#flip()
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer flip();
-
- /**
- * @see java.nio.Buffer#rewind()
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer rewind();
-
- /**
- * @see java.nio.Buffer#remaining()
- *
- * @return The remaining bytes in the buffer
- */
- public abstract int remaining();
-
- /**
- * @see java.nio.Buffer#hasRemaining()
- *
- * @return <tt>true</tt> if there are some remaining bytes in the buffer
- */
- public abstract boolean hasRemaining();
-
- /**
- * @see ByteBuffer#duplicate()
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer duplicate();
-
- /**
- * @see ByteBuffer#slice()
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer slice();
-
- /**
- * @see ByteBuffer#asReadOnlyBuffer()
- *
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer asReadOnlyBuffer();
-
- /**
- * @see ByteBuffer#hasArray()
- *
- * @return <tt>true</tt> if the {@link #array()} method will return a byte[]
- */
- public abstract boolean hasArray();
-
- /**
- * @see ByteBuffer#array()
- *
- * @return A byte[] if this IoBuffer supports it
- */
- public abstract byte[] array();
-
- /**
- * @see ByteBuffer#arrayOffset()
- *
- * @return The offset in the returned byte[] when the {@link #array()} method is \
called
- */
- public abstract int arrayOffset();
-
- /**
- * @see ByteBuffer#get()
- *
- * @return The byte at the current position
- */
- public abstract byte get();
-
- /**
- * Reads one unsigned byte as a short integer.
- *
- * @return the unsigned short at the current position
- */
- public abstract short getUnsigned();
-
- /**
- * @see ByteBuffer#put(byte)
- *
- * @param b The byte to put in the buffer
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer put(byte b);
-
- /**
- * @see ByteBuffer#get(int)
- *
- * @param index The position for which we want to read a byte
- * @return the byte at the given position
- */
- public abstract byte get(int index);
-
- /**
- * Reads one byte as an unsigned short integer.
- *
- * @param index The position for which we want to read an unsigned byte
- * @return the unsigned byte at the given position
- */
- public abstract short getUnsigned(int index);
-
- /**
- * @see ByteBuffer#put(int, byte)
- *
- * @param index The position where the byte will be put
- * @param b The byte to put
- * @return the modified IoBuffer
-
- */
- public abstract IoBuffer put(int index, byte b);
-
- /**
- * @see ByteBuffer#get(byte[], int, int)
- *
- * @param dst The destination buffer
- * @param offset The position in the original buffer
- * @param length The number of bytes to copy
- * @return the modified IoBuffer
- */
- public abstract IoBuffer get(byte[] dst, int offset, int length);
-
- /**
- * @see ByteBuffer#get(byte[])
- *
- * @param dst The byte[] that will contain the read bytes
- * @return the IoBuffer
- */
- public abstract IoBuffer get(byte[] dst);
-
- /**
- * Get a new IoBuffer containing a slice of the current buffer
- *
- * @param index The position in the buffer
- * @param length The number of bytes to copy
- * @return the new IoBuffer
- */
- public abstract IoBuffer getSlice(int index, int length);
-
- /**
- * Get a new IoBuffer containing a slice of the current buffer
- *
- * @param length The number of bytes to copy
- * @return the new IoBuffer
- */
- public abstract IoBuffer getSlice(int length);
-
- /**
- * Writes the content of the specified <tt>src</tt> into this buffer.
- *
- * @param src The source ByteBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer put(ByteBuffer src);
-
- /**
- * Writes the content of the specified <tt>src</tt> into this buffer.
- *
- * @param src The source IoBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer put(IoBuffer src);
-
- /**
- * @see ByteBuffer#put(byte[], int, int)
- *
- * @param src The byte[] to put
- * @param offset The position in the source
- * @param length The number of bytes to copy
- * @return the modified IoBuffer
- */
- public abstract IoBuffer put(byte[] src, int offset, int length);
-
- /**
- * @see ByteBuffer#put(byte[])
- *
- * @param src The byte[] to put
- * @return the modified IoBuffer
- */
- public abstract IoBuffer put(byte[] src);
-
- /**
- * @see ByteBuffer#compact()
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer compact();
-
- /**
- * @see ByteBuffer#order()
- *
- * @return the IoBuffer ByteOrder
- */
- public abstract ByteOrder order();
-
- /**
- * @see ByteBuffer#order(ByteOrder)
- *
- * @param bo The new ByteBuffer to use for this IoBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer order(ByteOrder bo);
-
- /**
- * @see ByteBuffer#getChar()
- *
- * @return The char at the current position
- */
- public abstract char getChar();
-
- /**
- * @see ByteBuffer#putChar(char)
- *
- * @param value The char to put at the current position
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putChar(char value);
-
- /**
- * @see ByteBuffer#getChar(int)
- *
- * @param index The index in the IoBuffer where we will read a char from
- * @return the char at 'index' position
- */
- public abstract char getChar(int index);
-
- /**
- * @see ByteBuffer#putChar(int, char)
- *
- * @param index The index in the IoBuffer where we will put a char in
- * @param value The char to put at the current position
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putChar(int index, char value);
-
- /**
- * @see ByteBuffer#asCharBuffer()
- *
- * @return a new CharBuffer
- */
- public abstract CharBuffer asCharBuffer();
-
- /**
- * @see ByteBuffer#getShort()
- *
- * @return The read short
- */
- public abstract short getShort();
-
- /**
- * Reads two bytes unsigned integer.
- *
- * @return The read unsigned short
- */
- public abstract int getUnsignedShort();
-
- /**
- * @see ByteBuffer#putShort(short)
- *
- * @param value The short to put at the current position
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putShort(short value);
-
- /**
- * @see ByteBuffer#getShort()
- *
- * @param index The index in the IoBuffer where we will read a short from
- * @return The read short
- */
- public abstract short getShort(int index);
-
- /**
- * Reads two bytes unsigned integer.
- *
- * @param index The index in the IoBuffer where we will read an unsigned short \
from
- * @return the unsigned short at the given position
- */
- public abstract int getUnsignedShort(int index);
-
- /**
- * @see ByteBuffer#putShort(int, short)
- *
- * @param index The position at which the short should be written
- * @param value The short to put at the current position
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putShort(int index, short value);
-
- /**
- * @see ByteBuffer#asShortBuffer()
- *
- * @return A ShortBuffer from this IoBuffer
- */
- public abstract ShortBuffer asShortBuffer();
-
- /**
- * @see ByteBuffer#getInt()
- *
- * @return The int read
- */
- public abstract int getInt();
-
- /**
- * Reads four bytes unsigned integer.
- *
- * @return The unsigned int read
- */
- public abstract long getUnsignedInt();
-
- /**
- * Relative <i>get</i> method for reading a medium int value.
- *
- * <p>
- * Reads the next three bytes at this buffer's current position, composing
- * them into an int value according to the current byte order, and then
- * increments the position by three.
- *
- * @return The medium int value at the buffer's current position
- */
- public abstract int getMediumInt();
-
- /**
- * Relative <i>get</i> method for reading an unsigned medium int value.
- *
- * <p>
- * Reads the next three bytes at this buffer's current position, composing
- * them into an int value according to the current byte order, and then
- * increments the position by three.
- *
- * @return The unsigned medium int value at the buffer's current position
- */
- public abstract int getUnsignedMediumInt();
-
- /**
- * Absolute <i>get</i> method for reading a medium int value.
- *
- * <p>
- * Reads the next three bytes at this buffer's current position, composing
- * them into an int value according to the current byte order.
- *
- * @param index The index from which the medium int will be read
- * @return The medium int value at the given index
- *
- * @throws IndexOutOfBoundsException
- * If <tt>index</tt> is negative or not smaller than the
- * buffer's limit
- */
- public abstract int getMediumInt(int index);
-
- /**
- * Absolute <i>get</i> method for reading an unsigned medium int value.
- *
- * <p>
- * Reads the next three bytes at this buffer's current position, composing
- * them into an int value according to the current byte order.
- *
- * @param index The index from which the unsigned medium int will be read
- * @return The unsigned medium int value at the given index
- *
- * @throws IndexOutOfBoundsException
- * If <tt>index</tt> is negative or not smaller than the
- * buffer's limit
- */
- public abstract int getUnsignedMediumInt(int index);
-
- /**
- * Relative <i>put</i> method for writing a medium int value.
- *
- * <p>
- * Writes three bytes containing the given int value, in the current byte
- * order, into this buffer at the current position, and then increments the
- * position by three.
- *
- * @param value The medium int value to be written
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putMediumInt(int value);
-
- /**
- * Absolute <i>put</i> method for writing a medium int value.
- *
- * <p>
- * Writes three bytes containing the given int value, in the current byte
- * order, into this buffer at the given index.
- *
- * @param index The index at which the bytes will be written
- *
- * @param value The medium int value to be written
- *
- * @return the modified IoBuffer
- *
- * @throws IndexOutOfBoundsException
- * If <tt>index</tt> is negative or not smaller than the
- * buffer's limit, minus three
- */
- public abstract IoBuffer putMediumInt(int index, int value);
-
- /**
- * @see ByteBuffer#putInt(int)
- *
- * @param value The int to put at the current position
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putInt(int value);
-
- /**
- * Writes an unsigned byte into the ByteBuffer
- *
- * @param value the byte to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsigned(byte value);
-
- /**
- * Writes an unsigned byte into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the byte to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsigned(int index, byte value);
-
- /**
- * Writes an unsigned byte into the ByteBuffer
- *
- * @param value the short to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsigned(short value);
-
- /**
- * Writes an unsigned byte into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the short to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsigned(int index, short value);
-
- /**
- * Writes an unsigned byte into the ByteBuffer
- *
- * @param value the int to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsigned(int value);
-
- /**
- * Writes an unsigned byte into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the int to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsigned(int index, int value);
-
- /**
- * Writes an unsigned byte into the ByteBuffer
- *
- * @param value the long to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsigned(long value);
-
- /**
- * Writes an unsigned byte into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the long to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsigned(int index, long value);
-
- /**
- * Writes an unsigned int into the ByteBuffer
- * @param value the byte to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedInt(byte value);
-
- /**
- * Writes an unsigned int into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the byte to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedInt(int index, byte value);
-
- /**
- * Writes an unsigned int into the ByteBuffer
- *
- * @param value the short to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedInt(short value);
-
- /**
- * Writes an unsigned int into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the short to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedInt(int index, short value);
-
- /**
- * Writes an unsigned int into the ByteBuffer
- *
- * @param value the int to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedInt(int value);
-
- /**
- * Writes an unsigned int into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the int to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedInt(int index, int value);
-
- /**
- * Writes an unsigned int into the ByteBuffer
- *
- * @param value the long to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedInt(long value);
-
- /**
- * Writes an unsigned int into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the long to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedInt(int index, long value);
-
- /**
- * Writes an unsigned short into the ByteBuffer
- *
- * @param value the byte to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedShort(byte value);
-
- /**
- * Writes an unsigned Short into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the byte to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedShort(int index, byte value);
-
- /**
- * Writes an unsigned Short into the ByteBuffer
- *
- * @param value the short to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedShort(short value);
-
- /**
- * Writes an unsigned Short into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the unsigned short
- * @param value the unsigned short to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedShort(int index, short value);
-
- /**
- * Writes an unsigned Short into the ByteBuffer
- *
- * @param value the int to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedShort(int value);
-
- /**
- * Writes an unsigned Short into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the value
- * @param value the int to write
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedShort(int index, int value);
-
- /**
- * Writes an unsigned Short into the ByteBuffer
- *
- * @param value the long to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedShort(long value);
-
- /**
- * Writes an unsigned Short into the ByteBuffer at a specified position
- *
- * @param index the position in the buffer to write the short
- * @param value the long to write
- *
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putUnsignedShort(int index, long value);
-
- /**
- * @see ByteBuffer#getInt(int)
- * @param index The index in the IoBuffer where we will read an int from
- * @return the int at the given position
- */
- public abstract int getInt(int index);
-
- /**
- * Reads four bytes unsigned integer.
- * @param index The index in the IoBuffer where we will read an unsigned int \
from
- * @return The long at the given position
- */
- public abstract long getUnsignedInt(int index);
-
- /**
- * @see ByteBuffer#putInt(int, int)
- *
- * @param index The position where to put the int
- * @param value The int to put in the IoBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putInt(int index, int value);
-
- /**
- * @see ByteBuffer#asIntBuffer()
- *
- * @return the modified IoBuffer
- */
- public abstract IntBuffer asIntBuffer();
-
- /**
- * @see ByteBuffer#getLong()
- *
- * @return The long at the current position
- */
- public abstract long getLong();
-
- /**
- * @see ByteBuffer#putLong(int, long)
- *
- * @param value The log to put in the IoBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putLong(long value);
-
- /**
- * @see ByteBuffer#getLong(int)
- *
- * @param index The index in the IoBuffer where we will read a long from
- * @return the long at the given position
- */
- public abstract long getLong(int index);
-
- /**
- * @see ByteBuffer#putLong(int, long)
- *
- * @param index The position where to put the long
- * @param value The long to put in the IoBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putLong(int index, long value);
-
- /**
- * @see ByteBuffer#asLongBuffer()
- *
- * @return a LongBuffer from this IoBffer
- */
- public abstract LongBuffer asLongBuffer();
-
- /**
- * @see ByteBuffer#getFloat()
- *
- * @return the float at the current position
- */
- public abstract float getFloat();
-
- /**
- * @see ByteBuffer#putFloat(float)
- *
- * @param value The float to put in the IoBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putFloat(float value);
-
- /**
- * @see ByteBuffer#getFloat(int)
- *
- * @param index The index in the IoBuffer where we will read a float from
- * @return The float at the given position
- */
- public abstract float getFloat(int index);
-
- /**
- * @see ByteBuffer#putFloat(int, float)
- *
- * @param index The position where to put the float
- * @param value The float to put in the IoBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putFloat(int index, float value);
-
- /**
- * @see ByteBuffer#asFloatBuffer()
- *
- * @return A FloatBuffer from this IoBuffer
- */
- public abstract FloatBuffer asFloatBuffer();
-
- /**
- * @see ByteBuffer#getDouble()
- *
- * @return the double at the current position
- */
- public abstract double getDouble();
-
- /**
- * @see ByteBuffer#putDouble(double)
- *
- * @param value The double to put at the IoBuffer current position
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putDouble(double value);
-
- /**
- * @see ByteBuffer#getDouble(int)
- *
- * @param index The position where to get the double from
- * @return The double at the given position
- */
- public abstract double getDouble(int index);
-
- /**
- * @see ByteBuffer#putDouble(int, double)
- *
- * @param index The position where to put the double
- * @param value The double to put in the IoBuffer
- * @return the modified IoBuffer
- */
- public abstract IoBuffer putDouble(int index, double value);
-
- /**
- * @see ByteBuffer#asDoubleBuffer()
- *
- * @return A buffer containing Double
- */
- public abstract DoubleBuffer asDoubleBuffer();
-
- /**
- * @return an {@link InputStream} that reads the data from this buffer.
- * {@link InputStream#read()} returns <tt>-1</tt> if the buffer position
- * reaches to the limit.
- */
- public abstract InputStream asInputStream();
-
- /**
- * @return an {@link OutputStream} that appends the data into this buffer.
- * Please note that the {@link OutputStream#write(int)} will throw a
- * {@link BufferOverflowException} instead of an {@link IOException} in case
- * of buffer overflow. Please set <tt>autoExpand</tt> property by calling
- * {@link #setAutoExpand(boolean)} to prevent the unexpected runtime
- * exception.
- */
- public abstract OutputStream asOutputStream();
-
- /**
- * Returns hexdump of this buffer. The data and pointer are not changed as a
- * result of this method call.
- *
- * @return hexidecimal representation of this buffer
- */
- public abstract String getHexDump();
-
- /**
- * Return hexdump of this buffer with limited length.
- *
- * @param lengthLimit
- * The maximum number of bytes to dump from the current buffer
- * position.
- * @return hexidecimal representation of this buffer
- */
- public abstract String getHexDump(int lengthLimit);
-
- // //////////////////////////////
- // String getters and putters //
- // //////////////////////////////
-
- /**
- * Reads a <code>NUL</code>-terminated string from this buffer using the
- * specified <code>decoder</code> and returns it. This method reads until
- * the limit of this buffer if no <tt>NUL</tt> is found.
- *
- * @param decoder The {@link CharsetDecoder} to use
- * @return the read String
- * @exception CharacterCodingException Thrown when an error occurred while \
decoding the buffer
- */
- public abstract String getString(CharsetDecoder decoder) throws \
CharacterCodingException;
-
- /**
- * Reads a <code>NUL</code>-terminated string from this buffer using the
- * specified <code>decoder</code> and returns it.
- *
- * @param fieldSize the maximum number of bytes to read
- * @param decoder The {@link CharsetDecoder} to use
- * @return the read String
- * @exception CharacterCodingException Thrown when an error occurred while \
decoding the buffer
- */
- public abstract String getString(int fieldSize, CharsetDecoder decoder) throws \
CharacterCodingException;
-
- /**
- * Writes the content of <code>in</code> into this buffer using the
- * specified <code>encoder</code>. This method doesn't terminate string with
- * <tt>NUL</tt>. You have to do it by yourself.
- *
- * @param val The CharSequence to put in the IoBuffer
- * @param encoder The CharsetEncoder to use
- * @return The modified IoBuffer
- * @throws CharacterCodingException When we have an error while decoding the \
String
- */
- public abstract IoBuffer putString(CharSequence val, CharsetEncoder encoder) \
throws CharacterCodingException;
-
- /**
- * Writes the content of <code>in</code> into this buffer as a
- * <code>NUL</code>-terminated string using the specified
- * <code>encoder</code>.
- * <p>
- * If the charset name of the encoder is UTF-16, you cannot specify odd
- * <code>fieldSize</code>, and this method will append two <code>NUL</code>s
- * as a terminator.
- * <p>
- * Please note that this method doesn't terminate with <code>NUL</code> if
- * the input string is longer than <tt>fieldSize</tt>.
- *
- * @param val The CharSequence to put in the IoBuffer
- * @param fieldSize the maximum number of bytes to write
- * @param encoder The CharsetEncoder to use
- * @return The modified IoBuffer
- * @throws CharacterCodingException When we have an error while decoding the \
String
- */
- public abstract IoBuffer putString(CharSequence val, int fieldSize, \
CharsetEncoder encoder)
- throws CharacterCodingException;
-
- /**
- * Reads a string which has a 16-bit length field before the actual encoded
- * string, using the specified <code>decoder</code> and returns it. This
- * method is a shortcut for <tt>getPrefixedString(2, decoder)</tt>.
- *
- * @param decoder The CharsetDecoder to use
- * @return The read String
- *
- * @throws CharacterCodingException When we have an error while decoding the \
String
- */
- public abstract String getPrefixedString(CharsetDecoder decoder) throws \
CharacterCodingException;
-
- /**
- * Reads a string which has a length field before the actual encoded string,
- * using the specified <code>decoder</code> and returns it.
- *
- * @param prefixLength the length of the length field (1, 2, or 4)
- * @param decoder The CharsetDecoder to use
- * @return The read String
- *
- * @throws CharacterCodingException When we have an error while decoding the \
String
- */
- public abstract String getPrefixedString(int prefixLength, CharsetDecoder \
decoder) throws CharacterCodingException;
-
- /**
- * Writes the content of <code>in</code> into this buffer as a string which
- * has a 16-bit length field before the actual encoded string, using the
- * specified <code>encoder</code>. This method is a shortcut for
- * <tt>putPrefixedString(in, 2, 0, encoder)</tt>.
- *
- * @param in The CharSequence to put in the IoBuffer
- * @param encoder The CharsetEncoder to use
- * @return The modified IoBuffer
- *
- * @throws CharacterCodingException When we have an error while decoding the \
CharSequence
- */
- public abstract IoBuffer putPrefixedString(CharSequence in, CharsetEncoder \
encoder) throws CharacterCodingException;
-
- /**
- * Writes the content of <code>in</code> into this buffer as a string which
- * has a 16-bit length field before the actual encoded string, using the
- * specified <code>encoder</code>. This method is a shortcut for
- * <tt>putPrefixedString(in, prefixLength, 0, encoder)</tt>.
- *
- * @param in The CharSequence to put in the IoBuffer
- * @param prefixLength the length of the length field (1, 2, or 4)
- * @param encoder The CharsetEncoder to use
- * @return The modified IoBuffer
- *
- * @throws CharacterCodingException When we have an error while decoding the \
CharSequence
- */
- public abstract IoBuffer putPrefixedString(CharSequence in, int prefixLength, \
CharsetEncoder encoder)
- throws CharacterCodingException;
-
- /**
- * Writes the content of <code>in</code> into this buffer as a string which
- * has a 16-bit length field before the actual encoded string, using the
- * specified <code>encoder</code>. This method is a shortcut for
- * <tt>putPrefixedString(in, prefixLength, padding, ( byte ) 0, encoder)</tt>
- *
- * @param in The CharSequence to put in the IoBuffer
- * @param prefixLength the length of the length field (1, 2, or 4)
- * @param padding the number of padded <tt>NUL</tt>s (1 (or 0), 2, or 4)
- * @param encoder The CharsetEncoder to use
- * @return The modified IoBuffer
- *
- * @throws CharacterCodingException When we have an error while decoding the \
CharSequence
- */
- public abstract IoBuffer putPrefixedString(CharSequence in, int prefixLength, \
int padding, CharsetEncoder encoder)
- throws CharacterCodingException;
-
- /**
- * Writes the content of <code>val</code> into this buffer as a string which
- * has a 16-bit length field before the actual encoded string, using the
- * specified <code>encoder</code>.
- *
- * @param val The CharSequence to put in teh IoBuffer
- * @param prefixLength the length of the length field (1, 2, or 4)
- * @param padding the number of padded bytes (1 (or 0), 2, or 4)
- * @param padValue the value of padded bytes
- * @param encoder The CharsetEncoder to use
- * @return The modified IoBuffer
- * @throws CharacterCodingException When we have an error while decoding the \
CharSequence
- */
- public abstract IoBuffer putPrefixedString(CharSequence val, int prefixLength, \
int padding, byte padValue,
- CharsetEncoder encoder) throws CharacterCodingException;
-
- /**
- * Reads a Java object from the buffer using the context {@link ClassLoader}
- * of the current thread.
- *
- * @return The read Object
- * @throws ClassNotFoundException thrown when we can't find the Class to use
- */
- public abstract Object getObject() throws ClassNotFoundException;
-
- /**
- * Reads a Java object from the buffer using the specified
- * <tt>classLoader</tt>.
- *
- * @param classLoader The classLoader to use to read an Object from the IoBuffer
- * @return The read Object
- * @throws ClassNotFoundException thrown when we can't find the Class to use
- */
- public abstract Object getObject(final ClassLoader classLoader) throws \
ClassNotFoundException;
-
- /**
- * Writes the specified Java object to the buffer.
- *
- * @param o The Object to write in the IoBuffer
- * @return The modified IoBuffer
- */
- public abstract IoBuffer putObject(Object o);
-
- /**
- *
- * @param prefixLength the length of the prefix field (1, 2, or 4)
- * @return <tt>true</tt> if this buffer contains a data which has a data
- * length as a prefix and the buffer has remaining data as enough as
- * specified in the data length field. This method is identical with
- * <tt>prefixedDataAvailable( prefixLength, Integer.MAX_VALUE )</tt>. Please
- * not that using this method can allow DoS (Denial of Service) attack in
- * case the remote peer sends too big data length value. It is recommended
- * to use {@link #prefixedDataAvailable(int, int)} instead.
- * @throws IllegalArgumentException if prefixLength is wrong
- * @throws BufferDataException if data length is negative
- */
- public abstract boolean prefixedDataAvailable(int prefixLength);
-
- /**
- * @param prefixLength the length of the prefix field (1, 2, or 4)
- * @param maxDataLength the allowed maximum of the read data length
- * @return <tt>true</tt> if this buffer contains a data which has a data
- * length as a prefix and the buffer has remaining data as enough as
- * specified in the data length field.
- * @throws IllegalArgumentException
- * if prefixLength is wrong
- * @throws BufferDataException
- * if data length is negative or greater then
- * <tt>maxDataLength</tt>
- */
- public abstract boolean prefixedDataAvailable(int prefixLength, int \
maxDataLength);
-
- // ///////////////////
- // IndexOf methods //
- // ///////////////////
-
- /**
- * Returns the first occurrence position of the specified byte from the
- * current position to the current limit.
- *
- * @param b The byte we are looking for
- * @return <tt>-1</tt> if the specified byte is not found
- */
- public abstract int indexOf(byte b);
-
- // ////////////////////////
- // Skip or fill methods //
- // ////////////////////////
-
- /**
- * Forwards the position of this buffer as the specified <code>size</code>
- * bytes.
- *
- * @param size The added size
- * @return The modified IoBuffer
- */
- public abstract IoBuffer skip(int size);
-
- /**
- * Fills this buffer with the specified value. This method moves buffer
- * position forward.
- *
- * @param value The value to fill the IoBuffer with
- * @param size The added size
- * @return The modified IoBuffer
- */
- public abstract IoBuffer fill(byte value, int size);
-
- /**
- * Fills this buffer with the specified value. This method does not change
- * buffer position.
- *
- * @param value The value to fill the IoBuffer with
- * @param size The added size
- * @return The modified IoBuffer
- */
- public abstract IoBuffer fillAndReset(byte value, int size);
-
- /**
- * Fills this buffer with <code>NUL (0x00)</code>. This method moves buffer
- * position forward.
- *
- * @param size The added size
- * @return The modified IoBuffer
- */
- public abstract IoBuffer fill(int size);
-
- /**
- * Fills this buffer with <code>NUL (0x00)</code>. This method does not
- * change buffer position.
- *
- * @param size The added size
- * @return The modified IoBuffer
- */
- public abstract IoBuffer fillAndReset(int size);
-
- // ////////////////////////
- // Enum methods //
- // ////////////////////////
-
- /**
- * Reads a byte from the buffer and returns the correlating enum constant
- * defined by the specified enum type.
- *
- * @param <E> The enum type to return
- * @param enumClass The enum's class object
- * @return The correlated enum constant
- */
- public abstract <E extends Enum<E>> E getEnum(Class<E> enumClass);
-
- /**
- * Reads a byte from the buffer and returns the correlating enum constant
- * defined by the specified enum type.
- *
- * @param <E> The enum type to return
- * @param index the index from which the byte will be read
- * @param enumClass The enum's class object
- * @return The correlated enum constant
- */
- public abstract <E extends Enum<E>> E getEnum(int index, Class<E> enumClass);
-
- /**
- * Reads a short from the buffer and returns the correlating enum constant
- * defined by the specified enum type.
- *
- * @param <E> The enum type to return
- * @param enumClass The enum's class object
- * @return The correlated enum constant
- */
- public abstract <E extends Enum<E>> E getEnumShort(Class<E> enumClass);
-
- /**
- * Reads a short from the buffer and returns the correlating enum constant
- * defined by the specified enum type.
- *
- * @param <E> The enum type to return
- * @param index the index from which the bytes will be read
- * @param enumClass The enum's class object
- * @return The correlated enum constant
- */
- public abstract <E extends Enum<E>> E getEnumShort(int index, Class<E> \
enumClass);
-
- /**
- * Reads an int from the buffer and returns the correlating enum constant
- * defined by the specified enum type.
- *
- * @param <E> The enum type to return
- * @param enumClass The enum's class object
- * @return The correlated enum constant
- */
- public abstract <E extends Enum<E>> E getEnumInt(Class<E> enumClass);
-
- /**
- * Reads an int from the buffer and returns the correlating enum constant
- * defined by the specified enum type.
- *
- * @param <E> The enum type to return
- * @param index the index from which the bytes will be read
- * @param enumClass The enum's class object
- * @return The correlated enum constant
- */
- public abstract <E extends Enum<E>> E getEnumInt(int index, Class<E> enumClass);
-
- /**
- * Writes an enum's ordinal value to the buffer as a byte.
- *
- * @param e The enum to write to the buffer
- * @return The modified IoBuffer
- */
- public abstract IoBuffer putEnum(Enum<?> e);
-
- /**
- * Writes an enum's ordinal value to the buffer as a byte.
- *
- * @param index The index at which the byte will be written
- * @param e The enum to write to the buffer
- * @return The modified IoBuffer
- */
- public abstract IoBuffer putEnum(int index, Enum<?> e);
-
- /**
- * Writes an enum's ordinal value to the buffer as a short.
- *
- * @param e The enum to write to the buffer
- * @return The modified IoBuffer
- */
- public abstract IoBuffer putEnumShort(Enum<?> e);
-
- /**
- * Writes an enum's ordinal value to the buffer as a short.
- *
- * @param index The index at which the bytes will be written
- * @param e The enum to write to the buffer
- * @return The modified IoBuffer
- */
- public abstract IoBuffer putEnumShort(int index, Enum<?> e);
-
- /**
- * Writes an enum's ordinal value to the buffer as an integer.
- *
- * @param e The enum to write to the buffer
- * @return The modified IoBuffer
- */
- public abstract IoBuffer putEnumInt(Enum<?> e);
-
- /**
- * Writes an enum's ordinal value to the buffer as an integer.
- *
- * @param index The index at which the bytes will be written
- * @param e The enum to write to the buffer
- * @return The modified IoBuffer
- */
- public abstract IoBuffer putEnumInt(int index, Enum<?> e);
-
- // ////////////////////////
- // EnumSet methods //
- // ////////////////////////
-
- /**
- * Reads a byte sized bit vector and converts it to an {@link EnumSet}.
- *
- * <p>
- * Each bit is mapped to a value in the specified enum. The least
- * significant bit maps to the first entry in the specified enum and each
- * subsequent bit maps to each subsequent bit as mapped to the subsequent
- * enum value.
- *
- * @param <E> the enum type
- * @param enumClass the enum class used to create the EnumSet
- * @return the EnumSet representation of the bit vector
- */
- public abstract <E extends Enum<E>> Set<E> getEnumSet(Class<E> enumClass);
-
- /**
- * Reads a byte sized bit vector and converts it to an {@link EnumSet}.
- *
- * @see #getEnumSet(Class)
- * @param <E> the enum type
- * @param index the index from which the byte will be read
- * @param enumClass the enum class used to create the EnumSet
- * @return the EnumSet representation of the bit vector
- */
- public abstract <E extends Enum<E>> Set<E> getEnumSet(int index, Class<E> \
enumClass);
-
- /**
- * Reads a short sized bit vector and converts it to an {@link EnumSet}.
- *
- * @see #getEnumSet(Class)
- * @param <E> the enum type
- * @param enumClass the enum class used to create the EnumSet
- * @return the EnumSet representation of the bit vector
- */
- public abstract <E extends Enum<E>> Set<E> getEnumSetShort(Class<E> enumClass);
-
- /**
- * Reads a short sized bit vector and converts it to an {@link EnumSet}.
- *
- * @see #getEnumSet(Class)
- * @param <E> the enum type
- * @param index the index from which the bytes will be read
- * @param enumClass the enum class used to create the EnumSet
- * @return the EnumSet representation of the bit vector
- */
- public abstract <E extends Enum<E>> Set<E> getEnumSetShort(int index, Class<E> \
enumClass);
-
- /**
- * Reads an int sized bit vector and converts it to an {@link EnumSet}.
- *
- * @see #getEnumSet(Class)
- * @param <E> the enum type
- * @param enumClass the enum class used to create the EnumSet
- * @return the EnumSet representation of the bit vector
- */
- public abstract <E extends Enum<E>> Set<E> getEnumSetInt(Class<E> enumClass);
-
- /**
- * Reads an int sized bit vector and converts it to an {@link EnumSet}.
- *
- * @see #getEnumSet(Class)
- * @param <E> the enum type
- * @param index the index from which the bytes will be read
- * @param enumClass the enum class used to create the EnumSet
- * @return the EnumSet representation of the bit vector
- */
- public abstract <E extends Enum<E>> Set<E> getEnumSetInt(int index, Class<E> \
enumClass);
-
- /**
- * Reads a long sized bit vector and converts it to an {@link EnumSet}.
- *
- * @see #getEnumSet(Class)
- * @param <E> the enum type
- * @param enumClass the enum class used to create the EnumSet
- * @return the EnumSet representation of the bit vector
- */
- public abstract <E extends Enum<E>> Set<E> getEnumSetLong(Class<E> enumClass);
-
- /**
- * Reads a long sized bit vector and converts it to an {@link EnumSet}.
- *
- * @see #getEnumSet(Class)
- * @param <E> the enum type
- * @param index the index from which the bytes will be read
- * @param enumClass the enum class used to create the EnumSet
- * @return the EnumSet representation of the bit vector
- */
- public abstract <E extends Enum<E>> Set<E> getEnumSetLong(int index, Class<E> \
enumClass);
-
- /**
- * Writes the specified {@link Set} to the buffer as a byte sized bit
- * vector.
- *
- * @param <E> the enum type of the Set
- * @param set the enum set to write to the buffer
- * @return the modified IoBuffer
- */
- public abstract <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set);
-
- /**
- * Writes the specified {@link Set} to the buffer as a byte sized bit
- * vector.
- *
- * @param <E> the enum type of the Set
- * @param index the index at which the byte will be written
- * @param set the enum set to write to the buffer
- * @return the modified IoBuffer
- */
- public abstract <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set);
-
- /**
- * Writes the specified {@link Set} to the buffer as a short sized bit
- * vector.
- *
- * @param <E> the enum type of the Set
- * @param set the enum set to write to the buffer
- * @return the modified IoBuffer
- */
- public abstract <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set);
-
- /**
- * Writes the specified {@link Set} to the buffer as a short sized bit
- * vector.
- *
- * @param <E> the enum type of the Set
- * @param index the index at which the bytes will be written
- * @param set the enum set to write to the buffer
- * @return the modified IoBuffer
- */
- public abstract <E extends Enum<E>> IoBuffer putEnumSetShort(int index, Set<E> \
set);
-
- /**
- * Writes the specified {@link Set} to the buffer as an int sized bit
- * vector.
- *
- * @param <E> the enum type of the Set
- * @param set the enum set to write to the buffer
- * @return the modified IoBuffer
- */
- public abstract <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set);
-
- /**
- * Writes the specified {@link Set} to the buffer as an int sized bit
- * vector.
- *
- * @param <E> the enum type of the Set
- * @param index the index at which the bytes will be written
- * @param set the enum set to write to the buffer
- * @return the modified IoBuffer
- */
- public abstract <E extends Enum<E>> IoBuffer putEnumSetInt(int index, Set<E> \
set);
-
- /**
- * Writes the specified {@link Set} to the buffer as a long sized bit
- * vector.
- *
- * @param <E> the enum type of the Set
- * @param set the enum set to write to the buffer
- * @return the modified IoBuffer
- */
- public abstract <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set);
-
- /**
- * Writes the specified {@link Set} to the buffer as a long sized bit
- * vector.
- *
- * @param <E> the enum type of the Set
- * @param index the index at which the bytes will be written
- * @param set the enum set to write to the buffer
- * @return the modified IoBuffer
- */
- public abstract <E extends Enum<E>> IoBuffer putEnumSetLong(int index, Set<E> \
set); + /** The allocator used to create new buffers */
+ private static IoBufferAllocator allocator = new SimpleBufferAllocator();
+
+ /** A flag indicating which type of buffer we are using : heap or direct */
+ private static boolean useDirectBuffer = false;
+
+ /**
+ * Creates a new instance. This is an empty constructor. It's protected, to
+ * forbid its usage by the users.
+ */
+ protected IoBuffer() {
+ // Do nothing
+ }
+
+ /**
+ * @return the allocator used by existing and new buffers
+ */
+ public static IoBufferAllocator getAllocator() {
+ return allocator;
+ }
+
+ /**
+ * Sets the allocator used by existing and new buffers
+ *
+ * @param newAllocator the new allocator to use
+ */
+ public static void setAllocator(IoBufferAllocator newAllocator) {
+ if (newAllocator == null) {
+ throw new IllegalArgumentException("allocator");
+ }
+
+ IoBufferAllocator oldAllocator = allocator;
+
+ allocator = newAllocator;
+
+ if (null != oldAllocator) {
+ oldAllocator.dispose();
+ }
+ }
+
+ /**
+ * @return <tt>true</tt> if and only if a direct buffer is allocated by default
+ * when the type of the new buffer is not specified. The default value
+ * is <tt>false</tt>.
+ */
+ public static boolean isUseDirectBuffer() {
+ return useDirectBuffer;
+ }
+
+ /**
+ * Sets if a direct buffer should be allocated by default when the type of the
+ * new buffer is not specified. The default value is <tt>false</tt>.
+ *
+ * @param useDirectBuffer Tells if direct buffers should be allocated
+ */
+ public static void setUseDirectBuffer(boolean useDirectBuffer) {
+ IoBuffer.useDirectBuffer = useDirectBuffer;
+ }
+
+ /**
+ * Returns the direct or heap buffer which is capable to store the specified
+ * amount of bytes.
+ *
+ * @param capacity the capacity of the buffer
+ * @return a IoBuffer which can hold up to capacity bytes
+ *
+ * @see #setUseDirectBuffer(boolean)
+ */
+ public static IoBuffer allocate(int capacity) {
+ return allocate(capacity, useDirectBuffer);
+ }
+
+ /**
+ * Returns a direct or heap IoBuffer which can contain the specified number of
+ * bytes.
+ *
+ * @param capacity the capacity of the buffer
+ * @param useDirectBuffer <tt>true</tt> to get a direct buffer, <tt>false</tt>
+ * to get a heap buffer.
+ * @return a direct or heap IoBuffer which can hold up to capacity bytes
+ */
+ public static IoBuffer allocate(int capacity, boolean useDirectBuffer) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException("capacity: " + capacity);
+ }
+
+ return allocator.allocate(capacity, useDirectBuffer);
+ }
+
+ /**
+ * Wraps the specified NIO {@link ByteBuffer} into a MINA buffer (either direct
+ * or heap).
+ *
+ * @param nioBuffer The {@link ByteBuffer} to wrap
+ * @return a IoBuffer containing the bytes stored in the {@link ByteBuffer}
+ */
+ public static IoBuffer wrap(ByteBuffer nioBuffer) {
+ return allocator.wrap(nioBuffer);
+ }
+
+ /**
+ * Wraps the specified byte array into a MINA heap buffer. Note that the byte
+ * array is not copied, so any modification done on it will be visible by both
+ * sides.
+ *
+ * @param byteArray The byte array to wrap
+ * @return a heap IoBuffer containing the byte array
+ */
+ public static IoBuffer wrap(byte[] byteArray) {
+ return wrap(ByteBuffer.wrap(byteArray));
+ }
+
+ /**
+ * Wraps the specified byte array into MINA heap buffer. We just wrap the bytes
+ * starting from offset up to offset + length. Note that the byte array is not
+ * copied, so any modification done on it will be visible by both sides.
+ *
+ * @param byteArray The byte array to wrap
+ * @param offset The starting point in the byte array
+ * @param length The number of bytes to store
+ * @return a heap IoBuffer containing the selected part of the byte array
+ */
+ public static IoBuffer wrap(byte[] byteArray, int offset, int length) {
+ return wrap(ByteBuffer.wrap(byteArray, offset, length));
+ }
+
+ /**
+ * Normalizes the specified capacity of the buffer to power of 2, which is often
+ * helpful for optimal memory usage and performance. If it is greater than or
+ * equal to {@link Integer#MAX_VALUE}, it returns {@link Integer#MAX_VALUE}. If
+ * it is zero, it returns zero.
+ *
+ * @param requestedCapacity The IoBuffer capacity we want to be able to store
+ * @return The power of 2 strictly superior to the requested capacity
+ */
+ protected static int normalizeCapacity(int requestedCapacity) {
+ if (requestedCapacity < 0) {
+ return Integer.MAX_VALUE;
+ }
+
+ int newCapacity = Integer.highestOneBit(requestedCapacity);
+ newCapacity <<= (newCapacity < requestedCapacity ? 1 : 0);
+
+ return newCapacity < 0 ? Integer.MAX_VALUE : newCapacity;
+ }
+
+ /**
+ * Declares this buffer and all its derived buffers are not used anymore so that
+ * it can be reused by some {@link IoBufferAllocator} implementations. It is not
+ * mandatory to call this method, but you might want to invoke this method for
+ * maximum performance.
+ */
+ public abstract void free();
+
+ /**
+ * @return the underlying NIO {@link ByteBuffer} instance.
+ */
+ public abstract ByteBuffer buf();
+
+ /**
+ * @see ByteBuffer#isDirect()
+ *
+ * @return <tt>True</tt> if this is a direct buffer
+ */
+ public abstract boolean isDirect();
+
+ /**
+ * @return <tt>true</tt> if and only if this buffer is derived from another
+ * buffer via one of the {@link #duplicate()}, {@link #slice()} or
+ * {@link #asReadOnlyBuffer()} methods.
+ */
+ public abstract boolean isDerived();
+
+ /**
+ * @see ByteBuffer#isReadOnly()
+ *
+ * @return <tt>true</tt> if the buffer is readOnly
+ */
+ public abstract boolean isReadOnly();
+
+ /**
+ * @return the minimum capacity of this buffer which is used to determine the
+ * new capacity of the buffer shrunk by the {@link #compact()} and
+ * {@link #shrink()} operation. The default value is the initial
+ * capacity of the buffer.
+ */
+ public abstract int minimumCapacity();
+
+ /**
+ * Sets the minimum capacity of this buffer which is used to determine the new
+ * capacity of the buffer shrunk by {@link #compact()} and {@link #shrink()}
+ * operation. The default value is the initial capacity of the buffer.
+ *
+ * @param minimumCapacity the wanted minimum capacity
+ * @return the underlying NIO {@link ByteBuffer} instance.
+ */
+ public abstract IoBuffer minimumCapacity(int minimumCapacity);
+
+ /**
+ * @see ByteBuffer#capacity()
+ *
+ * @return the buffer capacity
+ */
+ public abstract int capacity();
+
+ /**
+ * Increases the capacity of this buffer. If the new capacity is less than or
+ * equal to the current capacity, this method returns the original buffer. If
+ * the new capacity is greater than the current capacity, the buffer is
+ * reallocated while retaining the position, limit, mark and the content of the
+ * buffer. <br>
+ * Note that the IoBuffer is replaced, it's not copied. <br>
+ * Assuming a buffer contains N bytes, its position is 0 and its current
+ * capacity is C, here are the resulting buffer if we set the new capacity to a
+ * value V < C and V > C :
+ *
+ * <pre>
+ * Initial buffer :
+ *
+ * 0 L C
+ * +--------+----------+
+ * |XXXXXXXX| |
+ * +--------+----------+
+ * ^ ^ ^
+ * | | |
+ * pos limit capacity
+ *
+ * V <= C :
+ *
+ * 0 L C
+ * +--------+----------+
+ * |XXXXXXXX| |
+ * +--------+----------+
+ * ^ ^ ^
+ * | | |
+ * pos limit newCapacity
+ *
+ * V > C :
+ *
+ * 0 L C V
+ * +--------+-----------------------+
+ * |XXXXXXXX| : |
+ * +--------+-----------------------+
+ * ^ ^ ^ ^
+ * | | | |
+ * pos limit oldCapacity newCapacity
+ *
+ * The buffer has been increased.
+ *
+ * </pre>
+ *
+ * @param newCapacity the wanted capacity
+ * @return the underlying NIO {@link ByteBuffer} instance.
+ */
+ public abstract IoBuffer capacity(int newCapacity);
+
+ /**
+ * @return <tt>true</tt> if and only if <tt>autoExpand</tt> is turned on.
+ */
+ public abstract boolean isAutoExpand();
+
+ /**
+ * Turns on or off <tt>autoExpand</tt>.
+ *
+ * @param autoExpand The flag value to set
+ * @return The modified IoBuffer instance
+ */
+ public abstract IoBuffer setAutoExpand(boolean autoExpand);
+
+ /**
+ * @return <tt>true</tt> if and only if <tt>autoShrink</tt> is turned on.
+ */
+ public abstract boolean isAutoShrink();
+
+ /**
+ * Turns on or off <tt>autoShrink</tt>.
+ *
+ * @param autoShrink The flag value to set
+ * @return The modified IoBuffer instance
+ */
+ public abstract IoBuffer setAutoShrink(boolean autoShrink);
+
+ /**
+ * Changes the capacity and limit of this buffer so this buffer get the
+ * specified <tt>expectedRemaining</tt> room from the current position. This
+ * method works even if you didn't set <tt>autoExpand</tt> to <tt>true</tt>.
+ * <br>
+ * Assuming a buffer contains N bytes, its position is P and its current
+ * capacity is C, here are the resulting buffer if we call the expand method
+ * with a expectedRemaining value V :
+ *
+ * <pre>
+ * Initial buffer :
+ *
+ * 0 L C
+ * +--------+----------+
+ * |XXXXXXXX| |
+ * +--------+----------+
+ * ^ ^ ^
+ * | | |
+ * pos limit capacity
+ *
+ * ( pos + V ) <= L, no change :
+ *
+ * 0 L C
+ * +--------+----------+
+ * |XXXXXXXX| |
+ * +--------+----------+
+ * ^ ^ ^
+ * | | |
+ * pos limit newCapacity
+ *
+ * You can still put ( L - pos ) bytes in the buffer
+ *
+ * ( pos + V ) > L & ( pos + V ) <= C :
+ *
+ * 0 L C
+ * +------------+------+
+ * |XXXXXXXX:...| |
+ * +------------+------+
+ * ^ ^ ^
+ * | | |
+ * pos newlimit newCapacity
+ *
+ * You can now put ( L - pos + V ) bytes in the buffer.
+ *
+ *
+ * ( pos + V ) > C
+ *
+ * 0 L C
+ * +-------------------+----+
+ * |XXXXXXXX:..........:....|
+ * +------------------------+
+ * ^ ^
+ * | |
+ * pos +-- newlimit
+ * |
+ * +-- newCapacity
+ *
+ * You can now put ( L - pos + V ) bytes in the buffer, which limit is now
+ * equals to the capacity.
+ * </pre>
+ *
+ * Note that the expecting remaining bytes starts at the current position. In
+ * all those examples, the position is 0.
+ *
+ * @param expectedRemaining The expected remaining bytes in the buffer
+ * @return The modified IoBuffer instance
+ */
+ public abstract IoBuffer expand(int expectedRemaining);
+
+ /**
+ * Changes the capacity and limit of this buffer so this buffer get the
+ * specified <tt>expectedRemaining</tt> room from the specified
+ * <tt>position</tt>. This method works even if you didn't set
+ * <tt>autoExpand</tt> to <tt>true</tt>. Assuming a buffer contains N bytes, its
+ * position is P and its current capacity is C, here are the resulting buffer if
+ * we call the expand method with a expectedRemaining value V :
+ *
+ * <pre>
+ * Initial buffer :
+ *
+ * P L C
+ * +--------+----------+
+ * |XXXXXXXX| |
+ * +--------+----------+
+ * ^ ^ ^
+ * | | |
+ * pos limit capacity
+ *
+ * ( pos + V ) <= L, no change :
+ *
+ * P L C
+ * +--------+----------+
+ * |XXXXXXXX| |
+ * +--------+----------+
+ * ^ ^ ^
+ * | | |
+ * pos limit newCapacity
+ *
+ * You can still put ( L - pos ) bytes in the buffer
+ *
+ * ( pos + V ) > L & ( pos + V ) <= C :
+ *
+ * P L C
+ * +------------+------+
+ * |XXXXXXXX:...| |
+ * +------------+------+
+ * ^ ^ ^
+ * | | |
+ * pos newlimit newCapacity
+ *
+ * You can now put ( L - pos + V) bytes in the buffer.
+ *
+ *
+ * ( pos + V ) > C
+ *
+ * P L C
+ * +-------------------+----+
+ * |XXXXXXXX:..........:....|
+ * +------------------------+
+ * ^ ^
+ * | |
+ * pos +-- newlimit
+ * |
+ * +-- newCapacity
+ *
+ * You can now put ( L - pos + V ) bytes in the buffer, which limit is now
+ * equals to the capacity.
+ * </pre>
+ *
+ * Note that the expecting remaining bytes starts at the current position. In
+ * all those examples, the position is P.
+ *
+ * @param position The starting position from which we want to define a
+ * remaining number of bytes
+ * @param expectedRemaining The expected remaining bytes in the buffer
+ * @return The modified IoBuffer instance
+ */
+ public abstract IoBuffer expand(int position, int expectedRemaining);
+
+ /**
+ * Changes the capacity of this buffer so this buffer occupies as less memory as
+ * possible while retaining the position, limit and the buffer content between
+ * the position and limit. <br>
+ * <b>The capacity of the buffer never becomes less than
+ * {@link #minimumCapacity()}</b> <br>
+ * . The mark is discarded once the capacity changes. <br>
+ * Typically, a call to this method tries to remove as much unused bytes as
+ * possible, dividing by two the initial capacity until it can't without
+ * obtaining a new capacity lower than the {@link #minimumCapacity()}. For
+ * instance, if the limit is 7 and the capacity is 36, with a minimum capacity
+ * of 8, shrinking the buffer will left a capacity of 9 (we go down from 36 to
+ * 18, then from 18 to 9).
+ *
+ * <pre>
+ * Initial buffer :
+ *
+ * +--------+----------+
+ * |XXXXXXXX| |
+ * +--------+----------+
+ * ^ ^ ^ ^
+ * | | | |
+ * pos | | capacity
+ * | |
+ * | +-- minimumCapacity
+ * |
+ * +-- limit
+ *
+ * Resulting buffer :
+ *
+ * +--------+--+-+
+ * |XXXXXXXX| | |
+ * +--------+--+-+
+ * ^ ^ ^ ^
+ * | | | |
+ * | | | +-- new capacity
+ * | | |
+ * pos | +-- minimum capacity
+ * |
+ * +-- limit
+ * </pre>
+ *
+ * @return The modified IoBuffer instance
+ */
+ public abstract IoBuffer shrink();
+
+ /**
+ * @see java.nio.Buffer#position()
+ * @return The current position in the buffer
+ */
+ public abstract int position();
+
+ /**
+ * @see java.nio.Buffer#position(int)
+ *
+ * @param newPosition Sets the new position in the buffer
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer position(int newPosition);
+
+ /**
+ * @see java.nio.Buffer#limit()
+ *
+ * @return the modified IoBuffer 's limit
+ */
+ public abstract int limit();
+
+ /**
+ * @see java.nio.Buffer#limit(int)
+ *
+ * @param newLimit The new buffer's limit
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer limit(int newLimit);
+
+ /**
+ * @see java.nio.Buffer#mark()
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer mark();
+
+ /**
+ * @return the position of the current mark. This method returns <tt>-1</tt> if
+ * no mark is set.
+ */
+ public abstract int markValue();
+
+ /**
+ * @see java.nio.Buffer#reset()
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer reset();
+
+ /**
+ * @see java.nio.Buffer#clear()
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer clear();
+
+ /**
+ * Clears this buffer and fills its content with <tt>NUL</tt>. The position is
+ * set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer sweep();
+
+ /**
+ * double Clears this buffer and fills its content with <tt>value</tt>. The
+ * position is set to zero, the limit is set to the capacity, and the mark is
+ * discarded.
+ *
+ * @param value The value to put in the buffer
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer sweep(byte value);
+
+ /**
+ * @see java.nio.Buffer#flip()
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer flip();
+
+ /**
+ * @see java.nio.Buffer#rewind()
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer rewind();
+
+ /**
+ * @see java.nio.Buffer#remaining()
+ *
+ * @return The remaining bytes in the buffer
+ */
+ public abstract int remaining();
+
+ /**
+ * @see java.nio.Buffer#hasRemaining()
+ *
+ * @return <tt>true</tt> if there are some remaining bytes in the buffer
+ */
+ public abstract boolean hasRemaining();
+
+ /**
+ * @see ByteBuffer#duplicate()
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer duplicate();
+
+ /**
+ * @see ByteBuffer#slice()
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer slice();
+
+ /**
+ * @see ByteBuffer#asReadOnlyBuffer()
+ *
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer asReadOnlyBuffer();
+
+ /**
+ * @see ByteBuffer#hasArray()
+ *
+ * @return <tt>true</tt> if the {@link #array()} method will return a byte[]
+ */
+ public abstract boolean hasArray();
+
+ /**
+ * @see ByteBuffer#array()
+ *
+ * @return A byte[] if this IoBuffer supports it
+ */
+ public abstract byte[] array();
+
+ /**
+ * @see ByteBuffer#arrayOffset()
+ *
+ * @return The offset in the returned byte[] when the {@link #array()} method is
+ * called
+ */
+ public abstract int arrayOffset();
+
+ /**
+ * @see ByteBuffer#get()
+ *
+ * @return The byte at the current position
+ */
+ public abstract byte get();
+
+ /**
+ * Reads one unsigned byte as a short integer.
+ *
+ * @return the unsigned short at the current position
+ */
+ public abstract short getUnsigned();
+
+ /**
+ * @see ByteBuffer#put(byte)
+ *
+ * @param b The byte to put in the buffer
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer put(byte b);
+
+ /**
+ * @see ByteBuffer#get(int)
+ *
+ * @param index The position for which we want to read a byte
+ * @return the byte at the given position
+ */
+ public abstract byte get(int index);
+
+ /**
+ * Reads one byte as an unsigned short integer.
+ *
+ * @param index The position for which we want to read an unsigned byte
+ * @return the unsigned byte at the given position
+ */
+ public abstract short getUnsigned(int index);
+
+ /**
+ * @see ByteBuffer#put(int, byte)
+ *
+ * @param index The position where the byte will be put
+ * @param b The byte to put
+ * @return the modified IoBuffer
+ *
+ */
+ public abstract IoBuffer put(int index, byte b);
+
+ /**
+ * @see ByteBuffer#get(byte[], int, int)
+ *
+ * @param dst The destination buffer
+ * @param offset The position in the original buffer
+ * @param length The number of bytes to copy
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer get(byte[] dst, int offset, int length);
+
+ /**
+ * @see ByteBuffer#get(byte[])
+ *
+ * @param dst The byte[] that will contain the read bytes
+ * @return the IoBuffer
+ */
+ public abstract IoBuffer get(byte[] dst);
+
+ /**
+ * Get a new IoBuffer containing a slice of the current buffer
+ *
+ * @param index The position in the buffer
+ * @param length The number of bytes to copy
+ * @return the new IoBuffer
+ */
+ public abstract IoBuffer getSlice(int index, int length);
+
+ /**
+ * Get a new IoBuffer containing a slice of the current buffer
+ *
+ * @param length The number of bytes to copy
+ * @return the new IoBuffer
+ */
+ public abstract IoBuffer getSlice(int length);
+
+ /**
+ * Writes the content of the specified <tt>src</tt> into this buffer.
+ *
+ * @param src The source ByteBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer put(ByteBuffer src);
+
+ /**
+ * Writes the content of the specified <tt>src</tt> into this buffer.
+ *
+ * @param src The source IoBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer put(IoBuffer src);
+
+ /**
+ * @see ByteBuffer#put(byte[], int, int)
+ *
+ * @param src The byte[] to put
+ * @param offset The position in the source
+ * @param length The number of bytes to copy
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer put(byte[] src, int offset, int length);
+
+ /**
+ * @see ByteBuffer#put(byte[])
+ *
+ * @param src The byte[] to put
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer put(byte[] src);
+
+ /**
+ * @see ByteBuffer#compact()
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer compact();
+
+ /**
+ * @see ByteBuffer#order()
+ *
+ * @return the IoBuffer ByteOrder
+ */
+ public abstract ByteOrder order();
+
+ /**
+ * @see ByteBuffer#order(ByteOrder)
+ *
+ * @param bo The new ByteBuffer to use for this IoBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer order(ByteOrder bo);
+
+ /**
+ * @see ByteBuffer#getChar()
+ *
+ * @return The char at the current position
+ */
+ public abstract char getChar();
+
+ /**
+ * @see ByteBuffer#putChar(char)
+ *
+ * @param value The char to put at the current position
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putChar(char value);
+
+ /**
+ * @see ByteBuffer#getChar(int)
+ *
+ * @param index The index in the IoBuffer where we will read a char from
+ * @return the char at 'index' position
+ */
+ public abstract char getChar(int index);
+
+ /**
+ * @see ByteBuffer#putChar(int, char)
+ *
+ * @param index The index in the IoBuffer where we will put a char in
+ * @param value The char to put at the current position
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putChar(int index, char value);
+
+ /**
+ * @see ByteBuffer#asCharBuffer()
+ *
+ * @return a new CharBuffer
+ */
+ public abstract CharBuffer asCharBuffer();
+
+ /**
+ * @see ByteBuffer#getShort()
+ *
+ * @return The read short
+ */
+ public abstract short getShort();
+
+ /**
+ * Reads two bytes unsigned integer.
+ *
+ * @return The read unsigned short
+ */
+ public abstract int getUnsignedShort();
+
+ /**
+ * @see ByteBuffer#putShort(short)
+ *
+ * @param value The short to put at the current position
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putShort(short value);
+
+ /**
+ * @see ByteBuffer#getShort()
+ *
+ * @param index The index in the IoBuffer where we will read a short from
+ * @return The read short
+ */
+ public abstract short getShort(int index);
+
+ /**
+ * Reads two bytes unsigned integer.
+ *
+ * @param index The index in the IoBuffer where we will read an unsigned short
+ * from
+ * @return the unsigned short at the given position
+ */
+ public abstract int getUnsignedShort(int index);
+
+ /**
+ * @see ByteBuffer#putShort(int, short)
+ *
+ * @param index The position at which the short should be written
+ * @param value The short to put at the current position
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putShort(int index, short value);
+
+ /**
+ * @see ByteBuffer#asShortBuffer()
+ *
+ * @return A ShortBuffer from this IoBuffer
+ */
+ public abstract ShortBuffer asShortBuffer();
+
+ /**
+ * @see ByteBuffer#getInt()
+ *
+ * @return The int read
+ */
+ public abstract int getInt();
+
+ /**
+ * Reads four bytes unsigned integer.
+ *
+ * @return The unsigned int read
+ */
+ public abstract long getUnsignedInt();
+
+ /**
+ * Relative <i>get</i> method for reading a medium int value.
+ *
+ * <p>
+ * Reads the next three bytes at this buffer's current position, composing them
+ * into an int value according to the current byte order, and then increments
+ * the position by three.
+ *
+ * @return The medium int value at the buffer's current position
+ */
+ public abstract int getMediumInt();
+
+ /**
+ * Relative <i>get</i> method for reading an unsigned medium int value.
+ *
+ * <p>
+ * Reads the next three bytes at this buffer's current position, composing them
+ * into an int value according to the current byte order, and then increments
+ * the position by three.
+ *
+ * @return The unsigned medium int value at the buffer's current position
+ */
+ public abstract int getUnsignedMediumInt();
+
+ /**
+ * Absolute <i>get</i> method for reading a medium int value.
+ *
+ * <p>
+ * Reads the next three bytes at this buffer's current position, composing them
+ * into an int value according to the current byte order.
+ *
+ * @param index The index from which the medium int will be read
+ * @return The medium int value at the given index
+ *
+ * @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
+ * smaller than the buffer's limit
+ */
+ public abstract int getMediumInt(int index);
+
+ /**
+ * Absolute <i>get</i> method for reading an unsigned medium int value.
+ *
+ * <p>
+ * Reads the next three bytes at this buffer's current position, composing them
+ * into an int value according to the current byte order.
+ *
+ * @param index The index from which the unsigned medium int will be read
+ * @return The unsigned medium int value at the given index
+ *
+ * @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
+ * smaller than the buffer's limit
+ */
+ public abstract int getUnsignedMediumInt(int index);
+
+ /**
+ * Relative <i>put</i> method for writing a medium int value.
+ *
+ * <p>
+ * Writes three bytes containing the given int value, in the current byte order,
+ * into this buffer at the current position, and then increments the position by
+ * three.
+ *
+ * @param value The medium int value to be written
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putMediumInt(int value);
+
+ /**
+ * Absolute <i>put</i> method for writing a medium int value.
+ *
+ * <p>
+ * Writes three bytes containing the given int value, in the current byte order,
+ * into this buffer at the given index.
+ *
+ * @param index The index at which the bytes will be written
+ *
+ * @param value The medium int value to be written
+ *
+ * @return the modified IoBuffer
+ *
+ * @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
+ * smaller than the buffer's limit, minus
+ * three
+ */
+ public abstract IoBuffer putMediumInt(int index, int value);
+
+ /**
+ * @see ByteBuffer#putInt(int)
+ *
+ * @param value The int to put at the current position
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putInt(int value);
+
+ /**
+ * Writes an unsigned byte into the ByteBuffer
+ *
+ * @param value the byte to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsigned(byte value);
+
+ /**
+ * Writes an unsigned byte into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the byte to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsigned(int index, byte value);
+
+ /**
+ * Writes an unsigned byte into the ByteBuffer
+ *
+ * @param value the short to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsigned(short value);
+
+ /**
+ * Writes an unsigned byte into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the short to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsigned(int index, short value);
+
+ /**
+ * Writes an unsigned byte into the ByteBuffer
+ *
+ * @param value the int to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsigned(int value);
+
+ /**
+ * Writes an unsigned byte into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the int to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsigned(int index, int value);
+
+ /**
+ * Writes an unsigned byte into the ByteBuffer
+ *
+ * @param value the long to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsigned(long value);
+
+ /**
+ * Writes an unsigned byte into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the long to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsigned(int index, long value);
+
+ /**
+ * Writes an unsigned int into the ByteBuffer
+ *
+ * @param value the byte to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedInt(byte value);
+
+ /**
+ * Writes an unsigned int into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the byte to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedInt(int index, byte value);
+
+ /**
+ * Writes an unsigned int into the ByteBuffer
+ *
+ * @param value the short to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedInt(short value);
+
+ /**
+ * Writes an unsigned int into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the short to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedInt(int index, short value);
+
+ /**
+ * Writes an unsigned int into the ByteBuffer
+ *
+ * @param value the int to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedInt(int value);
+
+ /**
+ * Writes an unsigned int into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the int to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedInt(int index, int value);
+
+ /**
+ * Writes an unsigned int into the ByteBuffer
+ *
+ * @param value the long to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedInt(long value);
+
+ /**
+ * Writes an unsigned int into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the long to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedInt(int index, long value);
+
+ /**
+ * Writes an unsigned short into the ByteBuffer
+ *
+ * @param value the byte to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedShort(byte value);
+
+ /**
+ * Writes an unsigned Short into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the byte to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedShort(int index, byte value);
+
+ /**
+ * Writes an unsigned Short into the ByteBuffer
+ *
+ * @param value the short to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedShort(short value);
+
+ /**
+ * Writes an unsigned Short into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the unsigned short
+ * @param value the unsigned short to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedShort(int index, short value);
+
+ /**
+ * Writes an unsigned Short into the ByteBuffer
+ *
+ * @param value the int to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedShort(int value);
+
+ /**
+ * Writes an unsigned Short into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the value
+ * @param value the int to write
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedShort(int index, int value);
+
+ /**
+ * Writes an unsigned Short into the ByteBuffer
+ *
+ * @param value the long to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedShort(long value);
+
+ /**
+ * Writes an unsigned Short into the ByteBuffer at a specified position
+ *
+ * @param index the position in the buffer to write the short
+ * @param value the long to write
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putUnsignedShort(int index, long value);
+
+ /**
+ * @see ByteBuffer#getInt(int)
+ * @param index The index in the IoBuffer where we will read an int from
+ * @return the int at the given position
+ */
+ public abstract int getInt(int index);
+
+ /**
+ * Reads four bytes unsigned integer.
+ *
+ * @param index The index in the IoBuffer where we will read an unsigned int
+ * from
+ * @return The long at the given position
+ */
+ public abstract long getUnsignedInt(int index);
+
+ /**
+ * @see ByteBuffer#putInt(int, int)
+ *
+ * @param index The position where to put the int
+ * @param value The int to put in the IoBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putInt(int index, int value);
+
+ /**
+ * @see ByteBuffer#asIntBuffer()
+ *
+ * @return the modified IoBuffer
+ */
+ public abstract IntBuffer asIntBuffer();
+
+ /**
+ * @see ByteBuffer#getLong()
+ *
+ * @return The long at the current position
+ */
+ public abstract long getLong();
+
+ /**
+ * @see ByteBuffer#putLong(int, long)
+ *
+ * @param value The log to put in the IoBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putLong(long value);
+
+ /**
+ * @see ByteBuffer#getLong(int)
+ *
+ * @param index The index in the IoBuffer where we will read a long from
+ * @return the long at the given position
+ */
+ public abstract long getLong(int index);
+
+ /**
+ * @see ByteBuffer#putLong(int, long)
+ *
+ * @param index The position where to put the long
+ * @param value The long to put in the IoBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putLong(int index, long value);
+
+ /**
+ * @see ByteBuffer#asLongBuffer()
+ *
+ * @return a LongBuffer from this IoBffer
+ */
+ public abstract LongBuffer asLongBuffer();
+
+ /**
+ * @see ByteBuffer#getFloat()
+ *
+ * @return the float at the current position
+ */
+ public abstract float getFloat();
+
+ /**
+ * @see ByteBuffer#putFloat(float)
+ *
+ * @param value The float to put in the IoBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putFloat(float value);
+
+ /**
+ * @see ByteBuffer#getFloat(int)
+ *
+ * @param index The index in the IoBuffer where we will read a float from
+ * @return The float at the given position
+ */
+ public abstract float getFloat(int index);
+
+ /**
+ * @see ByteBuffer#putFloat(int, float)
+ *
+ * @param index The position where to put the float
+ * @param value The float to put in the IoBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putFloat(int index, float value);
+
+ /**
+ * @see ByteBuffer#asFloatBuffer()
+ *
+ * @return A FloatBuffer from this IoBuffer
+ */
+ public abstract FloatBuffer asFloatBuffer();
+
+ /**
+ * @see ByteBuffer#getDouble()
+ *
+ * @return the double at the current position
+ */
+ public abstract double getDouble();
+
+ /**
+ * @see ByteBuffer#putDouble(double)
+ *
+ * @param value The double to put at the IoBuffer current position
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putDouble(double value);
+
+ /**
+ * @see ByteBuffer#getDouble(int)
+ *
+ * @param index The position where to get the double from
+ * @return The double at the given position
+ */
+ public abstract double getDouble(int index);
+
+ /**
+ * @see ByteBuffer#putDouble(int, double)
+ *
+ * @param index The position where to put the double
+ * @param value The double to put in the IoBuffer
+ * @return the modified IoBuffer
+ */
+ public abstract IoBuffer putDouble(int index, double value);
+
+ /**
+ * @see ByteBuffer#asDoubleBuffer()
+ *
+ * @return A buffer containing Double
+ */
+ public abstract DoubleBuffer asDoubleBuffer();
+
+ /**
+ * @return an {@link InputStream} that reads the data from this buffer.
+ * {@link InputStream#read()} returns <tt>-1</tt> if the buffer position
+ * reaches to the limit.
+ */
+ public abstract InputStream asInputStream();
+
+ /**
+ * @return an {@link OutputStream} that appends the data into this buffer.
+ * Please note that the {@link OutputStream#write(int)} will throw a
+ * {@link BufferOverflowException} instead of an {@link IOException} in
+ * case of buffer overflow. Please set <tt>autoExpand</tt> property by
+ * calling {@link #setAutoExpand(boolean)} to prevent the unexpected
+ * runtime exception.
+ */
+ public abstract OutputStream asOutputStream();
+
+ /**
+ * Returns hexdump of this buffer. The data and pointer are not changed as a
+ * result of this method call.
+ *
+ * @return hexidecimal representation of this buffer
+ */
+ public abstract String getHexDump();
+
+ /**
+ * Return hexdump of this buffer with limited length.
+ *
+ * @param lengthLimit The maximum number of bytes to dump from the current
+ * buffer position.
+ * @return hexidecimal representation of this buffer
+ */
+ public abstract String getHexDump(int lengthLimit);
+
+ /**
+ * Return hexdump of this buffer with limited length.
+ *
+ * @param lengthLimit The maximum number of bytes to dump from the current
+ * buffer position.
+ *
+ * @param pretty Produces multi-line pretty hex dumps
+ *
+ * @return hexidecimal representation of this buffer
+ */
+ public abstract String getHexDump(int lengthLimit, boolean pretty);
+
+ // //////////////////////////////
+ // String getters and putters //
+ // //////////////////////////////
+
+ /**
+ * Reads a <code>NUL</code>-terminated string from this buffer using the
+ * specified <code>decoder</code> and returns it. This method reads until the
+ * limit of this buffer if no <tt>NUL</tt> is found.
+ *
+ * @param decoder The {@link CharsetDecoder} to use
+ * @return the read String
+ * @exception CharacterCodingException Thrown when an error occurred while
+ * decoding the buffer
+ */
+ public abstract String getString(CharsetDecoder decoder) throws \
CharacterCodingException; +
+ /**
+ * Reads a <code>NUL</code>-terminated string from this buffer using the
+ * specified <code>decoder</code> and returns it.
+ *
+ * @param fieldSize the maximum number of bytes to read
+ * @param decoder The {@link CharsetDecoder} to use
+ * @return the read String
+ * @exception CharacterCodingException Thrown when an error occurred while
+ * decoding the buffer
+ */
+ public abstract String getString(int fieldSize, CharsetDecoder decoder) throws \
CharacterCodingException; +
+ /**
+ * Writes the content of <code>in</code> into this buffer using the specified
+ * <code>encoder</code>. This method doesn't terminate string with <tt>NUL</tt>.
+ * You have to do it by yourself.
+ *
+ * @param val The CharSequence to put in the IoBuffer
+ * @param encoder The CharsetEncoder to use
+ * @return The modified IoBuffer
+ * @throws CharacterCodingException When we have an error while decoding the
+ * String
+ */
+ public abstract IoBuffer putString(CharSequence val, CharsetEncoder encoder) throws \
CharacterCodingException; +
+ /**
+ * Writes the content of <code>in</code> into this buffer as a
+ * <code>NUL</code>-terminated string using the specified <code>encoder</code>.
+ * <p>
+ * If the charset name of the encoder is UTF-16, you cannot specify odd
+ * <code>fieldSize</code>, and this method will append two <code>NUL</code>s as
+ * a terminator.
+ * <p>
+ * Please note that this method doesn't terminate with <code>NUL</code> if the
+ * input string is longer than <tt>fieldSize</tt>.
+ *
+ * @param val The CharSequence to put in the IoBuffer
+ * @param fieldSize the maximum number of bytes to write
+ * @param encoder The CharsetEncoder to use
+ * @return The modified IoBuffer
+ * @throws CharacterCodingException When we have an error while decoding the
+ * String
+ */
+ public abstract IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder \
encoder) + throws CharacterCodingException;
+
+ /**
+ * Reads a string which has a 16-bit length field before the actual encoded
+ * string, using the specified <code>decoder</code> and returns it. This method
+ * is a shortcut for <tt>getPrefixedString(2, decoder)</tt>.
+ *
+ * @param decoder The CharsetDecoder to use
+ * @return The read String
+ *
+ * @throws CharacterCodingException When we have an error while decoding the
+ * String
+ */
+ public abstract String getPrefixedString(CharsetDecoder decoder) throws \
CharacterCodingException; +
+ /**
+ * Reads a string which has a length field before the actual encoded string,
+ * using the specified <code>decoder</code> and returns it.
+ *
+ * @param prefixLength the length of the length field (1, 2, or 4)
+ * @param decoder The CharsetDecoder to use
+ * @return The read String
+ *
+ * @throws CharacterCodingException When we have an error while decoding the
+ * String
+ */
+ public abstract String getPrefixedString(int prefixLength, CharsetDecoder decoder) \
throws CharacterCodingException; +
+ /**
+ * Writes the content of <code>in</code> into this buffer as a string which has
+ * a 16-bit length field before the actual encoded string, using the specified
+ * <code>encoder</code>. This method is a shortcut for
+ * <tt>putPrefixedString(in, 2, 0, encoder)</tt>.
+ *
+ * @param in The CharSequence to put in the IoBuffer
+ * @param encoder The CharsetEncoder to use
+ * @return The modified IoBuffer
+ *
+ * @throws CharacterCodingException When we have an error while decoding the
+ * CharSequence
+ */
+ public abstract IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) \
throws CharacterCodingException; +
+ /**
+ * Writes the content of <code>in</code> into this buffer as a string which has
+ * a 16-bit length field before the actual encoded string, using the specified
+ * <code>encoder</code>. This method is a shortcut for
+ * <tt>putPrefixedString(in, prefixLength, 0, encoder)</tt>.
+ *
+ * @param in The CharSequence to put in the IoBuffer
+ * @param prefixLength the length of the length field (1, 2, or 4)
+ * @param encoder The CharsetEncoder to use
+ * @return The modified IoBuffer
+ *
+ * @throws CharacterCodingException When we have an error while decoding the
+ * CharSequence
+ */
+ public abstract IoBuffer putPrefixedString(CharSequence in, int prefixLength, \
CharsetEncoder encoder) + throws CharacterCodingException;
+
+ /**
+ * Writes the content of <code>in</code> into this buffer as a string which has
+ * a 16-bit length field before the actual encoded string, using the specified
+ * <code>encoder</code>. This method is a shortcut for
+ * <tt>putPrefixedString(in, prefixLength, padding, ( byte ) 0, encoder)</tt>
+ *
+ * @param in The CharSequence to put in the IoBuffer
+ * @param prefixLength the length of the length field (1, 2, or 4)
+ * @param padding the number of padded <tt>NUL</tt>s (1 (or 0), 2, or 4)
+ * @param encoder The CharsetEncoder to use
+ * @return The modified IoBuffer
+ *
+ * @throws CharacterCodingException When we have an error while decoding the
+ * CharSequence
+ */
+ public abstract IoBuffer putPrefixedString(CharSequence in, int prefixLength, int \
padding, CharsetEncoder encoder) + throws CharacterCodingException;
+
+ /**
+ * Writes the content of <code>val</code> into this buffer as a string which has
+ * a 16-bit length field before the actual encoded string, using the specified
+ * <code>encoder</code>.
+ *
+ * @param val The CharSequence to put in teh IoBuffer
+ * @param prefixLength the length of the length field (1, 2, or 4)
+ * @param padding the number of padded bytes (1 (or 0), 2, or 4)
+ * @param padValue the value of padded bytes
+ * @param encoder The CharsetEncoder to use
+ * @return The modified IoBuffer
+ * @throws CharacterCodingException When we have an error while decoding the
+ * CharSequence
+ */
+ public abstract IoBuffer putPrefixedString(CharSequence val, int prefixLength, int \
padding, byte padValue, + CharsetEncoder encoder) throws CharacterCodingException;
+
+ /**
+ * Reads a Java object from the buffer using the context {@link ClassLoader} of
+ * the current thread.
+ *
+ * @return The read Object
+ * @throws ClassNotFoundException thrown when we can't find the Class to use
+ */
+ public abstract Object getObject() throws ClassNotFoundException;
+
+ /**
+ * Reads a Java object from the buffer using the specified <tt>classLoader</tt>.
+ *
+ * @param classLoader The classLoader to use to read an Object from the IoBuffer
+ * @return The read Object
+ * @throws ClassNotFoundException thrown when we can't find the Class to use
+ */
+ public abstract Object getObject(final ClassLoader classLoader) throws \
ClassNotFoundException; +
+ /**
+ * Writes the specified Java object to the buffer.
+ *
+ * @param o The Object to write in the IoBuffer
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer putObject(Object o);
+
+ /**
+ *
+ * @param prefixLength the length of the prefix field (1, 2, or 4)
+ * @return <tt>true</tt> if this buffer contains a data which has a data length
+ * as a prefix and the buffer has remaining data as enough as specified
+ * in the data length field. This method is identical with
+ * <tt>prefixedDataAvailable( prefixLength, Integer.MAX_VALUE )</tt>.
+ * Please not that using this method can allow DoS (Denial of Service)
+ * attack in case the remote peer sends too big data length value. It is
+ * recommended to use {@link #prefixedDataAvailable(int, int)} instead.
+ * @throws IllegalArgumentException if prefixLength is wrong
+ * @throws BufferDataException if data length is negative
+ */
+ public abstract boolean prefixedDataAvailable(int prefixLength);
+
+ /**
+ * @param prefixLength the length of the prefix field (1, 2, or 4)
+ * @param maxDataLength the allowed maximum of the read data length
+ * @return <tt>true</tt> if this buffer contains a data which has a data length
+ * as a prefix and the buffer has remaining data as enough as specified
+ * in the data length field.
+ * @throws IllegalArgumentException if prefixLength is wrong
+ * @throws BufferDataException if data length is negative or greater then
+ * <tt>maxDataLength</tt>
+ */
+ public abstract boolean prefixedDataAvailable(int prefixLength, int maxDataLength);
+
+ // ///////////////////
+ // IndexOf methods //
+ // ///////////////////
+
+ /**
+ * Returns the first occurrence position of the specified byte from the current
+ * position to the current limit.
+ *
+ * @param b The byte we are looking for
+ * @return <tt>-1</tt> if the specified byte is not found
+ */
+ public abstract int indexOf(byte b);
+
+ // ////////////////////////
+ // Skip or fill methods //
+ // ////////////////////////
+
+ /**
+ * Forwards the position of this buffer as the specified <code>size</code>
+ * bytes.
+ *
+ * @param size The added size
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer skip(int size);
+
+ /**
+ * Fills this buffer with the specified value. This method moves buffer position
+ * forward.
+ *
+ * @param value The value to fill the IoBuffer with
+ * @param size The added size
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer fill(byte value, int size);
+
+ /**
+ * Fills this buffer with the specified value. This method does not change
+ * buffer position.
+ *
+ * @param value The value to fill the IoBuffer with
+ * @param size The added size
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer fillAndReset(byte value, int size);
+
+ /**
+ * Fills this buffer with <code>NUL (0x00)</code>. This method moves buffer
+ * position forward.
+ *
+ * @param size The added size
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer fill(int size);
+
+ /**
+ * Fills this buffer with <code>NUL (0x00)</code>. This method does not change
+ * buffer position.
+ *
+ * @param size The added size
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer fillAndReset(int size);
+
+ // ////////////////////////
+ // Enum methods //
+ // ////////////////////////
+
+ /**
+ * Reads a byte from the buffer and returns the correlating enum constant
+ * defined by the specified enum type.
+ *
+ * @param <E> The enum type to return
+ * @param enumClass The enum's class object
+ * @return The correlated enum constant
+ */
+ public abstract <E extends Enum<E>> E getEnum(Class<E> enumClass);
+
+ /**
+ * Reads a byte from the buffer and returns the correlating enum constant
+ * defined by the specified enum type.
+ *
+ * @param <E> The enum type to return
+ * @param index the index from which the byte will be read
+ * @param enumClass The enum's class object
+ * @return The correlated enum constant
+ */
+ public abstract <E extends Enum<E>> E getEnum(int index, Class<E> enumClass);
+
+ /**
+ * Reads a short from the buffer and returns the correlating enum constant
+ * defined by the specified enum type.
+ *
+ * @param <E> The enum type to return
+ * @param enumClass The enum's class object
+ * @return The correlated enum constant
+ */
+ public abstract <E extends Enum<E>> E getEnumShort(Class<E> enumClass);
+
+ /**
+ * Reads a short from the buffer and returns the correlating enum constant
+ * defined by the specified enum type.
+ *
+ * @param <E> The enum type to return
+ * @param index the index from which the bytes will be read
+ * @param enumClass The enum's class object
+ * @return The correlated enum constant
+ */
+ public abstract <E extends Enum<E>> E getEnumShort(int index, Class<E> enumClass);
+
+ /**
+ * Reads an int from the buffer and returns the correlating enum constant
+ * defined by the specified enum type.
+ *
+ * @param <E> The enum type to return
+ * @param enumClass The enum's class object
+ * @return The correlated enum constant
+ */
+ public abstract <E extends Enum<E>> E getEnumInt(Class<E> enumClass);
+
+ /**
+ * Reads an int from the buffer and returns the correlating enum constant
+ * defined by the specified enum type.
+ *
+ * @param <E> The enum type to return
+ * @param index the index from which the bytes will be read
+ * @param enumClass The enum's class object
+ * @return The correlated enum constant
+ */
+ public abstract <E extends Enum<E>> E getEnumInt(int index, Class<E> enumClass);
+
+ /**
+ * Writes an enum's ordinal value to the buffer as a byte.
+ *
+ * @param e The enum to write to the buffer
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer putEnum(Enum<?> e);
+
+ /**
+ * Writes an enum's ordinal value to the buffer as a byte.
+ *
+ * @param index The index at which the byte will be written
+ * @param e The enum to write to the buffer
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer putEnum(int index, Enum<?> e);
+
+ /**
+ * Writes an enum's ordinal value to the buffer as a short.
+ *
+ * @param e The enum to write to the buffer
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer putEnumShort(Enum<?> e);
+
+ /**
+ * Writes an enum's ordinal value to the buffer as a short.
+ *
+ * @param index The index at which the bytes will be written
+ * @param e The enum to write to the buffer
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer putEnumShort(int index, Enum<?> e);
+
+ /**
+ * Writes an enum's ordinal value to the buffer as an integer.
+ *
+ * @param e The enum to write to the buffer
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer putEnumInt(Enum<?> e);
+
+ /**
+ * Writes an enum's ordinal value to the buffer as an integer.
+ *
+ * @param index The index at which the bytes will be written
+ * @param e The enum to write to the buffer
+ * @return The modified IoBuffer
+ */
+ public abstract IoBuffer putEnumInt(int index, Enum<?> e);
+
+ // ////////////////////////
+ // EnumSet methods //
+ // ////////////////////////
+
+ /**
+ * Reads a byte sized bit vector and converts it to an {@link EnumSet}.
+ *
+ * <p>
+ * Each bit is mapped to a value in the specified enum. The least significant
+ * bit maps to the first entry in the specified enum and each subsequent bit
+ * maps to each subsequent bit as mapped to the subsequent enum value.
+ *
+ * @param <E> the enum type
+ * @param enumClass the enum class used to create the EnumSet
+ * @return the EnumSet representation of the bit vector
+ */
+ public abstract <E extends Enum<E>> Set<E> getEnumSet(Class<E> enumClass);
+
+ /**
+ * Reads a byte sized bit vector and converts it to an {@link EnumSet}.
+ *
+ * @see #getEnumSet(Class)
+ * @param <E> the enum type
+ * @param index the index from which the byte will be read
+ * @param enumClass the enum class used to create the EnumSet
+ * @return the EnumSet representation of the bit vector
+ */
+ public abstract <E extends Enum<E>> Set<E> getEnumSet(int index, Class<E> \
enumClass); +
+ /**
+ * Reads a short sized bit vector and converts it to an {@link EnumSet}.
+ *
+ * @see #getEnumSet(Class)
+ * @param <E> the enum type
+ * @param enumClass the enum class used to create the EnumSet
+ * @return the EnumSet representation of the bit vector
+ */
+ public abstract <E extends Enum<E>> Set<E> getEnumSetShort(Class<E> enumClass);
+
+ /**
+ * Reads a short sized bit vector and converts it to an {@link EnumSet}.
+ *
+ * @see #getEnumSet(Class)
+ * @param <E> the enum type
+ * @param index the index from which the bytes will be read
+ * @param enumClass the enum class used to create the EnumSet
+ * @return the EnumSet representation of the bit vector
+ */
+ public abstract <E extends Enum<E>> Set<E> getEnumSetShort(int index, Class<E> \
enumClass); +
+ /**
+ * Reads an int sized bit vector and converts it to an {@link EnumSet}.
+ *
+ * @see #getEnumSet(Class)
+ * @param <E> the enum type
+ * @param enumClass the enum class used to create the EnumSet
+ * @return the EnumSet representation of the bit vector
+ */
+ public abstract <E extends Enum<E>> Set<E> getEnumSetInt(Class<E> enumClass);
+
+ /**
+ * Reads an int sized bit vector and converts it to an {@link EnumSet}.
+ *
+ * @see #getEnumSet(Class)
+ * @param <E> the enum type
+ * @param index the index from which the bytes will be read
+ * @param enumClass the enum class used to create the EnumSet
+ * @return the EnumSet representation of the bit vector
+ */
+ public abstract <E extends Enum<E>> Set<E> getEnumSetInt(int index, Class<E> \
enumClass); +
+ /**
+ * Reads a long sized bit vector and converts it to an {@link EnumSet}.
+ *
+ * @see #getEnumSet(Class)
+ * @param <E> the enum type
+ * @param enumClass the enum class used to create the EnumSet
+ * @return the EnumSet representation of the bit vector
+ */
+ public abstract <E extends Enum<E>> Set<E> getEnumSetLong(Class<E> enumClass);
+
+ /**
+ * Reads a long sized bit vector and converts it to an {@link EnumSet}.
+ *
+ * @see #getEnumSet(Class)
+ * @param <E> the enum type
+ * @param index the index from which the bytes will be read
+ * @param enumClass the enum class used to create the EnumSet
+ * @return the EnumSet representation of the bit vector
+ */
+ public abstract <E extends Enum<E>> Set<E> getEnumSetLong(int index, Class<E> \
enumClass); +
+ /**
+ * Writes the specified {@link Set} to the buffer as a byte sized bit vector.
+ *
+ * @param <E> the enum type of the Set
+ * @param set the enum set to write to the buffer
+ * @return the modified IoBuffer
+ */
+ public abstract <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set);
+
+ /**
+ * Writes the specified {@link Set} to the buffer as a byte sized bit vector.
+ *
+ * @param <E> the enum type of the Set
+ * @param index the index at which the byte will be written
+ * @param set the enum set to write to the buffer
+ * @return the modified IoBuffer
+ */
+ public abstract <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set);
+
+ /**
+ * Writes the specified {@link Set} to the buffer as a short sized bit vector.
+ *
+ * @param <E> the enum type of the Set
+ * @param set the enum set to write to the buffer
+ * @return the modified IoBuffer
+ */
+ public abstract <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set);
+
+ /**
+ * Writes the specified {@link Set} to the buffer as a short sized bit vector.
+ *
+ * @param <E> the enum type of the Set
+ * @param index the index at which the bytes will be written
+ * @param set the enum set to write to the buffer
+ * @return the modified IoBuffer
+ */
+ public abstract <E extends Enum<E>> IoBuffer putEnumSetShort(int index, Set<E> \
set); +
+ /**
+ * Writes the specified {@link Set} to the buffer as an int sized bit vector.
+ *
+ * @param <E> the enum type of the Set
+ * @param set the enum set to write to the buffer
+ * @return the modified IoBuffer
+ */
+ public abstract <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set);
+
+ /**
+ * Writes the specified {@link Set} to the buffer as an int sized bit vector.
+ *
+ * @param <E> the enum type of the Set
+ * @param index the index at which the bytes will be written
+ * @param set the enum set to write to the buffer
+ * @return the modified IoBuffer
+ */
+ public abstract <E extends Enum<E>> IoBuffer putEnumSetInt(int index, Set<E> set);
+
+ /**
+ * Writes the specified {@link Set} to the buffer as a long sized bit vector.
+ *
+ * @param <E> the enum type of the Set
+ * @param set the enum set to write to the buffer
+ * @return the modified IoBuffer
+ */
+ public abstract <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set);
+
+ /**
+ * Writes the specified {@link Set} to the buffer as a long sized bit vector.
+ *
+ * @param <E> the enum type of the Set
+ * @param index the index at which the bytes will be written
+ * @param set the enum set to write to the buffer
+ * @return the modified IoBuffer
+ */
+ public abstract <E extends Enum<E>> IoBuffer putEnumSetLong(int index, Set<E> set);
}
diff --git a/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferHexDumper.java \
b/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferHexDumper.java index \
452498c..1bcf322 100644
--- a/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferHexDumper.java
+++ b/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferHexDumper.java
@@ -19,6 +19,8 @@
*/
package org.apache.mina.core.buffer;
+import java.io.UnsupportedEncodingException;
+
/**
* Provides utility methods to dump an {@link IoBuffer} into a hex formatted
* string.
@@ -27,79 +29,206 @@ package org.apache.mina.core.buffer;
*/
class IoBufferHexDumper {
- /**
- * The high digits lookup table.
- */
- private static final byte[] highDigits;
-
- /**
- * The low digits lookup table.
- */
- private static final byte[] lowDigits;
-
- /**
- * Initialize lookup tables.
- */
- static {
- final byte[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', \
'C', 'D', 'E', 'F' };
-
- int i;
- byte[] high = new byte[256];
- byte[] low = new byte[256];
-
- for (i = 0; i < 256; i++) {
- high[i] = digits[i >>> 4];
- low[i] = digits[i & 0x0F];
+ /**
+ * Dumps an {@link IoBuffer} to a hex formatted string.
+ *
+ * @param in the buffer to dump
+ * @param length the limit at which hex dumping will stop
+ * @return a hex formatted string representation of the <i>in</i>
+ * {@link IoBuffer}.
+ */
+ public static String getHexdump(IoBuffer in, int length) {
+ if (length < 0) {
+ throw new IllegalArgumentException("length: " + length + " must be non-negative \
number"); + }
+
+ int pos = in.position();
+ int rem = in.limit() - pos;
+ int items = Math.min(rem, length);
+
+ if (items == 0) {
+ return "";
+ }
+
+ int lim = pos + items;
+
+ StringBuilder out = new StringBuilder((items * 3) + 6);
+
+ for (;;) {
+ int byteValue = in.get(pos++) & 0xFF;
+ out.append((char) hexDigit[(byteValue >> 4) & 0x0F]);
+ out.append((char) hexDigit[byteValue & 0xf]);
+
+ if (pos < lim) {
+ out.append(' ');
+ } else {
+ break;
+ }
+ }
+
+ if (items != rem) {
+ out.append("...");
+ }
+
+ return out.toString();
}
- highDigits = high;
- lowDigits = low;
- }
-
- /**
- * Dumps an {@link IoBuffer} to a hex formatted string.
- *
- * @param in
- * the buffer to dump
- * @param length
- * the limit at which hex dumping will stop
- * @return a hex formatted string representation of the <i>in</i>
- * {@link IoBuffer}.
- */
- public static String getHexdump(IoBuffer in, int length) {
- if (length < 0) {
- throw new IllegalArgumentException("length: " + length + " must be non-negative \
number"); + /**
+ * Produces a verbose hex dump from the {@link ReadableBuffer}
+ *
+ * @return The formatted String representing the content between position() and
+ * limit().
+ */
+ public static final String getPrettyHexDump(final IoBuffer buf) {
+ return getPrettyHexDump(buf, buf.position(), buf.remaining());
}
- int pos = in.position();
- int rem = in.limit() - pos;
- int items = Math.min(rem, length);
-
- if (items == 0) {
- return "";
+ /**
+ * Produces a verbose hex dump
+ *
+ * @param start initial position which to read bytes
+ *
+ * @param length number of bytes to display
+ *
+ * @return The formatted String representing the content between (offset) and
+ * (offset+count)
+ */
+ public static final String getPrettyHexDump(final IoBuffer buf, final int start, \
final int length) { + final int len = Math.min(length, buf.limit() - start);
+
+ final byte[] bytes = new byte[len];
+
+ int o = start;
+
+ for (int i = 0; i < len; i++) {
+ bytes[i] = buf.get(o++);
+ }
+
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append("Source ");
+ sb.append(buf);
+ sb.append(" showing index ");
+ sb.append(start);
+ sb.append(" through ");
+ sb.append((start + length));
+ sb.append("\n");
+ sb.append(toPrettyHexDump(bytes, 0, bytes.length));
+
+ return sb.toString();
}
- int lim = pos + items;
+ /**
+ * Generates a hex dump with line numbers, hex, volumes, and ascii
+ * representation
+ *
+ * @param data source data to read for the hex dump
+ *
+ * @param pos index position to begin reading
+ *
+ * @param len number of bytes to read
+ *
+ * @return string hex dump
+ */
+ public static final String toPrettyHexDump(final byte[] data, final int pos, final \
int len) { + if ((data == null) || ((pos < 0) | (len < 0)) || ((pos + len) > \
data.length)) { + throw new IllegalArgumentException("byte[] is null || pos < 0 || \
len < 0 || pos + len > byte[].length"); + }
- StringBuilder out = new StringBuilder((items * 3) + 6);
+ final StringBuilder b = new StringBuilder();
- /* first sequence to align the spaces */{
- int byteValue = in.get(pos++) & 0xFF;
- out.append((char) highDigits[byteValue]);
- out.append((char) lowDigits[byteValue]);
- }
+ // Process every byte in the data.
+
+ for (int i = pos, c = 0, line = 16; i < len; i += line) {
+ b.append(String.format("%06d", Integer.valueOf(c)) + " ");
+
+ b.append(toPrettyHexDumpLine(data, i, Math.min((pos + len) - i, line), 8, line));
+
+ if ((i + line) < len) {
+ b.append("\n");
+ }
+
+ c += line;
+ }
+
+ return b.toString();
- /* loop remainder */for (; pos < lim;) {
- out.append(' ');
- int byteValue = in.get(pos++) & 0xFF;
- out.append((char) highDigits[byteValue]);
- out.append((char) lowDigits[byteValue]);
}
- if (items != rem) {
- out.append("...");
+ /**
+ * Generates the hex dump line with hex values, columns, and ascii
+ * representation
+ *
+ * @param data source data to read for the hex dump
+ *
+ * @param pos index position to begin reading
+ *
+ * @param len number of bytes to read; this can be less than the <tt>line</tt>
+ * width
+ *
+ * @param col number of bytes in a column
+ *
+ * @param line line width in bytes which pads the output if <tt>len</tt> is less
+ * than <tt>line</tt>
+ *
+ * @return string hex dump
+ */
+ private static final String toPrettyHexDumpLine(final byte[] data, final int pos, \
final int len, final int col, + final int line) {
+ if ((line % 2) != 0) {
+ throw new IllegalArgumentException("length must be multiple of 2");
+ }
+
+ final StringBuilder b = new StringBuilder();
+
+ for (int i = pos, t = Math.min(data.length - pos, len) + pos; i < t;) {
+ for (int x = 0; (x < col) && (i < t); i++, x++) {
+ b.append(toHex(data[i]));
+ b.append(" ");
+ }
+
+ b.append(" ");
+ }
+
+ int cl = (line * 3) + (line / col);
+
+ if (b.length() != cl) // check if we need to pad the output
+ {
+ cl -= b.length();
+
+ while (cl > 0) {
+ b.append(" ");
+ cl--;
+ }
+ }
+
+ try {
+ String p = new String(data, pos, Math.min(data.length - pos, len), \
"Cp1252").replace("\r\n", "..") + .replace("\n", ".").replace("\\", ".");
+
+ final char[] ch = p.toCharArray();
+
+ for (int m = 0; m < ch.length; m++) {
+ if (ch[m] < 32) {
+ ch[m] = (char) 46; // add dots for whitespace chars
+ }
+ }
+
+ b.append(ch);
+ } catch (final UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+
+ return b.toString();
}
- return out.toString();
- }
+ private static final char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', \
'8', '9', 'a', 'b', 'c', 'd', 'e', + 'f' };
+
+ public static final String toHex(final byte b) {
+ // Returns hex String representation of byte
+
+ final char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
+ return new String(array);
+ }
}
\ No newline at end of file
diff --git a/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferWrapper.java \
b/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferWrapper.java index \
7616af1..d0d14dd 100644
--- a/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferWrapper.java
+++ b/mina-core/src/main/java/org/apache/mina/core/buffer/IoBufferWrapper.java
@@ -38,1516 +38,1522 @@ import java.util.Set;
/**
* A {@link IoBuffer} that wraps a buffer and proxies any operations to it.
* <p>
- * You can think this class like a {@link FileOutputStream}. All operations
- * are proxied by default so that you can extend this class and override existing
- * operations selectively. You can introduce new operations, too.
+ * You can think this class like a {@link FileOutputStream}. All operations are
+ * proxied by default so that you can extend this class and override existing
+ * operations selectively. You can introduce new operations, too.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class IoBufferWrapper extends IoBuffer {
- /**
- * The buffer proxied by this proxy.
- */
- private final IoBuffer buf;
-
- /**
- * Create a new instance.
- * @param buf the buffer to be proxied
- */
- protected IoBufferWrapper(IoBuffer buf) {
- if (buf == null) {
- throw new IllegalArgumentException("buf");
- }
- this.buf = buf;
- }
-
- /**
- * @return the parent buffer that this buffer wrapped.
- */
- public IoBuffer getParentBuffer() {
- return buf;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isDirect() {
- return buf.isDirect();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ByteBuffer buf() {
- return buf.buf();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int capacity() {
- return buf.capacity();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int position() {
- return buf.position();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer position(int newPosition) {
- buf.position(newPosition);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int limit() {
- return buf.limit();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer limit(int newLimit) {
- buf.limit(newLimit);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer mark() {
- buf.mark();
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer reset() {
- buf.reset();
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer clear() {
- buf.clear();
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer sweep() {
- buf.sweep();
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer sweep(byte value) {
- buf.sweep(value);
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer flip() {
- buf.flip();
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IoBuffer rewind() {
- buf.rewind();
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int remaining() {
- return buf.remaining();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean hasRemaining() {
- return buf.hasRemaining();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public byte get() {
- return buf.get();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public short getUnsigned() {
- return buf.getUnsigned();
- }
-
- /**
... 2929 lines suppressed ...
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic