You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by st...@apache.org on 2006/12/12 18:36:22 UTC

svn commit: r486248 [2/3] - in /incubator/qpid/trunk/qpid/dotnet: Qpid.Buffer/ Qpid.Client.Transport.Socket.Blocking/ Qpid.Client/Client/ Qpid.Client/Client/Message/ Qpid.Codec/ Qpid.Codec/Demux/ Qpid.Common/Framing/ Qpid.Common/stylesheets/

Modified: incubator/qpid/trunk/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs?view=diff&rev=486248&r1=486247&r2=486248
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs (original)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs Tue Dec 12 09:36:17 2006
@@ -19,432 +19,2375 @@
  *
  */
 using System;
-using System.Collections;
 using System.Text;
 
 namespace Qpid.Buffer
 {
-    /// <summary>
-    /// A buffer that manages an underlying byte oriented stream, and writes and reads to and from it in
-    /// BIG ENDIAN order.
-    /// </summary>
-    public abstract class ByteBuffer
+    public enum ByteOrder { BigEndian, LittleEndian }
+//    /// <summary>
+//    /// A buffer that manages an underlying byte oriented stream, and writes and reads to and from it in
+//    /// BIG ENDIAN order.
+//    /// </summary>
+//    public abstract class ByteBuffer
+//    {
+//        protected const int MINIMUM_CAPACITY = 1;
+//        
+//        protected static Stack _containerStack = new Stack();
+//        
+//        protected static Stack[] _heapBufferStacks = new Stack[]
+//            {
+//                new Stack(), new Stack(), new Stack(), new Stack(), 
+//                new Stack(), new Stack(), new Stack(), new Stack(), 
+//                new Stack(), new Stack(), new Stack(), new Stack(), 
+//                new Stack(), new Stack(), new Stack(), new Stack(), 
+//                new Stack(), new Stack(), new Stack(), new Stack(), 
+//                new Stack(), new Stack(), new Stack(), new Stack(), 
+//                new Stack(), new Stack(), new Stack(), new Stack(), 
+//                new Stack(), new Stack(), new Stack(), new Stack()
+//            };
+//
+//        /// <summary>
+//        /// Returns the direct or heap buffer which is capable of the specified size.
+//        /// Currently does not support direct buffers but this will be an option in future.
+//        /// </summary>
+//        /// <param name="capacity">The capacity.</param>
+//        /// <returns></returns>
+//        public static ByteBuffer Allocate(int capacity)
+//        {
+//            // for now, just allocate a heap buffer but in future could do an optimised "direct" buffer
+//            // that is implemented natively
+//            return Allocate(capacity, false);
+//        }
+//        
+//        public static ByteBuffer Allocate(int capacity, bool direct)
+//        {
+//            ByteBuffer buffer = Allocate0(capacity, direct);
+//            RefCountingByteBuffer buf = AllocateContainer();
+//            buf.Init(buffer);
+//            return buf;
+//        }
+//        
+//        private static RefCountingByteBuffer AllocateContainer()
+//        {
+//            RefCountingByteBuffer buf = null;
+//            lock (_containerStack)
+//            {
+//                if (_containerStack.Count > 0)
+//                {
+//                    buf = (RefCountingByteBuffer) _containerStack.Pop();
+//                }
+//            }
+//            
+//            if (buf == null)
+//            {
+//                buf = new RefCountingByteBuffer();                
+//            }
+//            return buf;
+//        }
+//        
+//        protected static ByteBuffer Allocate0(int capacity, bool direct)
+//        {
+//            if (direct)
+//            {
+//                throw new NotSupportedException("Direct buffers not currently implemented");
+//            }            
+//            int idx = GetBufferStackIndex(_heapBufferStacks, capacity);
+//            Stack stack = _heapBufferStacks[idx];
+//            ByteBuffer buf = null;
+//            lock (stack)
+//            {
+//                if (stack.Count > 0)
+//                {
+//                    buf = (ByteBuffer) stack.Pop();
+//                }
+//            }
+//
+//            if (buf == null)
+//            {
+//                buf = new HeapByteBuffer(MINIMUM_CAPACITY << idx);
+//            }
+//
+//            return buf;
+//        }
+//        
+//        protected static void Release0(ByteBuffer buf)
+//        {
+//            Stack stack = _heapBufferStacks[GetBufferStackIndex(_heapBufferStacks, buf.Capacity)];
+//            lock (stack)
+//            {
+//                stack.Push(buf);
+//            }            
+//        }
+//        
+//        private static int GetBufferStackIndex(Stack[] bufferStacks, int size)
+//        {
+//            int targetSize = MINIMUM_CAPACITY;
+//            int stackIdx = 0;
+//            // each bucket contains buffers that are double the size of the previous bucket
+//            while (size > targetSize)
+//            {
+//                targetSize <<= 1;
+//                stackIdx++;
+//                if (stackIdx >= bufferStacks.Length)
+//                {
+//                    throw new ArgumentOutOfRangeException("size", "Buffer size is too big: " + size);
+//                }
+//            }
+//            return stackIdx;
+//        }
+//
+//        /// <summary>
+//        /// Increases the internal reference count of this buffer to defer automatic release. You have
+//        /// to invoke release() as many times as you invoked this method to release this buffer.
+//        /// </summary>
+//        public abstract void Acquire();
+//
+//        /// <summary>
+//        /// Releases the specified buffer to the buffer pool.
+//        /// </summary>
+//        public abstract void Release();
+//
+//        public abstract int Capacity
+//        {
+//            get;
+//        }
+//
+//        public abstract bool IsAutoExpand
+//        {
+//            get;
+//            set;
+//        }
+//
+//        /// <summary>
+//        /// Changes the capacity and limit of this buffer sot his buffer gets the specified
+//        /// expectedRemaining room from the current position. This method works even if you didn't set
+//        /// autoExpand to true.
+//        /// </summary>
+//        /// <param name="expectedRemaining">Room you want from the current position</param>        
+//        public abstract void Expand(int expectedRemaining);
+//
+//        /// <summary>
+//        /// Changes the capacity and limit of this buffer sot his buffer gets the specified
+//        /// expectedRemaining room from the specified position.
+//        /// </summary>
+//        /// <param name="pos">The pos you want the room to be available from.</param>
+//        /// <param name="expectedRemaining">The expected room you want available.</param>        
+//        public abstract void Expand(int pos, int expectedRemaining);
+//
+//        /// <summary>
+//        /// Returns true if and only if this buffer is returned back to the buffer pool when released.
+//        /// </summary>
+//        /// <value><c>true</c> if pooled; otherwise, <c>false</c>.</value>
+//        public abstract bool Pooled
+//        {
+//            get;
+//            set;
+//        }
+//        
+//        public abstract int Position
+//        {
+//            get;
+//            set;
+//        }
+//
+//        public abstract int Limit
+//        {
+//            get;
+//            set;
+//        }
+//
+//        //public abstract void Mark();
+//
+//        //public abstract void Reset();
+//
+//        public abstract void Clear();
+//
+//        /// <summary>
+//        /// Clears this buffer and fills its content with NULL. The position is set to zero, the limit is set to
+//        /// capacity and the mark is discarded.
+//        /// </summary>
+//        public void Sweep()
+//        {
+//            Clear();
+//            FillAndReset(Remaining);
+//        }
+//        
+//        public void Sweep(byte value)
+//        {
+//            Clear();
+//            FillAndReset(value, Remaining);
+//        }
+//
+//        public abstract void Flip();
+//
+//        public abstract void Rewind();
+//
+//        public abstract int Remaining
+//        {
+//            get;
+//        }
+//        
+//        public bool HasRemaining()
+//        {
+//            return Remaining > 0;
+//        }
+//
+//        public abstract byte Get();
+//
+//        public abstract byte Get(int index);
+//        
+//        public abstract void Get(byte[] destination);
+//
+//        public abstract ushort GetUnsignedShort();
+//
+//        public abstract uint GetUnsignedInt();
+//
+//        public abstract ulong GetUnsignedLong();
+//
+//        public abstract string GetString(uint length, Encoding encoder);
+//
+//        public abstract void Put(byte data);
+//
+//        public abstract void Put(byte[] data);
+//        public abstract void Put(byte[] data, int offset, int size);
+//
+//        public abstract void Put(ushort data);
+//
+//        public abstract void Put(uint data);
+//
+//        public abstract void Put(ulong data);
+//
+//        public abstract void Put(ByteBuffer buf);
+//        
+//        public abstract void Compact();
+//
+//        public abstract byte[] ToByteArray();
+//        
+//        public override string ToString()
+//        {
+//            StringBuilder buf = new StringBuilder();
+//            buf.Append("HeapBuffer");
+//            buf.AppendFormat("[pos={0} lim={1} cap={2} : {3}]", Position, Limit, Capacity, HexDump);
+//            return buf.ToString();
+//        }
+//
+//        public override int GetHashCode()
+//        {
+//            int h = 1;
+//            int p = Position;
+//            for (int i = Limit - 1; i >= p; i--)
+//            {
+//                h = 31 * h + Get(i);
+//            }
+//
+//            return h;
+//        }
+//
+//        public override bool Equals(object obj)
+//        {
+//            if (!(obj is ByteBuffer))
+//            {
+//                return false;
+//            }
+//            ByteBuffer that = (ByteBuffer) obj;
+//            
+//            if (Remaining != that.Remaining)
+//            {
+//                return false;
+//            }
+//            int p = Position;
+//            for (int i = 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;
+//        }
+//        
+//        public string HexDump
+//        {
+//            get
+//            {
+//                return ByteBufferHexDumper.GetHexDump(this);
+//            }
+//        }
+//
+//        /// <summary>
+//        /// Fills the buffer with the specified specified value. This method moves the buffer position forward.
+//        /// </summary>
+//        /// <param name="value">The value.</param>
+//        /// <param name="size">The size.</param>
+//        public void Fill(byte value, int size)
+//        {
+//            AutoExpand(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 |= (ushort)intValue;
+//                
+//                for (int i = q; i > 0; i--)
+//                {
+//                    Put((ulong)longValue);
+//                }
+//            }
+//
+//            q = r >> 2;
+//            r = r & 3;
+//            
+//            if (q > 0)
+//            {
+//                int intValue = value | (value << 8) | (value << 16) | (value << 24);
+//                Put((uint)intValue);
+//            }
+//
+//            q = r >> 1;
+//            r = r & 1;
+//            
+//            if (q > 0)
+//            {
+//                short shortValue = (short) (value | (value << 8));
+//                Put((ushort) shortValue);
+//            }
+//            if (r > 0)
+//            {
+//                Put(value);
+//            }
+//        }
+//        
+//        public void FillAndReset(byte value, int size)
+//        {
+//            AutoExpand(size);
+//            int pos = Position;
+//            try
+//            {
+//                Fill(value, size);
+//            }
+//            finally
+//            {
+//                Position = pos;
+//            }            
+//        }
+//        
+//        public void Fill(int size)
+//        {
+//            AutoExpand(size);
+//            int q = size >> 3;
+//            int r = size & 7;
+//
+//            for (int i = q; i > 0; i--)
+//            {
+//                Put(0L);
+//            }
+//
+//            q = r >> 2;
+//            r = r & 3;
+//
+//            if (q > 0)
+//            {
+//                Put(0);
+//            }
+//
+//            q = r >> 1;
+//            r = r & 1;
+//
+//            if(q > 0)
+//            {
+//                Put((ushort) 0);
+//            }
+//
+//            if (r > 0)
+//            {
+//                Put((byte) 0);
+//            }
+//        }
+//        
+//        public void FillAndReset(int size)
+//        {
+//            AutoExpand(size);
+//            int pos = Position;
+//            try
+//            {
+//                Fill(size);
+//            }
+//            finally
+//            {
+//                Position = pos;
+//            }
+//        }
+//        
+//        public void Skip(int size)
+//        {
+//            AutoExpand(size);
+//            Position = Position + size;
+//        }
+//        
+//        protected void AutoExpand(int expectedRemaining)
+//        {
+//            if (IsAutoExpand)
+//            {
+//                Expand(expectedRemaining);
+//            }
+//        }
+//        
+//        protected void AutoExpand(int pos, int expectedRemaining)
+//        {
+//            if (IsAutoExpand)
+//            {
+//                Expand(pos, expectedRemaining);
+//            }
+//        }                
+//    }
+
+    /*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+//package org.apache.mina.common;
+//
+//import java.io.IOException;
+//import java.io.InputStream;
+//import java.io.ObjectInputStream;
+//import java.io.ObjectOutputStream;
+//import java.io.ObjectStreamClass;
+//import java.io.OutputStream;
+//import java.nio.BufferOverflowException;
+//import java.nio.BufferUnderflowException;
+//import java.nio.ByteOrder;
+//import java.nio.CharBuffer;
+//import java.nio.DoubleBuffer;
+//import java.nio.FloatBuffer;
+//import java.nio.IntBuffer;
+//import java.nio.LongBuffer;
+//import java.nio.ShortBuffer;
+//import java.nio.charset.CharacterCodingException;
+//import java.nio.charset.CharsetDecoder;
+//import java.nio.charset.CharsetEncoder;
+//import java.nio.charset.CoderResult;
+//
+//import org.apache.mina.common.support.ByteBufferHexDumper;
+//import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+    /**
+     * A byte buffer used by MINA applications.
+     * <p>
+     * This is a replacement for {@link FixedByteBuffer}. Please refer to
+     * {@link FixedByteBuffer} and {@link java.nio.Buffer} documentation for
+     * usage.  MINA does not use NIO {@link FixedByteBuffer} 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 hard to distinguish if the buffer is created from MINA buffer
+     * pool or not.  MINA have to return used buffers back to pool.</li>
+     * <li>It is difficult to write variable-length data due to its fixed
+     * capacity</li>
+     * </ul>
+     * </p>
+     *
+     * <h2>Allocation</h2>
+     * <p>
+     * You can get a heap buffer from buffer pool:
+     * <pre>
+     * ByteBuffer buf = ByteBuffer.allocate(1024, false);
+     * </pre>
+     * you can also get a direct buffer from buffer pool:
+     * <pre>
+     * ByteBuffer buf = ByteBuffer.allocate(1024, true);
+     * </pre>
+     * or you can let MINA choose:
+     * <pre>
+     * ByteBuffer buf = ByteBuffer.allocate(1024);
+     * </pre>
+     * </p>
+     *
+     * <h2>Acquire/Release</h2>
+     * <p>
+     * <b>Please note that you never need to release the allocated buffer</b>
+     * because MINA will release it automatically when:
+     * <ul>
+     * <li>You pass the buffer by calling {@link IoSession#write(Object)}.</li>
+     * <li>You pass the buffer by calling {@link IoFilter.NextFilter#filterWrite(IoSession,IoFilter.WriteRequest)}.</li>
+     * <li>You pass the buffer by calling {@link ProtocolEncoderOutput#write(ByteBuffer)}.</li>
+     * </ul>
+     * And, you don't need to release any {@link ByteBuffer} which is passed as a parameter
+     * of {@link IoHandler#messageReceived(IoSession, Object)} method.  They are released
+     * automatically when the method returns.
+     * <p>
+     * You have to release buffers manually by calling {@link #release()} when:
+     * <ul>
+     * <li>You allocated a buffer, but didn't pass the buffer to any of two methods above.</li>
+     * <li>You called {@link #acquire()} to prevent the buffer from being released.</li>
+     * </ul>
+     * </p>
+     *
+     * <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.  Wrapped MINA buffers are not returned
+     * to the buffer pool by default to prevent unexpected memory leakage by default.
+     * In case you want to make it pooled, you can call {@link #setPooled(bool)}
+     * with <tt>true</tt> flag to enable pooling.
+     *
+     * <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.  MINA <tt>ByteBuffer</tt>
+     * introduces <tt>autoExpand</tt> property.  If <tt>autoExpand</tt> property
+     * is true, you never get {@link BufferOverflowException} or
+     * {@link IndexOutOfBoundsException} (except when index is negative).
+     * It automatically expands its capacity and limit value.  For example:
+     * <pre>
+     * String greeting = messageBundle.getMessage( "hello" );
+     * ByteBuffer buf = ByteBuffer.allocate( 16 );
+     * // Turn on autoExpand (it is off by default)
+     * buf.setAutoExpand( true );
+     * buf.putString( greeting, utf8encoder );
+     * </pre>
+     * NIO <tt>ByteBuffer</tt> is reallocated by MINA <tt>ByteBuffer</tt> behind
+     * the scene if the encoded data is larger than 16 bytes.  Its capacity will
+     * increase by two times, and its limit will increase to the last position
+     * the string is written.
+     * </p>
+     *
+     * <h2>Derived Buffers</h2>
+     * <p>
+     * Derived buffers are the buffers which were created by
+     * {@link #duplicate()}, {@link #slice()}, or {@link #asReadOnlyBuffer()}.
+     * They are useful especially when you broadcast the same messages to
+     * multiple {@link IoSession}s.  Please note that the derived buffers are
+     * neither pooled nor auto-expandable.  Trying to expand a derived buffer will
+     * raise {@link IllegalStateException}.
+     * </p>
+     *
+     * <h2>Changing Buffer Allocation and Management Policy</h2>
+     * <p>
+     * MINA provides a {@link ByteBufferAllocator} interface to let you override
+     * the default buffer management behavior.  There are two allocators provided
+     * out-of-the-box:
+     * <ul>
+     * <li>{@link PooledByteBufferAllocator} (Default)</li>
+     * <li>{@link SimpleByteBufferAllocator}</li>
+     * </ul>
+     * You can change the allocator by calling {@link #setAllocator(ByteBufferAllocator)}.
+     * </p>
+     *
+     * @author The Apache Directory Project (mina-dev@directory.apache.org)
+     * @version $Rev: 451854 $, $Date: 2006-10-02 11:30:11 +0900 (월, 02 10월 2006) $
+     * @noinspection StaticNonFinalField
+     * @see ByteBufferAllocator
+     */
+    public abstract class ByteBuffer : IComparable
     {
-        protected const int MINIMUM_CAPACITY = 1;
-        
-        protected static Stack _containerStack = new Stack();
-        
-        protected static Stack[] _heapBufferStacks = new Stack[]
-            {
-                new Stack(), new Stack(), new Stack(), new Stack(), 
-                new Stack(), new Stack(), new Stack(), new Stack(), 
-                new Stack(), new Stack(), new Stack(), new Stack(), 
-                new Stack(), new Stack(), new Stack(), new Stack(), 
-                new Stack(), new Stack(), new Stack(), new Stack(), 
-                new Stack(), new Stack(), new Stack(), new Stack(), 
-                new Stack(), new Stack(), new Stack(), new Stack(), 
-                new Stack(), new Stack(), new Stack(), new Stack()
-            };
-
-        /// <summary>
-        /// Returns the direct or heap buffer which is capable of the specified size.
-        /// Currently does not support direct buffers but this will be an option in future.
-        /// </summary>
-        /// <param name="capacity">The capacity.</param>
-        /// <returns></returns>
-        public static ByteBuffer Allocate(int capacity)
-        {
-            // for now, just allocate a heap buffer but in future could do an optimised "direct" buffer
-            // that is implemented natively
-            return Allocate(capacity, false);
-        }
-        
-        public static ByteBuffer Allocate(int capacity, bool direct)
-        {
-            ByteBuffer buffer = Allocate0(capacity, direct);
-            RefCountingByteBuffer buf = AllocateContainer();
-            buf.Init(buffer);
-            return buf;
-        }
-        
-        private static RefCountingByteBuffer AllocateContainer()
+        //private static ByteBufferAllocator allocator = new PooledByteBufferAllocator();
+        private static ByteBufferAllocator allocator = new SimpleByteBufferAllocator();
+
+        private static bool _useDirectBuffers = false;
+
+        public string HexDump
         {
-            RefCountingByteBuffer buf = null;
-            lock (_containerStack)
-            {
-                if (_containerStack.Count > 0)
-                {
-                    buf = (RefCountingByteBuffer) _containerStack.Pop();
-                }
-            }
-            
-            if (buf == null)
+            get
             {
-                buf = new RefCountingByteBuffer();                
+                return ByteBufferHexDumper.GetHexDump(this);
             }
-            return buf;
         }
-        
-        protected static ByteBuffer Allocate0(int capacity, bool direct)
+
+        /**
+         * Returns the current allocator which manages the allocated buffers.
+         */
+        public static ByteBufferAllocator getAllocator()
         {
-            if (direct)
-            {
-                throw new NotSupportedException("Direct buffers not currently implemented");
-            }            
-            int idx = GetBufferStackIndex(_heapBufferStacks, capacity);
-            Stack stack = _heapBufferStacks[idx];
-            ByteBuffer buf = null;
-            lock (stack)
+            return allocator;
+        }
+
+        /**
+         * Changes the current allocator with the specified one to manage
+         * the allocated buffers from now.
+         */
+        public static void setAllocator( ByteBufferAllocator newAllocator )
+        {
+            if( newAllocator == null )
             {
-                if (stack.Count > 0)
-                {
-                    buf = (ByteBuffer) stack.Pop();
-                }
+                throw new NullReferenceException("allocator cannot be null");
             }
 
-            if (buf == null)
+            ByteBufferAllocator oldAllocator = allocator;
+
+            allocator = newAllocator;
+
+            if( null != oldAllocator )
             {
-                buf = new HeapByteBuffer(MINIMUM_CAPACITY << idx);
+                oldAllocator.dispose();
             }
+        }
 
-            return buf;
+        public static bool isUseDirectBuffers()
+        {
+            return _useDirectBuffers;
         }
-        
-        protected static void Release0(ByteBuffer buf)
+
+        public static void setUseDirectBuffers( bool useDirectBuffers )
         {
-            Stack stack = _heapBufferStacks[GetBufferStackIndex(_heapBufferStacks, buf.Capacity)];
-            lock (stack)
-            {
-                stack.Push(buf);
-            }            
+            _useDirectBuffers = useDirectBuffers;
         }
-        
-        private static int GetBufferStackIndex(Stack[] bufferStacks, int size)
+
+        /**
+         * Returns the direct or heap buffer which is capable of the specified
+         * size.  This method tries to allocate direct buffer first, and then
+         * tries heap buffer if direct buffer memory is exhausted.  Please use
+         * {@link #allocate(int, bool)} to allocate buffers of specific type.
+         *
+         * @param capacity the capacity of the buffer
+         */
+        public static ByteBuffer allocate( int capacity )
         {
-            int targetSize = MINIMUM_CAPACITY;
-            int stackIdx = 0;
-            // each bucket contains buffers that are double the size of the previous bucket
-            while (size > targetSize)
-            {
-                targetSize <<= 1;
-                stackIdx++;
-                if (stackIdx >= bufferStacks.Length)
+            if( _useDirectBuffers )
+            {
+                try
                 {
-                    throw new ArgumentOutOfRangeException("size", "Buffer size is too big: " + size);
+                    // first try to allocate direct buffer
+                    return allocate( capacity, true );
+                }
+                catch (OutOfMemoryException)
+                {
+                    // fall through to heap buffer
                 }
             }
-            return stackIdx;
-        }
 
-        /// <summary>
-        /// Increases the internal reference count of this buffer to defer automatic release. You have
-        /// to invoke release() as many times as you invoked this method to release this buffer.
-        /// </summary>
-        public abstract void Acquire();
-
-        /// <summary>
-        /// Releases the specified buffer to the buffer pool.
-        /// </summary>
-        public abstract void Release();
+            return allocate( capacity, false );
+        }
 
-        public abstract int Capacity
+        /**
+         * Returns the buffer which is capable of the specified size.
+         *
+         * @param capacity the capacity of the buffer
+         * @param direct   <tt>true</tt> to get a direct buffer,
+         *                 <tt>false</tt> to get a heap buffer.
+         */
+        public static ByteBuffer allocate( int capacity, bool direct )
         {
-            get;
+            return allocator.allocate( capacity, direct );
         }
 
-        public abstract bool IsAutoExpand
+        /**
+         * Wraps the specified NIO {@link FixedByteBuffer} into MINA buffer.
+         */
+        public static ByteBuffer wrap( FixedByteBuffer nioBuffer )
         {
-            get;
-            set;
+            return allocator.wrap( nioBuffer );
         }
 
-        /// <summary>
-        /// Changes the capacity and limit of this buffer sot his buffer gets the specified
-        /// expectedRemaining room from the current position. This method works even if you didn't set
-        /// autoExpand to true.
-        /// </summary>
-        /// <param name="expectedRemaining">Room you want from the current position</param>        
-        public abstract void Expand(int expectedRemaining);
-
-        /// <summary>
-        /// Changes the capacity and limit of this buffer sot his buffer gets the specified
-        /// expectedRemaining room from the specified position.
-        /// </summary>
-        /// <param name="pos">The pos you want the room to be available from.</param>
-        /// <param name="expectedRemaining">The expected room you want available.</param>        
-        public abstract void Expand(int pos, int expectedRemaining);
-
-        /// <summary>
-        /// Returns true if and only if this buffer is returned back to the buffer pool when released.
-        /// </summary>
-        /// <value><c>true</c> if pooled; otherwise, <c>false</c>.</value>
-        public abstract bool Pooled
+        /**
+         * Wraps the specified byte array into MINA heap buffer.
+         */
+        public static ByteBuffer wrap( byte[] byteArray )
         {
-            get;
-            set;
+            return wrap( FixedByteBuffer.wrap( byteArray ) );
         }
-        
-        public abstract int Position
+
+        /**
+         * Wraps the specified byte array into MINA heap buffer.
+         * Please note that MINA buffers are going to be pooled, and
+         * therefore there can be waste of memory if you wrap
+         * your byte array specifying <tt>offset</tt> and <tt>length</tt>.
+         */
+        public static ByteBuffer wrap( byte[] byteArray, int offset, int length )
         {
-            get;
-            set;
+            return wrap( FixedByteBuffer.wrap( byteArray, offset, length ) );
         }
 
-        public abstract int Limit
+        protected ByteBuffer()
         {
-            get;
-            set;
         }
 
-        //public abstract void Mark();
+        /**
+         * Increases the internal reference count of this buffer to defer
+         * automatic release.  You have to invoke {@link #release()} as many
+         * as you invoked this method to release this buffer.
+         *
+         * @throws IllegalStateException if you attempt to acquire already
+         *                               released buffer.
+         */
+        public abstract void acquire();
 
-        //public abstract void Reset();
+        /**
+         * Releases the specified buffer to buffer pool.
+         *
+         * @throws IllegalStateException if you attempt to release already
+         *                               released buffer.
+         */
+        public abstract void release();
 
-        public abstract void Clear();
+        /**
+         * Returns the underlying NIO buffer instance.
+         */
+        public abstract FixedByteBuffer buf();
 
-        /// <summary>
-        /// Clears this buffer and fills its content with NULL. The position is set to zero, the limit is set to
-        /// capacity and the mark is discarded.
-        /// </summary>
-        public void Sweep()
-        {
-            Clear();
-            FillAndReset(Remaining);
-        }
+        /**
+         * @see FixedByteBuffer#isDirect()
+         */
+        public abstract bool isDirect();
         
-        public void Sweep(byte value)
-        {
-            Clear();
-            FillAndReset(value, Remaining);
-        }
-
-        public abstract void Flip();
-
-        public abstract void Rewind();
-
-        public abstract int Remaining
-        {
-            get;
-        }
+        /**
+         * @see FixedByteBuffer#isReadOnly()
+         */
+        public abstract bool isReadOnly();
+
+        /**
+         * @see FixedByteBuffer#capacity()
+         */
+        public abstract int capacity();
+        
+        /**
+         * Changes the capacity of this buffer.
+         */
+        public abstract ByteBuffer capacity( int newCapacity );
         
-        public bool HasRemaining()
+        /**
+         * Returns <tt>true</tt> if and only if <tt>autoExpand</tt> is turned on.
+         */
+        public abstract bool isAutoExpand();
+
+        /**
+         * Turns on or off <tt>autoExpand</tt>.
+         */
+        public abstract ByteBuffer setAutoExpand( bool autoExpand );
+
+        /**
+         * 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>.
+         */
+        public ByteBuffer expand( int expectedRemaining )
         {
-            return Remaining > 0;
+            return expand( position(), expectedRemaining );
         }
-
-        public abstract byte Get();
-
-        public abstract byte Get(int index);
         
-        public abstract void Get(byte[] destination);
-
-        public abstract ushort GetUnsignedShort();
-
-        public abstract uint GetUnsignedInt();
-
-        public abstract ulong GetUnsignedLong();
-
-        public abstract string GetString(uint length, Encoding encoder);
-
-        public abstract void Put(byte data);
-
-        public abstract void Put(byte[] data);
-        public abstract void Put(byte[] data, int offset, int size);
-
-        public abstract void Put(ushort data);
-
-        public abstract void Put(uint data);
-
-        public abstract void Put(ulong data);
-
-        public abstract void Put(ByteBuffer buf);
+        /**
+         * Changes the capacity and limit of this buffer so this buffer get
+         * the specified <tt>expectedRemaining</tt> room from the specified
+         * <tt>pos</tt>.
+         * This method works even if you didn't set <tt>autoExpand</tt> to
+         * <tt>true</tt>.
+         */
+        public abstract ByteBuffer expand( int pos, int expectedRemaining );
+
+        /**
+         * Returns <tt>true</tt> if and only if this buffer is returned back
+         * to the buffer pool when released.
+         * <p>
+         * The default value of this property is <tt>true</tt> if and only if you
+         * allocated this buffer using {@link #allocate(int)} or {@link #allocate(int, bool)},
+         * or <tt>false</tt> otherwise. (i.e. {@link #wrap(byte[])}, {@link #wrap(byte[], int, int)},
+         * and {@link #wrap(FixedByteBuffer)})
+         */
+        public abstract bool isPooled();
+
+        /**
+         * Sets whether this buffer is returned back to the buffer pool when released.
+         * <p>
+         * The default value of this property is <tt>true</tt> if and only if you
+         * allocated this buffer using {@link #allocate(int)} or {@link #allocate(int, bool)},
+         * or <tt>false</tt> otherwise. (i.e. {@link #wrap(byte[])}, {@link #wrap(byte[], int, int)},
+         * and {@link #wrap(FixedByteBuffer)})
+         */
+        public abstract void setPooled( bool pooled );
+
+        /**
+         * @see java.nio.Buffer#position()
+         */
+        public abstract int position();
+
+        /**
+         * @see java.nio.Buffer#position(int)
+         */
+        public abstract ByteBuffer position( int newPosition );
         
-        public abstract void Compact();
-
-        public abstract byte[] ToByteArray();
+        /**
+         * @see java.nio.Buffer#limit()
+         */
+        public abstract int limit();
+
+        /**
+         * @see java.nio.Buffer#limit(int)
+         */
+        public abstract ByteBuffer limit( int newLimit );
+
+        /**
+         * @see java.nio.Buffer#mark()
+         */
+        public abstract ByteBuffer mark();
+        
+        /**
+         * Returns 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()
+         */
+        public abstract ByteBuffer reset();
+        
+        /**
+         * @see java.nio.Buffer#clear()
+         */
+        public abstract ByteBuffer clear();
         
-        public override string ToString()
+        /**
+         * 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.
+         */
+//        public ByteBuffer sweep()
+//        {
+//            clear();
+//            return fillAndReset( remaining() );
+//        }
+
+        /**
+         * 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.
+         */
+//        public ByteBuffer sweep( byte value )
+//        {
+//            clear();
+//            return fillAndReset( value, remaining() );
+//        }
+
+        /**
+         * @see java.nio.Buffer#flip()
+         */
+        public abstract ByteBuffer flip();
+
+        /**
+         * @see java.nio.Buffer#rewind()
+         */
+        public abstract ByteBuffer rewind();
+
+        /**
+         * @see java.nio.Buffer#remaining()
+         */
+        public int remaining()
+        {
+            return limit() - position();
+        }
+
+        /**
+         * @see java.nio.Buffer#hasRemaining()
+         */
+        public bool hasRemaining()
+        {
+            return remaining() > 0;
+        }
+
+        /**
+         * @see FixedByteBuffer#duplicate()
+         */
+        public abstract ByteBuffer duplicate();
+
+        /**
+         * @see FixedByteBuffer#slice()
+         */
+        public abstract ByteBuffer slice();
+
+        /**
+         * @see FixedByteBuffer#asReadOnlyBuffer()
+         */
+        public abstract ByteBuffer asReadOnlyBuffer();
+
+        /**
+         * @see FixedByteBuffer#array()
+         */
+        public abstract byte[] array();
+
+        /**
+         * @see FixedByteBuffer#arrayOffset()
+         */
+        public abstract int arrayOffset();
+
+        /**
+         * @see FixedByteBuffer#get()
+         */
+        public abstract byte get();
+
+        /**
+         * Reads one unsigned byte as a short integer.
+         */
+        public short getUnsigned()
+        {
+            return (short)( get() & 0xff );
+        }
+
+        /**
+         * @see FixedByteBuffer#put(byte)
+         */
+        public abstract ByteBuffer put( byte b );
+
+        /**
+         * @see FixedByteBuffer#get(int)
+         */
+        public abstract byte get( int index );
+
+        /**
+         * Reads one byte as an unsigned short integer.
+         */
+        public short getUnsigned( int index )
+        {
+            return (short)( get( index ) & 0xff );
+        }
+
+        /**
+         * @see FixedByteBuffer#put(int, byte)
+         */
+        public abstract ByteBuffer put( int index, byte b );
+
+        /**
+         * @see FixedByteBuffer#get(byte[], int, int)
+         */
+        public abstract ByteBuffer get( byte[] dst, int offset, int length );
+
+        /**
+         * @see FixedByteBuffer#get(byte[])
+         */
+        public abstract ByteBuffer get(byte[] dst);
+//        {
+//            return get( dst, 0, dst.Length );
+//        }
+
+        /**
+         * Writes the content of the specified <tt>src</tt> into this buffer.
+         */
+        public abstract ByteBuffer put( FixedByteBuffer src );
+
+        /**
+         * Writes the content of the specified <tt>src</tt> into this buffer.
+         */
+        public ByteBuffer put( ByteBuffer src )
+        {
+            return put( src.buf() );
+        }
+
+        /**
+         * @see FixedByteBuffer#put(byte[], int, int)
+         */
+        public abstract ByteBuffer put( byte[] src, int offset, int length );
+
+        /**
+         * @see FixedByteBuffer#put(byte[])
+         */
+        public abstract ByteBuffer put(byte[] src);
+//        {
+//            return put(src);
+////            return put( src, 0, src.Length );
+//        }
+
+        /**
+         * @see FixedByteBuffer#compact()
+         */
+        public abstract ByteBuffer compact();
+
+        public String toString()
         {
             StringBuilder buf = new StringBuilder();
-            buf.Append("HeapBuffer");
-            buf.AppendFormat("[pos={0} lim={1} cap={2} : {3}]", Position, Limit, Capacity, HexDump);
+            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() );
+            buf.Append( ']' );
             return buf.ToString();
         }
 
-        public override int GetHashCode()
+        public int hashCode()
         {
             int h = 1;
-            int p = Position;
-            for (int i = Limit - 1; i >= p; i--)
+            int p = position();
+            for( int i = limit() - 1; i >= p; i -- )
             {
-                h = 31 * h + Get(i);
+                h = 31 * h + get( i );
             }
-
             return h;
         }
 
-        public override bool Equals(object obj)
+        public bool equals( Object o )
         {
-            if (!(obj is ByteBuffer))
+            if( !( o is ByteBuffer ) )
             {
                 return false;
             }
-            ByteBuffer that = (ByteBuffer) obj;
-            
-            if (Remaining != that.Remaining)
+
+            ByteBuffer that = (ByteBuffer)o;
+            if( this.remaining() != that.remaining() )
             {
                 return false;
             }
-            int p = Position;
-            for (int i = Limit - 1, j = that.Limit - 1; i >= p; i--, j--)
+
+            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)
+                byte v1 = this.get( i );
+                byte v2 = that.get( j );
+                if( v1 != v2 )
                 {
                     return false;
                 }
             }
             return true;
         }
