You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2005/04/19 09:43:51 UTC

svn commit: r161853 - directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java

Author: trustin
Date: Tue Apr 19 00:43:51 2005
New Revision: 161853

URL: http://svn.apache.org/viewcvs?view=rev&rev=161853
Log:
Changed ByteBuffer to pure abstract class so that users can create their own implementations.

Modified:
    directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java

Modified: directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java?view=diff&r1=161852&r2=161853
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java Tue Apr 19 00:43:51 2005
@@ -50,7 +50,7 @@
  * @author Trustin Lee (trustin@apache.org)
  * @version $Rev$, $Date$,
  */
-public final class ByteBuffer
+public abstract class ByteBuffer
 {
     private static final int MINIMUM_CAPACITY = 1;
 
@@ -109,21 +109,18 @@
         int idx = getBufferStackIndex( bufferStacks, capacity );
         Stack stack = bufferStacks[ idx ];
 
-        ByteBuffer buf;
+        DefaultByteBuffer buf;
         synchronized( stack )
         {
-            buf = ( ByteBuffer ) stack.pop();
+            buf = ( DefaultByteBuffer ) stack.pop();
             if( buf == null )
             {
-                buf = new ByteBuffer( MINIMUM_CAPACITY << idx, direct );
+                buf = new DefaultByteBuffer( MINIMUM_CAPACITY << idx, direct );
             }
         }
 
         buf.clear();
-        synchronized( buf )
-        {
-            buf.refCount = 1;
-        }
+        buf.resetRefCount();
 
         return buf;
     }
@@ -133,7 +130,7 @@
      */
     public static ByteBuffer wrap( java.nio.ByteBuffer nioBuffer )
     {
-        return new ByteBuffer( nioBuffer );
+        return new DefaultByteBuffer( nioBuffer );
     }
     
     private static int getBufferStackIndex( Stack[] bufferStacks, int size )
@@ -154,31 +151,10 @@
         return stackIdx;
     }
 
-    private final java.nio.ByteBuffer buf;
-
-    private int refCount = 1;
-    
-    private ByteBuffer( java.nio.ByteBuffer buf )
+    protected ByteBuffer()
     {
-        if( buf == null )
-        {
-            throw new NullPointerException( "buf" );
-        }
-        this.buf = buf;
     }
 
-    private ByteBuffer( int capacity, boolean direct )
-    {
-        if( direct )
-        {
-            buf = java.nio.ByteBuffer.allocateDirect( capacity );
-        }
-        else
-        {
-            buf = java.nio.ByteBuffer.allocate( capacity );
-        }
-    }
-    
     /**
      * Increases the internal reference count of this buffer to defer
      * automatic release.  You have to invoke {@link #release()} as many
@@ -187,15 +163,7 @@
      * @throws IllegalStateException if you attempt to acquire already
      *                               released buffer.
      */
-    public synchronized void acquire()
-    {
-        if( refCount <= 0 )
-        {
-            throw new IllegalStateException( "Already released buffer." );
-        }
-
-        refCount ++;
-    }
+    public abstract void acquire();
 
     /**
      * Releases the specified buffer to buffer pool.
@@ -203,418 +171,153 @@
      * @throws IllegalStateException if you attempt to release already
      *                               released buffer.
      */
-    public synchronized void release()
-    {
-        if( refCount <= 0 )
-        {
-            refCount = 0;
-            throw new IllegalStateException(
-                    "Already released buffer.  You released the buffer too many times." );
-        }
-
-        refCount --;
-        if( refCount > 0)
-        {
-            return;
-        }
-
-        Stack[] bufferStacks = buf.isDirect()? directBufferStacks : heapBufferStacks;
-        Stack stack = bufferStacks[ getBufferStackIndex( bufferStacks, buf.capacity() ) ];
-        synchronized( stack )
-        {
-            // push back
-            stack.push( this );
-        }
-    }
+    public abstract void release();
 
     /**
      * Returns the underlying NIO buffer instance.
      */
-    public java.nio.ByteBuffer buf()
-    {
-        return buf;
-    }
+    public abstract java.nio.ByteBuffer buf();
 
-    public int capacity()
-    {
-        return buf.capacity();
-    }
+    public abstract int capacity();
     
-    public int position()
-    {
-        return buf.position();
-    }
+    public abstract int position();
 
-    public ByteBuffer position( int newPosition )
-    {
-        buf.position( newPosition );
-        return this;
-    }
-
-    public int limit()
-    {
-        return buf.limit();
-    }
+    public abstract ByteBuffer position( int newPosition );
 
-    public ByteBuffer limit( int newLimit )
-    {
-        buf.limit( newLimit );
-        return this;
-    }
+    public abstract int limit();
 
-    public ByteBuffer mark()
-    {
-        buf.mark();
-        return this;
-    }
+    public abstract ByteBuffer limit( int newLimit );
 
-    public ByteBuffer reset()
-    {
-        buf.reset();
-        return this;
-    }
+    public abstract ByteBuffer mark();
 
