[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(&quot;hello&quot;);
- *     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(&quot;hello&quot;);
+ * 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 &lt; C \
                and V &gt; C :
-     * 
-     * <pre>
-     *  Initial buffer :
-     *   
-     *   0       L          C
-     *  +--------+----------+
-     *  |XXXXXXXX|          |
-     *  +--------+----------+
-     *   ^       ^          ^
-     *   |       |          |
-     *  pos    limit     capacity
-     *  
-     * V &lt;= C :
-     * 
-     *   0       L          C
-     *  +--------+----------+
-     *  |XXXXXXXX|          |
-     *  +--------+----------+
-     *   ^       ^          ^
-     *   |       |          |
-     *  pos    limit   newCapacity
-     *  
-     * V &gt; 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 )  &lt;= L, no change :
-     * 
-     *   0       L          C
-     *  +--------+----------+
-     *  |XXXXXXXX|          |
-     *  +--------+----------+
-     *   ^       ^          ^
-     *   |       |          |
-     *  pos    limit   newCapacity
-     *  
-     * You can still put ( L - pos ) bytes in the buffer
-     *  
-     * ( pos + V ) &gt; L &amp; ( pos + V ) &lt;= C :
-     * 
-     *  0        L          C
-     *  +------------+------+
-     *  |XXXXXXXX:...|      |
-     *  +------------+------+
-     *   ^           ^      ^
-     *   |           |      |
-     *  pos       newlimit  newCapacity
-     *  
-     *  You can now put ( L - pos + V )  bytes in the buffer.
-     *  
-     *  
-     *  ( pos + V ) &gt; 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 )  &lt;= L, no change :
-     * 
-     *      P    L          C
-     *  +--------+----------+
-     *  |XXXXXXXX|          |
-     *  +--------+----------+
-     *      ^    ^          ^
-     *      |    |          |
-     *     pos limit   newCapacity
-     *  
-     * You can still put ( L - pos ) bytes in the buffer
-     *  
-     * ( pos + V ) &gt; L &amp; ( pos + V ) &lt;= C :
-     * 
-     *      P    L          C
-     *  +------------+------+
-     *  |XXXXXXXX:...|      |
-     *  +------------+------+
-     *      ^        ^      ^
-     *      |        |      |
-     *     pos    newlimit  newCapacity
-     *  
-     *  You can now put ( L - pos + V)  bytes in the buffer.
-     *  
-     *  
-     *  ( pos + V ) &gt; 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 &lt; C and V &gt; C :
+	 * 
+	 * <pre>
+	 *  Initial buffer :
+	 *   
+	 *   0       L          C
+	 *  +--------+----------+
+	 *  |XXXXXXXX|          |
+	 *  +--------+----------+
+	 *   ^       ^          ^
+	 *   |       |          |
+	 *  pos    limit     capacity
+	 *  
+	 * V &lt;= C :
+	 * 
+	 *   0       L          C
+	 *  +--------+----------+
+	 *  |XXXXXXXX|          |
+	 *  +--------+----------+
+	 *   ^       ^          ^
+	 *   |       |          |
+	 *  pos    limit   newCapacity
+	 *  
+	 * V &gt; 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 )  &lt;= L, no change :
+	 * 
+	 *   0       L          C
+	 *  +--------+----------+
+	 *  |XXXXXXXX|          |
+	 *  +--------+----------+
+	 *   ^       ^          ^
+	 *   |       |          |
+	 *  pos    limit   newCapacity
+	 *  
+	 * You can still put ( L - pos ) bytes in the buffer
+	 *  
+	 * ( pos + V ) &gt; L &amp; ( pos + V ) &lt;= C :
+	 * 
+	 *  0        L          C
+	 *  +------------+------+
+	 *  |XXXXXXXX:...|      |
+	 *  +------------+------+
+	 *   ^           ^      ^
+	 *   |           |      |
+	 *  pos       newlimit  newCapacity
+	 *  
+	 *  You can now put ( L - pos + V )  bytes in the buffer.
+	 *  
+	 *  
+	 *  ( pos + V ) &gt; 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 )  &lt;= L, no change :
+	 * 
+	 *      P    L          C
+	 *  +--------+----------+
+	 *  |XXXXXXXX|          |
+	 *  +--------+----------+
+	 *      ^    ^          ^
+	 *      |    |          |
+	 *     pos limit   newCapacity
+	 *  
+	 * You can still put ( L - pos ) bytes in the buffer
+	 *  
+	 * ( pos + V ) &gt; L &amp; ( pos + V ) &lt;= C :
+	 * 
+	 *      P    L          C
+	 *  +------------+------+
+	 *  |XXXXXXXX:...|      |
+	 *  +------------+------+
+	 *      ^        ^      ^
+	 *      |        |      |
+	 *     pos    newlimit  newCapacity
+	 *  
+	 *  You can now put ( L - pos + V)  bytes in the buffer.
+	 *  
+	 *  
+	 *  ( pos + V ) &gt; 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