-        
-        public string HexDump
-        {
-            get
-            {
-                return ByteBufferHexDumper.GetHexDump(this);
-            }
-        }
 
-        /// <summary>
-        /// Fills the buffer with the specified specified value. This method moves the buffer position forward.
-        /// </summary>
-        /// <param name="value">The value.</param>
-        /// <param name="size">The size.</param>
-        public void Fill(byte value, int size)
-        {
-            AutoExpand(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 |= (ushort)intValue;
-                
-                for (int i = q; i > 0; i--)
+        public int CompareTo( Object o )
+        {
+            ByteBuffer that = (ByteBuffer)o;
+            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 )
                 {
-                    Put((ulong)longValue);
+                    continue;
+                }
+                if( v1 < v2 )
+                {
+                    return -1;
                 }
-            }
-
-            q = r >> 2;
-            r = r & 3;
-            
-            if (q > 0)
-            {
-                int intValue = value | (value << 8) | (value << 16) | (value << 24);
-                Put((uint)intValue);
-            }
 
-            q = r >> 1;
-            r = r & 1;
-            
-            if (q > 0)
-            {
-                short shortValue = (short) (value | (value << 8));
-                Put((ushort) shortValue);
+                return +1;
             }
-            if (r > 0)
-            {
-                Put(value);
-            }
-        }
-        
-        public void FillAndReset(byte value, int size)
-        {
-            AutoExpand(size);
-            int pos = Position;
-            try
-            {
-                Fill(value, size);
-            }
-            finally
-            {
-                Position = pos;
-            }            
+            return this.remaining() - that.remaining();
         }