-    public ByteBuffer clear()
-    {
-        buf.clear();
-        return this;
-    }
+    public abstract ByteBuffer reset();
 
-    public ByteBuffer flip()
-    {
-        buf.flip();
-        return this;
-    }
+    public abstract ByteBuffer clear();
 
-    public ByteBuffer rewind()
-    {
-        buf.rewind();
-        return this;
-    }
+    public abstract ByteBuffer flip();
 
-    public int remaining()
-    {
-        return buf.remaining();
-    }
+    public abstract ByteBuffer rewind();
 
-    public boolean hasRemaining()
-    {
-        return buf.hasRemaining();
-    }
+    public abstract int remaining();
 
-    public java.nio.ByteBuffer slice()
-    {
-        return buf.slice();
-    }
+    public abstract boolean hasRemaining();
 
-    public java.nio.ByteBuffer duplicate()
-    {
-        return buf.duplicate();
-    }
+    public abstract java.nio.ByteBuffer slice();
 
-    public java.nio.ByteBuffer asReadOnlyBuffer()
-    {
-        return buf.asReadOnlyBuffer();
-    }
+    public abstract java.nio.ByteBuffer duplicate();
 
-    public byte get()
-    {
-        return buf.get();
-    }
+    public abstract java.nio.ByteBuffer asReadOnlyBuffer();
 
-    public short getUnsigned()
-    {
-        return ( short ) ( get() & 0xff );
-    }
+    public abstract byte get();
 
-    public ByteBuffer put( byte b )
-    {
-        buf.put( b );
-        return this;
-    }
+    public abstract short getUnsigned();
 
-    public byte get( int index )
-    {
-        return buf.get( index );
-    }
+    public abstract ByteBuffer put( byte b );
 
-    public short getUnsigned( int index )
-    {
-        return ( short ) ( get( index ) & 0xff );
-    }
+    public abstract byte get( int index );
 
-    public ByteBuffer put( int index, byte b )
-    {
-        buf.put( index, b );
-        return this;
-    }
+    public abstract short getUnsigned( int index );
 
-    public ByteBuffer get( byte[] dst, int offset, int length )
-    {
-        buf.get( dst, offset, length );
-        return this;
-    }
+    public abstract ByteBuffer put( int index, byte b );
 
-    public ByteBuffer get( byte[] dst )
-    {
-        buf.get( dst );
-        return this;
-    }
+    public abstract ByteBuffer get( byte[] dst, int offset, int length );
 
-    public ByteBuffer put( java.nio.ByteBuffer src )
-    {
-        buf.put( src );
-        return this;
-    }
+    public abstract ByteBuffer get( byte[] dst );
 
-    public ByteBuffer put( ByteBuffer src )
-    {
-        buf.put( src.buf() );
-        return this;
-    }
+    public abstract ByteBuffer put( java.nio.ByteBuffer src );
 
-    public ByteBuffer put( byte[] src, int offset, int length )
-    {
-        buf.put( src, offset, length );
-        return this;
-    }
+    public abstract ByteBuffer put( ByteBuffer src );
 
-    public ByteBuffer put( byte[] src )
-    {
-        buf.put( src );
-        return this;
-    }
+    public abstract ByteBuffer put( byte[] src, int offset, int length );
 
-    public ByteBuffer compact()
-    {
-        buf.compact();
-        return this;
-    }
+    public abstract ByteBuffer put( byte[] src );
 
-    public String toString()
-    {
-        return buf.toString();
-    }
+    public abstract ByteBuffer compact();
 
-    public int hashCode()
-    {
-        return buf.hashCode();
-    }
+    public abstract String toString();
 
-    public boolean equals( Object ob )
-    {
-        if( !( ob instanceof ByteBuffer ) )
-            return false;
+    public abstract int hashCode();
 
-        ByteBuffer that = ( ByteBuffer ) ob;
-        return this.buf.equals( that.buf );
-    }
+    public abstract boolean equals( Object ob );
 
-    public int compareTo( ByteBuffer that )
-    {
-        return this.buf.compareTo( that.buf );
-    }
+    public abstract int compareTo( ByteBuffer that );
 
-    public ByteOrder order()
-    {
-        return buf.order();
-    }
+    public abstract ByteOrder order();
 
-    public ByteBuffer order( ByteOrder bo )
-    {
-        buf.order( bo );
-        return this;
-    }
+    public abstract ByteBuffer order( ByteOrder bo );
 
-    public char getChar()
-    {
-        return buf.getChar();
-    }
+    public abstract char getChar();
 
-    public ByteBuffer putChar( char value )
-    {
-        buf.putChar( value );
-        return this;
-    }
+    public abstract ByteBuffer putChar( char value );
 
-    public char getChar( int index )
-    {
-        return buf.getChar( index );
-    }
+    public abstract char getChar( int index );
 
-    public ByteBuffer putChar( int index, char value )
-    {
-        buf.putChar( index, value );
-        return this;
-    }
+    public abstract ByteBuffer putChar( int index, char value );
 