-        
-        public void Fill(int size)
-        {
-            AutoExpand(size);
-            int q = size >> 3;
-            int r = size & 7;
-
-            for (int i = q; i > 0; i--)
-            {
-                Put(0L);
-            }
-
-            q = r >> 2;
-            r = r & 3;
-
-            if (q > 0)
-            {
-                Put(0);
-            }
 
-            q = r >> 1;
-            r = r & 1;
-
-            if(q > 0)
-            {
-                Put((ushort) 0);
-            }
-
-            if (r > 0)
-            {
-                Put((byte) 0);
-            }
-        }
-        
-        public void FillAndReset(int size)
+        /**
+         * @see FixedByteBuffer#order()
+         */
+        public abstract ByteOrder order();
+
+        /**
+         * @see FixedByteBuffer#order(ByteOrder)
+         */
+        public abstract ByteBuffer order( ByteOrder bo );
+
+        /**
+         * @see FixedByteBuffer#getChar()
+         */
+        public abstract char getChar();
+
+        /**
+         * @see FixedByteBuffer#putChar(char)
+         */
+        public abstract ByteBuffer putChar( char value );
+
+        /**
+         * @see FixedByteBuffer#getChar(int)
+         */
+        public abstract char getChar( int index );
+
+        /**
+         * @see FixedByteBuffer#putChar(int, char)
+         */
+        public abstract ByteBuffer putChar( int index, char value );
+
+        /**
+         * @see FixedByteBuffer#asCharBuffer()
+         */
+//        public abstract CharBuffer asCharBuffer();
+
+        /**
+         * @see FixedByteBuffer#getShort()
+         */
+        public abstract short getShort();
+
+        /**
+         * Reads two bytes unsigned integer.
+         */
+        public int getUnsignedShort()
+        {
+            return getShort() & 0xffff;
+        }
+
+        /**
+         * @see FixedByteBuffer#putShort(short)
+         */
+        public abstract ByteBuffer putShort( short value );
+
+        /**
+         * @see FixedByteBuffer#getShort()
+         */
+        public abstract short getShort( int index );
+
+        /**
+         * Reads two bytes unsigned integer.
+         */
+        public int getUnsignedShort( int index )
+        {
+            return getShort( index ) & 0xffff;
+        }
+
+        /**
+         * @see FixedByteBuffer#putShort(int, short)
+         */
+        public abstract ByteBuffer putShort( int index, short value );
+
+        /**
+         * @see FixedByteBuffer#asShortBuffer()
+         */
+//        public abstract ShortBuffer asShortBuffer();
+
+        /**
+         * @see FixedByteBuffer#getInt()
+         */
+        public abstract int getInt();
+
+        /**
+         * Reads four bytes unsigned integer.
+         */
+        public uint getUnsignedInt()
+        {
+//            return getInt() & 0xffffffffL;
+
+            //CheckSpaceForReading(4);
+            byte b1 = get();
+            byte b2 = get();
+            byte b3 = get();
+            byte b4 = get();
+            return (uint)((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
+        }
+
+        /**
+         * @see FixedByteBuffer#putInt(int)
+         */
+        public abstract ByteBuffer putInt( int value );
+
+        /**
+         * @see FixedByteBuffer#getInt(int)
+         */
+        public abstract int getInt( int index );
+
+        /**
+         * Reads four bytes unsigned integer.
+         */
+        public long getUnsignedInt( int index )
+        {
+            return getInt( index ) & 0xffffffffL;
+        }
+
+        /**
+         * @see FixedByteBuffer#putInt(int, int)
+         */
+        public abstract ByteBuffer putInt( int index, int value );
+
+        /**
+         * @see FixedByteBuffer#asIntBuffer()
+         */
+//        public abstract IntBuffer asIntBuffer();
+
+        /**
+         * @see FixedByteBuffer#getLong()
+         */
+        public abstract long getLong();
+
+        /**
+         * @see FixedByteBuffer#putLong(int, long)
+         */
+        public abstract ByteBuffer putLong( long value );
+
+        /**
+         * @see FixedByteBuffer#getLong(int)
+         */
+        public abstract long getLong( int index );
+
+        /**
+         * @see FixedByteBuffer#putLong(int, long)
+         */
+        public abstract ByteBuffer putLong( int index, long value );
+
+        /**
+         * @see FixedByteBuffer#asLongBuffer()
+         */
+//        public abstract LongBuffer asLongBuffer();
+
+        /**
+         * @see FixedByteBuffer#getFloat()
+         */
+        public abstract float getFloat();
+
+        /**
+         * @see FixedByteBuffer#putFloat(float)
+         */
+        public abstract ByteBuffer putFloat( float value );
+
+        /**
+         * @see FixedByteBuffer#getFloat(int)
+         */
+        public abstract float getFloat( int index );
+
+        /**
+         * @see FixedByteBuffer#putFloat(int, float)
+         */
+        public abstract ByteBuffer putFloat( int index, float value );
+
+        /**
+         * @see FixedByteBuffer#asFloatBuffer()
+         */
+//        public abstract FloatBuffer asFloatBuffer();
+
+        /**
+         * @see FixedByteBuffer#getDouble()
+         */
+        public abstract double getDouble();
+
+        /**
+         * @see FixedByteBuffer#putDouble(double)
+         */
+        public abstract ByteBuffer putDouble( double value );
+
+        /**
+         * @see FixedByteBuffer#getDouble(int)
+         */
+        public abstract double getDouble( int index );
+
+        /**
+         * @see FixedByteBuffer#putDouble(int, double)
+         */
+        public abstract ByteBuffer putDouble( int index, double value );
+
+        /**
+         * @see FixedByteBuffer#asDoubleBuffer()
+         */
+//        public abstract DoubleBuffer asDoubleBuffer();
+
+        /**
+         * Returns 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 InputStream asInputStream()
+//        {
+//            // XXX: Use System.IO.Stream here?
+//            return new InputStream()
+//            {
+//                public int available()
+//                {
+//                    return ByteBuffer.this.remaining();
+//                }
+//
+//                public synchronized void mark( int readlimit )
+//                {
+//                    ByteBuffer.this.mark();
+//                }
+//
+//                public bool markSupported()
+//                {
+//                    return true;
+//                }
+//
+//                public int read()
+//                {
+//                    if( ByteBuffer.this.hasRemaining() )
+//                    {
+//                        return ByteBuffer.this.get() & 0xff;
+//                    }
+//                    else
+//                    {
+//                        return -1;
+//                    }
+//                }
+//
+//                public int read( byte[] b, int off, int len )
+//                {
+//                    int remaining = ByteBuffer.this.remaining();
+//                    if( remaining > 0 )
+//                    {
+//                        int readBytes = Math.min( remaining, len );
+//                        ByteBuffer.this.get( b, off, readBytes );
+//                        return readBytes;
+//                    }
+//                    else
+//                    {
+//                        return -1;
+//                    }
+//                }
+//
+//                public synchronized void reset()
+//                {
+//                    ByteBuffer.this.reset();
+//                }
+//
+//                public long skip( long n )
+//                {
+//                    int bytes;
+//                    if( n > Integer.MAX_VALUE )
+//                    {
+//                        bytes = ByteBuffer.this.remaining();
+//                    }
+//                    else
+//                    {
+//                        bytes = Math.min( ByteBuffer.this.remaining(), (int)n );
+//                    }
+//                    ByteBuffer.this.skip( bytes );
+//                    return bytes;
+//                }
+//            };
+//        }
+
+        /**
+         * Returns 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(bool)} to prevent the unexpected runtime
+         * exception.
+         */
+//        public OutputStream asOutputStream()
+//        {
+//            return new OutputStream()
+//            {
+//                public void write( byte[] b, int off, int len )
+//                {
+//                    ByteBuffer.this.put( b, off, len );
+//                }
+//
+//                public void write( int b )
+//                {
+//                    ByteBuffer.this.put( (byte)b );
+//                }
+//            };
+//        }
+
+        /**
+         * Returns hexdump of this buffer.
+         */
+        public String getHexDump()
+        {
+            return ByteBufferHexDumper.GetHexDump(this);
+        }
+
+        ////////////////////////////////
+        // 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.
+         */
+//        public String getString( Encoding decoder )
+//        {
+//            if( !hasRemaining() )
+//            {
+//                return "";
+//            }
+//
+//            decoder.
+//            bool utf16 = decoder.charset().name().startsWith( "UTF-16" );
+//
+//            int oldPos = position();
+//            int oldLimit = limit();
+//            int end;
+//
+//            if( !utf16 )
+//            {
+//                while( hasRemaining() )
+//                {
+//                    if( get() == 0 )
+//                    {
+//                        break;
+//                    }
+//                }
+//
+//                end = position();
+//                if( end == oldLimit && get( end - 1 ) != 0 )
+//                {
+//                    limit( end );
+//                }
+//                else
+//                {
+//                    limit( end - 1 );
+//                }
+//            }
+//            else
+//            {
+//                while( remaining() >= 2 )
+//                {
+//                    if( ( get() == 0 ) && ( get() == 0 ) )
+//                    {
+//                        break;
+//                    }
+//                }
+//
+//                end = position();
+//                if( end == oldLimit || end == oldLimit - 1 )
+//                {
+//                    limit( end );
+//                }
+//                else
+//                {
+//                    limit( end - 2 );
+//                }
+//            }
+//
+//            position( oldPos );
+//            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;
+//                }
+//
+//                cr.throwException();
+//            }
+//
+//            limit( oldLimit );
+//            position( end );
+//            return out.flip().toString();
+//        }
+
+        /**
+         * 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
+         */
+//        public String getString( int fieldSize, CharsetDecoder decoder ) throws CharacterCodingException
+//        {
+//            checkFieldSize( fieldSize );
+//
+//            if( fieldSize == 0 )
+//            {
+//                return "";
+//            }
+//
+//            if( !hasRemaining() )
+//            {
+//                return "";
+//            }
+//
+//            bool utf16 = decoder.charset().name().startsWith( "UTF-16" );
+//
+//            if( utf16 && ( ( fieldSize & 1 ) != 0 ) )
+//            {
+//                throw new IllegalArgumentException( "fieldSize is not even." );
+//            }
+//
+//            int oldPos = position();
+//            int oldLimit = limit();
+//            int end = position() + fieldSize;
+//
+//            if( oldLimit < end )
+//            {
+//                throw new BufferUnderflowException();
+//            }
+//
+//            int i;
+//
+//            if( !utf16 )
+//            {
+//                for( i = 0; i < fieldSize; i ++ )
+//                {
+//                    if( get() == 0 )
+//                    {
+//                        break;
+//                    }
+//                }
+//
+//                if( i == fieldSize )
+//                {
+//                    limit( end );
+//                }
+//                else
+//                {
+//                    limit( position() - 1 );
+//                }
+//            }
+//            else
+//            {
+//                for( i = 0; i < fieldSize; i += 2 )
+//                {
+//                    if( ( get() == 0 ) && ( get() == 0 ) )
+//                    {
+//                        break;
+//                    }
+//                }
+//
+//                if( i == fieldSize )
+//                {
+//                    limit( end );
+//                }
+//                else
+//                {
+//                    limit( position() - 2 );
+//                }
+//            }
+//
+//            position( oldPos );
+//            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;
+//                }
+//
+//                cr.throwException();
+//            }
+//
+//            limit( oldLimit );
+//            position( end );
+//            return out.flip().toString();
+//        }
+
+        /**
+         * 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.
+         *
+         * @throws BufferOverflowException if the specified string doesn't fit
+         */
+//        public ByteBuffer 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;
+//        }
+
+        /**
+         * 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 fieldSize the maximum number of bytes to write
+         */
+//        public ByteBuffer putString(
+//            CharSequence val, int fieldSize, CharsetEncoder encoder ) throws CharacterCodingException
+//        {
+//            checkFieldSize( fieldSize );
+//
+//            if( fieldSize == 0 )
+//                return this;
+//
+//            autoExpand( fieldSize );
+//
+//            bool utf16 = encoder.charset().name().startsWith( "UTF-16" );
+//
+//            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;
+//        }
+
+        /**
+         * 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>.
+         */
+//        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)
+         */
+//        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 "";
+//            }
+//
+//            bool utf16 = decoder.charset().name().startsWith( "UTF-16" );
+//
+//            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();
+//        }
+
+        /**
+         * 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>.
+         *
+         * @throws BufferOverflowException if the specified string doesn't fit
+         */
+//        public ByteBuffer putPrefixedString( CharSequence in, CharsetEncoder encoder ) throws CharacterCodingException
+//        {
+//            return putPrefixedString( in, 2, 0, encoder );
+//        }
+
+        /**
+         * 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 prefixLength the length of the length field (1, 2, or 4)
+         *
+         * @throws BufferOverflowException if the specified string doesn't fit
+         */
+//        public ByteBuffer putPrefixedString( CharSequence in, int prefixLength, CharsetEncoder encoder )
+//            throws CharacterCodingException
+//        {
+//            return putPrefixedString( in, prefixLength, 0, encoder );
+//        }
+
+        /**
+         * 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 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)
+         *
+         * @throws BufferOverflowException if the specified string doesn't fit
+         */
+//        public ByteBuffer putPrefixedString( CharSequence in, int prefixLength, int padding, CharsetEncoder encoder )
+//            throws CharacterCodingException
+//        {
+//            return putPrefixedString( in, prefixLength, padding, (byte)0, encoder );
+//        }
+
+        /**
+         * 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>.
+         *
+         * @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
+         *
+         * @throws BufferOverflowException if the specified string doesn't fit
+         */
+//        public ByteBuffer 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 );
+//            int expectedLength = (int)( in.remaining() * encoder.averageBytesPerChar() ) + 1;
+//
+//            skip( prefixLength ); // make a room for the length field
+//            int oldPos = position();
+//            encoder.reset();
+//
+//            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() && isAutoExpand() )
+//                {
+//                    autoExpand( expectedLength );
+//                    continue;
+//                }
+//                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;
+//        }
+
+        /**
+         * Reads a Java object from the buffer using the context {@link ClassLoader}
+         * of the current thread.
+         */
+//        public Object getObject() throws ClassNotFoundException
+//        {
+//            return getObject( Thread.currentThread().getContextClassLoader() );
+//        }
+
+        /**
+         * Reads a Java object from the buffer using the specified <tt>classLoader</tt>.
+         */
+//        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() )
+//                {
+//                    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException
+//                    {
+//                        String className = readUTF();
+//                        Class clazz = Class.forName( className, true, classLoader );
+//                        return ObjectStreamClass.lookup( clazz );
+//                    }
+//                };
+//                return in.readObject();
+//            }
+//            catch( IOException e )
+//            {
+//                throw new BufferDataException( e );
+//            }
+//            finally
+//            {
+//                limit( oldLimit );
+//            }
+//        }
+
+        /**
+         * Writes the specified Java object to the buffer.
+         */
+//        public ByteBuffer putObject( Object o )
+//        {
+//            int oldPos = position();
+//            skip( 4 ); // Make a room for the length field.
+//            try
+//            {
+//                ObjectOutputStream out = new ObjectOutputStream( asOutputStream() )
+//                {
+//                    protected void writeClassDescriptor( ObjectStreamClass desc ) throws IOException
+//                    {
+//                        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;
+//        }
+
+        /**
+         * Returns <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.
+         *
+         * @param prefixLength the length of the prefix field (1, 2, or 4)
+         *
+         * @throws IllegalArgumentException if prefixLength is wrong
+         * @throws BufferDataException      if data length is negative
+         */
+        public bool prefixedDataAvailable( int prefixLength )
+        {
+            return prefixedDataAvailable( prefixLength, int.MaxValue);
+        }
+
+        /**
+         * Returns <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.
+         *
+         * @param prefixLength  the length of the prefix field (1, 2, or 4)
+         * @param maxDataLength the allowed maximum of the read data length
+         *
+         * @throws IllegalArgumentException if prefixLength is wrong
+         * @throws BufferDataException      if data length is negative or greater then <tt>maxDataLength</tt>
+         */
+        public bool prefixedDataAvailable( int prefixLength, int maxDataLength )
         {
-            AutoExpand(size);
-            int pos = Position;
-            try
+            if( remaining() < prefixLength )
             {
-                Fill(size);
+                return false;
             }
-            finally
+
+            int dataLength;
+            switch( prefixLength )
             {
-                Position = pos;
-            }
-        }
-        
-        public void Skip(int size)
+                case 1:
+                    dataLength = getUnsigned( position() );
+                    break;
+                case 2:
+                    dataLength = getUnsignedShort( position() );
+                    break;
+                case 4:
+                    dataLength = getInt( position() );
+                    break;
+                default:
+                    throw new ArgumentException("prefixLength: " + prefixLength);
+            }
+
+            if( dataLength < 0 || dataLength > maxDataLength )
+            {
+                throw new BufferDataException( "dataLength: " + dataLength );
+            }
+
+            return remaining() - prefixLength >= dataLength;
+        }
+
+        //////////////////////////
+        // Skip or fill methods //
+        //////////////////////////
+
+        /**
+         * Forwards the position of this buffer as the specified <code>size</code>
+         * bytes.
+         */
+        public ByteBuffer skip( int size )
+        {
+            autoExpand( size );
+            return position( position() + size );
+        }
+
+        /**
+         * Fills this buffer with the specified value.
+         * This method moves buffer position forward.
+         */
+//        public ByteBuffer fill( byte value, int size )
+//        {
+//            autoExpand( 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 -- )
+//                {
+//                    putLong( longValue );
+//                }
+//            }
+//
+//            q = r >>> 2;
+//            r = r & 3;
+//
+//            if( q > 0 )
+//            {
+//                int intValue = value | ( value << 8 ) | ( value << 16 )
+//                               | ( value << 24 );
+//                putInt( intValue );
+//            }
+//
+//            q = r >> 1;
+//            r = r & 1;
+//
+//            if( q > 0 )
+//            {
+//                short shortValue = (short)( value | ( value << 8 ) );
+//                putShort( shortValue );
+//            }
+//
+//            if( r > 0 )
+//            {
+//                put( value );
+//            }
+//
+//            return this;
+//        }
+
+        /**
+         * Fills this buffer with the specified value.
+         * This method does not change buffer position.
+         */
+//        public ByteBuffer fillAndReset( byte value, int size )
+//        {
+//            autoExpand( size );
+//            int pos = position();
+//            try
+//            {
+//                fill( value, size );
+//            }
+//            finally
+//            {
+//                position( pos );
+//            }
+//            return this;
+//        }
+
+        /**
+         * Fills this buffer with <code>NUL (0x00)</code>.
+         * This method moves buffer position forward.
+         */
+//        public ByteBuffer 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;
+//        }
+
+        /**
+         * Fills this buffer with <code>NUL (0x00)</code>.
+         * This method does not change buffer position.
+         */
+//        public ByteBuffer fillAndReset( int size )
+//        {
+//            autoExpand( size );
+//            int pos = position();
+//            try
+//            {
+//                fill( size );
+//            }
+//            finally
+//            {
+//                position( pos );
+//            }
+//
+//            return this;
+//        }
+
+        /**
+         * This method forwards the call to {@link #expand(int)} only when
+         * <tt>autoExpand</tt> property is <tt>true</tt>.
+         */
+        protected ByteBuffer autoExpand( int expectedRemaining )
+        {
+            if( isAutoExpand() )
+            {
+                expand( expectedRemaining );
+            }
+            return this;
+        }
+
+        /**
+         * This method forwards the call to {@link #expand(int)} only when
+         * <tt>autoExpand</tt> property is <tt>true</tt>.
+         */
+        protected ByteBuffer autoExpand( int pos, int expectedRemaining )
+        {
+            if( isAutoExpand() )
+            {
+                expand( pos, expectedRemaining );
+            }
+            return this;
+        }
+
+        private static void checkFieldSize( int fieldSize )
         {
-            AutoExpand(size);
-            Position = Position + size;
-        }
-        
-        protected void AutoExpand(int expectedRemaining)
-        {
-            if (IsAutoExpand)
+            if( fieldSize < 0 )
             {
-                Expand(expectedRemaining);
+                throw new ArgumentOutOfRangeException("fieldSize");
             }
         }
-        
-        protected void AutoExpand(int pos, int expectedRemaining)
-        {
-            if (IsAutoExpand)
-            {
-                Expand(pos, expectedRemaining);
-            }
-        }                
+
+        public abstract void put(ushort value);
+        public abstract ushort GetUnsignedShort();
+        public abstract uint GetUnsignedInt();
+        public abstract void put(uint max);
+        public abstract void put(ulong tag);
+        public abstract ulong GetUnsignedLong();
     }
 }
-