-    public CharBuffer asCharBuffer()
-    {
-        return buf.asCharBuffer();
-    }
+    public abstract CharBuffer asCharBuffer();
 
-    public short getShort()
-    {
-        return buf.getShort();
-    }
+    public abstract short getShort();
 
-    public int getUnsignedShort()
-    {
-        return getShort() & 0xffff;
-    }
+    public abstract int getUnsignedShort();
 
-    public ByteBuffer putShort( short value )
-    {
-        buf.putShort( value );
-        return this;
-    }
+    public abstract ByteBuffer putShort( short value );
 
-    public short getShort( int index )
-    {
-        return buf.getShort( index );
-    }
+    public abstract short getShort( int index );
 
-    public int getUnsignedShort( int index )
-    {
-        return getShort( index ) & 0xffff;
-    }
+    public abstract int getUnsignedShort( int index );
 
-    public ByteBuffer putShort( int index, short value )
-    {
-        buf.putShort( index, value );
-        return this;
-    }
+    public abstract ByteBuffer putShort( int index, short value );
 
-    public ShortBuffer asShortBuffer()
-    {
-        return buf.asShortBuffer();
-    }
+    public abstract ShortBuffer asShortBuffer();
 
-    public int getInt()
-    {
-        return buf.getInt();
-    }
+    public abstract int getInt();
 
-    public long getUnsignedInt()
-    {
-        return getInt() & 0xffffffffL;
-    }
+    public abstract long getUnsignedInt();
 
-    public ByteBuffer putInt( int value )
-    {
-        buf.putInt( value );
-        return this;
-    }
+    public abstract ByteBuffer putInt( int value );
 
-    public int getInt( int index )
-    {
-        return buf.getInt( index );
-    }
+    public abstract int getInt( int index );
 
-    public long getUnsignedInt( int index )
-    {
-        return getInt( index ) & 0xffffffffL;
-    }
+    public abstract long getUnsignedInt( int index );
 
-    public ByteBuffer putInt( int index, int value )
-    {
-        buf.putInt( index, value );
-        return this;
-    }
+    public abstract ByteBuffer putInt( int index, int value );
 
-    public IntBuffer asIntBuffer()
-    {
-        return buf.asIntBuffer();
-    }
+    public abstract IntBuffer asIntBuffer();
 
-    public long getLong()
-    {
-        return buf.getLong();
-    }
+    public abstract long getLong();
 
-    public ByteBuffer putLong( long value )
-    {
-        buf.putLong( value );
-        return this;
-    }
+    public abstract ByteBuffer putLong( long value );
 
-    public long getLong( int index )
-    {
-        return buf.getLong( index );
-    }
+    public abstract long getLong( int index );
 
-    public ByteBuffer putLong( int index, long value )
-    {
-        buf.putLong( index, value );
-        return this;
-    }
+    public abstract ByteBuffer putLong( int index, long value );
 
-    public LongBuffer asLongBuffer()
-    {
-        return buf.asLongBuffer();
-    }
+    public abstract LongBuffer asLongBuffer();
 
-    public float getFloat()
-    {
-        return buf.getFloat();
-    }
+    public abstract float getFloat();
 
-    public ByteBuffer putFloat( float value )
-    {
-        buf.putFloat( value );
-        return this;
-    }
+    public abstract ByteBuffer putFloat( float value );
 
-    public float getFloat( int index )
-    {
-        return buf.getFloat( index );
-    }
+    public abstract float getFloat( int index );
 
-    public ByteBuffer putFloat( int index, float value )
-    {
-        buf.putFloat( index, value );
-        return this;
-    }
+    public abstract ByteBuffer putFloat( int index, float value );
 
-    public FloatBuffer asFloatBuffer()
-    {
-        return buf.asFloatBuffer();
-    }
+    public abstract FloatBuffer asFloatBuffer();
 
-    public double getDouble()
-    {
-        return buf.getDouble();
-    }
+    public abstract double getDouble();
 
-    public ByteBuffer putDouble( double value )
-    {
-        buf.putDouble( value );
-        return this;
-    }
+    public abstract ByteBuffer putDouble( double value );
 
-    public double getDouble( int index )
-    {
-        return buf.getDouble( index );
-    }
+    public abstract double getDouble( int index );
 
-    public ByteBuffer putDouble( int index, double value )
-    {
-        buf.putDouble( index, value );
-        return this;
-    }
+    public abstract ByteBuffer putDouble( int index, double value );
 
-    public DoubleBuffer asDoubleBuffer()
-    {
-        return buf.asDoubleBuffer();
-    }
+    public abstract DoubleBuffer asDoubleBuffer();
 
     /**
      * Returns hexdump of this buffer.
      */
-    public String getHexDump()
-    {
-        return ByteBufferHexDumper.getHexdump( this );
-    }
+    public abstract String getHexDump();
 
     ////////////////////////////////
     // String getters and putters //
@@ -626,77 +329,8 @@
      * 
      * @param fieldSize the maximum number of bytes to read
      */
-    public ByteBuffer getString( CharBuffer out, int fieldSize,
-                                CharsetDecoder decoder )
-    {
-        checkFieldSize( fieldSize );
-
-        if( fieldSize == 0 )
-            return this;
-
-        boolean utf16 = decoder.charset().name().startsWith( "UTF-16" );
-
-        if( utf16 && ( ( fieldSize & 1 ) != 0 ) )
-        {
-            throw new IllegalArgumentException( "fieldSize is not even." );
-        }
-
-        int i;
-        int oldLimit = buf.limit();
-        int limit = buf.position() + fieldSize;
-
-        if( oldLimit < limit )
-        {
-            throw new BufferOverflowException();
-        }
-
-        buf.mark();
-
-        if( !utf16 )
-        {
-            for( i = 0; i < fieldSize; i ++ )
-            {
-                if( buf.get() == 0 )
-                {
-                    break;
-                }
-            }
-
-            if( i == fieldSize )
-            {
-                buf.limit( limit );
-            }
-            else
-            {
-                buf.limit( buf.position() - 1 );
-            }
-        }
-        else
-        {
-            for( i = 0; i < fieldSize; i += 2 )
-            {
-                if( ( buf.get() == 0 ) && ( buf.get() == 0 ) )
-                {
-                    break;
-                }
-            }
-
-            if( i == fieldSize )
-            {
-                buf.limit( limit );
-            }
-            else
-            {
-                buf.limit( buf.position() - 2 );
-            }
-        }
-
-        buf.reset();
-        decoder.decode( buf, out, true );
-        buf.limit( oldLimit );
-        buf.position( limit );
-        return this;
-    }
+    public abstract ByteBuffer getString( CharBuffer out, int fieldSize,
+                                CharsetDecoder decoder );
 
     /**
      * Reads a <code>NUL</code>-terminated string from this buffer using the
@@ -704,13 +338,7 @@
      * 
      * @param fieldSize the maximum number of bytes to read
      */
-    public String getString( int fieldSize, CharsetDecoder decoder )
-    {
-        CharBuffer out = CharBuffer.allocate( ( int ) ( decoder
-                .maxCharsPerByte() * fieldSize ) + 1 );
-        getString( out, fieldSize, decoder );
-        return out.flip().toString();
-    }
+    public abstract String getString( int fieldSize, CharsetDecoder decoder );
 
     /**
      * Writes the content of <code>in</code> into this buffer as a 
@@ -726,49 +354,8 @@
      * 
      * @param fieldSize the maximum number of bytes to write
      */
-    public ByteBuffer putString( CharBuffer in, int fieldSize,
-                                CharsetEncoder encoder )
-    {
-        checkFieldSize( fieldSize );
-
-        if( fieldSize == 0 )
-            return this;
-
-        boolean utf16 = encoder.charset().name().startsWith( "UTF-16" );
-
-        if( utf16 && ( ( fieldSize & 1 ) != 0 ) )
-        {
-            throw new IllegalArgumentException( "fieldSize is not even." );
-        }
-
-        int oldLimit = buf.limit();
-        int limit = buf.position() + fieldSize;
-
-        if( oldLimit < limit )
-        {
-            throw new BufferOverflowException();
-        }
-
-        buf.limit( limit );
-        encoder.encode( in, buf, true );
-        buf.limit( oldLimit );
-
-        if( limit > buf.position() )
-        {
-            if( !utf16 )
-            {
-                buf.put( ( byte ) 0x00 );
-            }
-            else
-            {
-                buf.put( ( byte ) 0x00 );
-                buf.put( ( byte ) 0x00 );
-            }
-        }
-
-        buf.position( limit );
-        return this;
-    }
+    public abstract ByteBuffer putString( CharBuffer in, int fieldSize,
+                                CharsetEncoder encoder );
 
     /**
      * Writes the content of <code>in</code> into this buffer as a 
@@ -784,11 +371,8 @@
      * 
      * @param fieldSize the maximum number of bytes to write
      */
-    public ByteBuffer putString( CharSequence in, int fieldSize,
-                                CharsetEncoder encoder )
-    {
-        return putString( CharBuffer.wrap( in ), fieldSize, encoder );
-    }
+    public abstract ByteBuffer putString( CharSequence in, int fieldSize,
+                                CharsetEncoder encoder );
 
     //////////////////////////
     // Skip or fill methods //
@@ -798,174 +382,768 @@
      * Forwards the position of this buffer as the specified <code>size</code>
      * bytes.
      */
-    public ByteBuffer skip( int size )
-    {
-        return position( position() + size );
-    }
+    public abstract ByteBuffer skip( int size );
 
     /**
      * Fills this buffer with the specified value.
      * This method moves buffer position forward.
      */
-    public ByteBuffer fill( byte value, int size )
-    {
-        int q = size >>> 3;
-        int r = size & 7;
-
-        if( q > 0 )
-        {
-            int intValue = value | ( value << 8 ) | ( value << 16 )
-                           | ( value << 24 );
-            long longValue = intValue;
-            longValue <<= 32;
-            longValue |= intValue;
+    public abstract ByteBuffer fill( byte value, int size );
 
-            for( int i = q; i > 0; i -- )
-            {
-                buf.putLong( longValue );
-            }
-        }
+    /**
+     * Fills this buffer with the specified value.
+     * This method does not change buffer position.
+     */
+    public abstract ByteBuffer fillAndReset( byte value, int size );
 
-        q = r >>> 2;
-        r = r & 3;
+    /**
+     * Fills this buffer with <code>NUL (0x00)</code>.
+     * This method moves buffer position forward.
+     */
+    public abstract ByteBuffer fill( int size );
 
-        if( q > 0 )
-        {
-            int intValue = value | ( value << 8 ) | ( value << 16 )
-                           | ( value << 24 );
-            buf.putInt( intValue );
+    /**
+     * Fills this buffer with <code>NUL (0x00)</code>.
+     * This method does not change buffer position.
+     */
+    public abstract ByteBuffer fillAndReset( int size );
+    
+    /**
+     * Allocates and returns a new {@link ByteBuffer} whose content, position,
+     * limit, and capacity is identical.  
+     */
+    public abstract ByteBuffer fork();
+    
+    /**
+     * Allocates and returns a new {@link ByteBuffer} whose content, position,
+     * and limit except capacity is identical.  New capacity can be both greater
+     * and less than original capacity.  If limit or position is less than
+     * new capacity, they will become same with new capacity.
+     */
+    public abstract ByteBuffer fork( int newCapacity );
+    
+    private static class DefaultByteBuffer extends ByteBuffer
+    {
+        private final java.nio.ByteBuffer buf;
+
+        private int refCount = 1;
+        
+        private DefaultByteBuffer( java.nio.ByteBuffer buf )
+        {
+            if( buf == null )
+            {
+                throw new NullPointerException( "buf" );
+            }
+            this.buf = buf;
+        }
+
+        private DefaultByteBuffer( int capacity, boolean direct )
+        {
+            if( direct )
+            {
+                buf = java.nio.ByteBuffer.allocateDirect( capacity );
+            }
+            else
+            {
+                buf = java.nio.ByteBuffer.allocate( capacity );
+            }
+        }
+        
+        private synchronized void resetRefCount()
+        {
+            refCount = 1;
         }
+        
+        public synchronized void acquire()
+        {
+            if( refCount <= 0 )
+            {
+                throw new IllegalStateException( "Already released buffer." );
+            }
 
-        q = r >> 1;
-        r = r & 1;
+            refCount ++;
+        }
 
-        if( q > 0 )
+        public synchronized void release()
         {
-            short shortValue = ( short ) ( value | ( value << 8 ) );
-            buf.putShort( shortValue );
+            if( refCount <= 0 )
+            {
+                refCount = 0;
+                throw new IllegalStateException(
+                        "Already released buffer.  You released the buffer too many times." );
+            }
+
+            refCount --;
+            if( refCount > 0)
+            {
+                return;
+            }
+
+            Stack[] bufferStacks = buf.isDirect()? directBufferStacks : heapBufferStacks;
+            Stack stack = bufferStacks[ getBufferStackIndex( bufferStacks, buf.capacity() ) ];
+            synchronized( stack )
+            {
+                // push back
+                stack.push( this );
+            }
         }
 
-        if( r > 0 )
+        public java.nio.ByteBuffer buf()
         {
-            buf.put( value );
+            return buf;
         }
 
-        return this;
-    }
+        public int capacity()
+        {
+            return buf.capacity();
+        }
+        
+        public int position()
+        {
+            return buf.position();
+        }
 
-    /**
-     * Fills this buffer with the specified value.
-     * This method does not change buffer position.
-     */
-    public ByteBuffer fillAndReset( byte value, int size )
-    {
-        int pos = buf.position();
-        try
+        public ByteBuffer position( int newPosition )
         {
-            fill( value, size );
+            buf.position( newPosition );
+            return this;
         }
-        finally
+
+        public int limit()
         {
-            buf.position( pos );
+            return buf.limit();
         }
-        return this;
-    }
 
-    /**
-     * Fills this buffer with <code>NUL (0x00)</code>.
-     * This method moves buffer position forward.
-     */
-    public ByteBuffer fill( int size )
-    {
-        int q = size >>> 3;
-        int r = size & 7;
+        public ByteBuffer limit( int newLimit )
+        {
+            buf.limit( newLimit );
+            return this;
+        }
 
-        for( int i = q; i > 0; i -- )
+        public ByteBuffer mark()
         {
-            buf.putLong( 0L );
+            buf.mark();
+            return this;
         }
 
-        q = r >>> 2;
-        r = r & 3;
+        public ByteBuffer reset()
+        {
+            buf.reset();
+            return this;
+        }
 
-        if( q > 0 )
+        public ByteBuffer clear()
         {
-            buf.putInt( 0 );
+            buf.clear();
+            return this;
         }
 
-        q = r >> 1;
-        r = r & 1;
+        public ByteBuffer flip()
+        {
+            buf.flip();
+            return this;
+        }
 
-        if( q > 0 )
+        public ByteBuffer rewind()
         {
-            buf.putShort( ( short ) 0 );
+            buf.rewind();
+            return this;
         }
 
-        if( r > 0 )
+        public int remaining()
         {
-            buf.put( ( byte ) 0 );
+            return buf.remaining();
         }
 
-        return this;
-    }
+        public boolean hasRemaining()
+        {
+            return buf.hasRemaining();
+        }
 
-    /**
-     * Fills this buffer with <code>NUL (0x00)</code>.
-     * This method does not change buffer position.
-     */
-    public ByteBuffer fillAndReset( int size )
-    {
-        int pos = buf.position();
-        try
+        public java.nio.ByteBuffer slice()
         {
-            fill( size );
+            return buf.slice();
         }
-        finally
+
+        public java.nio.ByteBuffer duplicate()
         {
-            buf.position( pos );
+            return buf.duplicate();
         }
 
-        return this;
-    }
-    
-    /**
-     * Allocates and returns a new {@link ByteBuffer} whose content, position,
-     * limit, and capacity is identical.  
-     */
-    public ByteBuffer fork()
-    {
-        return fork( this.capacity() );
-    }
-    
-    /**
-     * Allocates and returns a new {@link ByteBuffer} whose content, position,
-     * and limit except capacity is identical.  New capacity can be both greater
-     * and less than original capacity.  If limit or position is less than
-     * new capacity, they will become same with new capacity.
-     */
-    public ByteBuffer fork( int newCapacity )
-    {
-        ByteBuffer buf = allocate( newCapacity );
-        int pos = this.position();
-        int limit = this.limit();
-        this.position( 0 );
-        this.limit( newCapacity < this.capacity()? newCapacity : this.capacity() );
-        buf.put( this );
-        buf.position( pos < newCapacity? pos : newCapacity );
-        buf.limit( limit < newCapacity? limit : newCapacity );
-        this.limit( this.capacity() );
-        this.position( pos );
-        this.limit( limit );
+        public java.nio.ByteBuffer asReadOnlyBuffer()
+        {
+            return buf.asReadOnlyBuffer();
+        }
+
+        public byte get()
+        {
+            return buf.get();
+        }
+
+        public short getUnsigned()
+        {
+            return ( short ) ( get() & 0xff );
+        }
+
+        public ByteBuffer put( byte b )
+        {
+            buf.put( b );
+            return this;
+        }
+
+        public byte get( int index )
+        {
+            return buf.get( index );
+        }
+
+        public short getUnsigned( int index )
+        {
+            return ( short ) ( get( index ) & 0xff );
+        }
+
+        public ByteBuffer put( int index, byte b )
+        {
+            buf.put( index, b );
+            return this;
+        }
+
+        public ByteBuffer get( byte[] dst, int offset, int length )
+        {
+            buf.get( dst, offset, length );
+            return this;
+        }
+
+        public ByteBuffer get( byte[] dst )
+        {
+            buf.get( dst );
+            return this;
+        }
+
+        public ByteBuffer put( java.nio.ByteBuffer src )
+        {
+            buf.put( src );
+            return this;
+        }
+
+        public ByteBuffer put( ByteBuffer src )
+        {
+            buf.put( src.buf() );
+            return this;
+        }
+
+        public ByteBuffer put( byte[] src, int offset, int length )
+        {
+            buf.put( src, offset, length );
+            return this;
+        }
+
+        public ByteBuffer put( byte[] src )
+        {
+            buf.put( src );
+            return this;
+        }
+
+        public ByteBuffer compact()
+        {
+            buf.compact();
+            return this;
+        }
+
+        public String toString()
+        {
+            return buf.toString();
+        }
+
+        public int hashCode()
+        {
+            return buf.hashCode();
+        }
+
+        public boolean equals( Object ob )
+        {
+            if( !( ob instanceof ByteBuffer ) )
+                return false;
+
+            ByteBuffer that = ( ByteBuffer ) ob;
+            return this.buf.equals( that.buf() );
+        }
+
+        public int compareTo( ByteBuffer that )
+        {
+            return this.buf.compareTo( that.buf() );
+        }
+
+        public ByteOrder order()
+        {
+            return buf.order();
+        }
+
+        public ByteBuffer order( ByteOrder bo )
+        {
+            buf.order( bo );
+            return this;
+        }
+
+        public char getChar()
+        {
+            return buf.getChar();
+        }
+
+        public ByteBuffer putChar( char value )
+        {
+            buf.putChar( value );
+            return this;
+        }
+
+        public char getChar( int index )
+        {
+            return buf.getChar( index );
+        }
+
+        public ByteBuffer putChar( int index, char value )
+        {
+            buf.putChar( index, value );
+            return this;
+        }
+
+        public CharBuffer asCharBuffer()
+        {
+            return buf.asCharBuffer();
+        }
+
+        public short getShort()
+        {
+            return buf.getShort();
+        }
+
+        public int getUnsignedShort()
+        {
+            return getShort() & 0xffff;
+        }
+
+        public ByteBuffer putShort( short value )
+        {
+            buf.putShort( value );
+            return this;
+        }
+
+        public short getShort( int index )
+        {
+            return buf.getShort( index );
+        }
+
+        public int getUnsignedShort( int index )
+        {
+            return getShort( index ) & 0xffff;
+        }
+
+        public ByteBuffer putShort( int index, short value )
+        {
+            buf.putShort( index, value );
+            return this;
+        }
+
+        public ShortBuffer asShortBuffer()
+        {
+            return buf.asShortBuffer();
+        }
+
+        public int getInt()
+        {
+            return buf.getInt();
+        }
+
+        public long getUnsignedInt()
+        {
+            return getInt() & 0xffffffffL;
+        }
+
+        public ByteBuffer putInt( int value )
+        {
+            buf.putInt( value );
+            return this;
+        }
+
+        public int getInt( int index )
+        {
+            return buf.getInt( index );
+        }
+
+        public long getUnsignedInt( int index )
+        {
+            return getInt( index ) & 0xffffffffL;
+        }
+
+        public ByteBuffer putInt( int index, int value )
+        {
+            buf.putInt( index, value );
+            return this;
+        }
+
+        public IntBuffer asIntBuffer()
+        {
+            return buf.asIntBuffer();
+        }
+
+        public long getLong()
+        {
+            return buf.getLong();
+        }
+
+        public ByteBuffer putLong( long value )
+        {
+            buf.putLong( value );
+            return this;
+        }
+
+        public long getLong( int index )
+        {
+            return buf.getLong( index );
+        }
+
+        public ByteBuffer putLong( int index, long value )
+        {
+            buf.putLong( index, value );
+            return this;
+        }
+
+        public LongBuffer asLongBuffer()
+        {
+            return buf.asLongBuffer();
+        }
+
+        public float getFloat()
+        {
+            return buf.getFloat();
+        }
+
+        public ByteBuffer putFloat( float value )
+        {
+            buf.putFloat( value );
+            return this;
+        }
+
+        public float getFloat( int index )
+        {
+            return buf.getFloat( index );
+        }
+
+        public ByteBuffer putFloat( int index, float value )
+        {
+            buf.putFloat( index, value );
+            return this;
+        }
+
+        public FloatBuffer asFloatBuffer()
+        {
+            return buf.asFloatBuffer();
+        }
+
+        public double getDouble()
+        {
+            return buf.getDouble();
+        }
+
+        public ByteBuffer putDouble( double value )
+        {
+            buf.putDouble( value );
+            return this;
+        }
+
+        public double getDouble( int index )
+        {
+            return buf.getDouble( index );
+        }
+
+        public ByteBuffer putDouble( int index, double value )
+        {
+            buf.putDouble( index, value );
+            return this;
+        }
+
+        public DoubleBuffer asDoubleBuffer()
+        {
+            return buf.asDoubleBuffer();
+        }
+
+        public String getHexDump()
+        {
+            return ByteBufferHexDumper.getHexdump( this );
+        }
+
+        public ByteBuffer getString( CharBuffer out, int fieldSize,
+                                    CharsetDecoder decoder )
+        {
+            checkFieldSize( fieldSize );
+
+            if( fieldSize == 0 )
+                return this;
+
+            boolean utf16 = decoder.charset().name().startsWith( "UTF-16" );
+
+            if( utf16 && ( ( fieldSize & 1 ) != 0 ) )
+            {
+                throw new IllegalArgumentException( "fieldSize is not even." );
+            }
+
+            int i;
+            int oldLimit = buf.limit();
+            int limit = buf.position() + fieldSize;
+
+            if( oldLimit < limit )
+            {
+                throw new BufferOverflowException();
+            }
+
+            buf.mark();
+
+            if( !utf16 )
+            {
+                for( i = 0; i < fieldSize; i ++ )
+                {
+                    if( buf.get() == 0 )
+                    {
+                        break;
+                    }
+                }
+
+                if( i == fieldSize )
+                {
+                    buf.limit( limit );
+                }
+                else
+                {
+                    buf.limit( buf.position() - 1 );
+                }
+            }
+            else
+            {
+                for( i = 0; i < fieldSize; i += 2 )
+                {
+                    if( ( buf.get() == 0 ) && ( buf.get() == 0 ) )
+                    {
+                        break;
+                    }
+                }
+
+                if( i == fieldSize )
+                {
+                    buf.limit( limit );
+                }
+                else
+                {
+                    buf.limit( buf.position() - 2 );
+                }
+            }
+
+            buf.reset();
+            decoder.decode( buf, out, true );
+            buf.limit( oldLimit );
+            buf.position( limit );
+            return this;
+        }
+
+        public String getString( int fieldSize, CharsetDecoder decoder )
+        {
+            CharBuffer out = CharBuffer.allocate( ( int ) ( decoder
+                    .maxCharsPerByte() * fieldSize ) + 1 );
+            getString( out, fieldSize, decoder );
+            return out.flip().toString();
+        }
+
+        public ByteBuffer putString( CharBuffer in, int fieldSize,
+                                    CharsetEncoder encoder )
+        {
+            checkFieldSize( fieldSize );
+
+            if( fieldSize == 0 )
+                return this;
+
+            boolean utf16 = encoder.charset().name().startsWith( "UTF-16" );
+
+            if( utf16 && ( ( fieldSize & 1 ) != 0 ) )
+            {
+                throw new IllegalArgumentException( "fieldSize is not even." );
+            }
+
+            int oldLimit = buf.limit();
+            int limit = buf.position() + fieldSize;
+
+            if( oldLimit < limit )
+            {
+                throw new BufferOverflowException();
+            }
+
+            buf.limit( limit );
+            encoder.encode( in, buf, true );
+            buf.limit( oldLimit );
+
+            if( limit > buf.position() )
+            {
+                if( !utf16 )
+                {
+                    buf.put( ( byte ) 0x00 );
+                }
+                else
+                {
+                    buf.put( ( byte ) 0x00 );
+                    buf.put( ( byte ) 0x00 );
+                }
+            }
+
+            buf.position( limit );
+            return this;
+        }
+
+        public ByteBuffer putString( CharSequence in, int fieldSize,
+                                    CharsetEncoder encoder )
+        {
+            return putString( CharBuffer.wrap( in ), fieldSize, encoder );
+        }
+
+        public ByteBuffer skip( int size )
+        {
+            return position( position() + size );
+        }
+
+        public ByteBuffer fill( byte value, int size )
+        {
+            int q = size >>> 3;
+            int r = size & 7;
+
+            if( q > 0 )
+            {
+                int intValue = value | ( value << 8 ) | ( value << 16 )
+                               | ( value << 24 );
+                long longValue = intValue;
+                longValue <<= 32;
+                longValue |= intValue;
+
+                for( int i = q; i > 0; i -- )
+                {
+                    buf.putLong( longValue );
+                }
+            }
+
+            q = r >>> 2;
+            r = r & 3;
+
+            if( q > 0 )
+            {
+                int intValue = value | ( value << 8 ) | ( value << 16 )
+                               | ( value << 24 );
+                buf.putInt( intValue );
+            }
+
+            q = r >> 1;
+            r = r & 1;
+
+            if( q > 0 )
+            {
+                short shortValue = ( short ) ( value | ( value << 8 ) );
+                buf.putShort( shortValue );
+            }
+
+            if( r > 0 )
+            {
+                buf.put( value );
+            }
+
+            return this;
+        }
+
+        public ByteBuffer fillAndReset( byte value, int size )
+        {
+            int pos = buf.position();
+            try
+            {
+                fill( value, size );
+            }
+            finally
+            {
+                buf.position( pos );
+            }
+            return this;
+        }
+
+        public ByteBuffer fill( int size )
+        {
+            int q = size >>> 3;
+            int r = size & 7;
+
+            for( int i = q; i > 0; i -- )
+            {
+                buf.putLong( 0L );
+            }
+
+            q = r >>> 2;
+            r = r & 3;
+
+            if( q > 0 )
+            {
+                buf.putInt( 0 );
+            }
+
+            q = r >> 1;
+            r = r & 1;
+
+            if( q > 0 )
+            {
+                buf.putShort( ( short ) 0 );
+            }
+
+            if( r > 0 )
+            {
+                buf.put( ( byte ) 0 );
+            }
+
+            return this;
+        }
+
+        public ByteBuffer fillAndReset( int size )
+        {
+            int pos = buf.position();
+            try
+            {
+                fill( size );
+            }
+            finally
+            {
+                buf.position( pos );
+            }
+
+            return this;
+        }
         
-        return buf;
-    }
+        public ByteBuffer fork()
+        {
+            return fork( this.capacity() );
+        }
+        
+        public ByteBuffer fork( int newCapacity )
+        {
+            ByteBuffer buf = allocate( newCapacity );
+            int pos = this.position();
+            int limit = this.limit();
+            this.position( 0 );
+            this.limit( newCapacity < this.capacity()? newCapacity : this.capacity() );
+            buf.put( this );
+            buf.position( pos < newCapacity? pos : newCapacity );
+            buf.limit( limit < newCapacity? limit : newCapacity );
+            this.limit( this.capacity() );
+            this.position( pos );
+            this.limit( limit );
+            
+            return buf;
+        }
 
-    private static void checkFieldSize( int fieldSize )
-    {
-        if( fieldSize < 0 )
+        private static void checkFieldSize( int fieldSize )
         {
-            throw new IllegalArgumentException(
-                    "fieldSize cannot be negative: " + fieldSize );
+            if( fieldSize < 0 )
+            {
+                throw new IllegalArgumentException(
+                        "fieldSize cannot be negative: " + fieldSize );
+            }
         }
     }
 }