From b10ee442673d6d9c8abb46bd7a0606364930130d Mon Sep 17 00:00:00 2001
From: Steven Shaw
+ * 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:
+ *
+ *
+ * fill, get/putString, and
+ * get/putAsciiInt() enough.
+ * You can get a heap buffer from buffer pool: + *
+ * ByteBuffer buf = ByteBuffer.allocate(1024, false); + *+ * you can also get a direct buffer from buffer pool: + *
+ * ByteBuffer buf = ByteBuffer.allocate(1024, true); + *+ * or you can let MINA choose: + *
+ * ByteBuffer buf = ByteBuffer.allocate(1024); + *+ * + * + *
+ * Please note that you never need to release the allocated buffer + * because MINA will release it automatically when: + *
+ * You have to release buffers manually by calling {@link #release()} when: + *
+ * This class provides a few wrap(...) 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 true flag to enable pooling. + * + *
+ * Writing variable-length data using NIO ByteBuffers is not really + * easy, and it is because its size is fixed. MINA ByteBuffer + * introduces autoExpand property. If autoExpand 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: + *
+ * 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 ); + *+ * NIO ByteBuffer is reallocated by MINA ByteBuffer 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. + * + * + *
+ * 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}. + *
+ * + *+ * MINA provides a {@link ByteBufferAllocator} interface to let you override + * the default buffer management behavior. There are two allocators provided + * out-of-the-box: + *
+ * The default value of this property is true if and only if you + * allocated this buffer using {@link #allocate(int)} or {@link #allocate(int, bool)}, + * or false 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. + *
+ * The default value of this property is true if and only if you
+ * allocated this buffer using {@link #allocate(int)} or {@link #allocate(int, bool)},
+ * or false 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 );
+
+ /**
+ * @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 -1 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();
+
+ /**
+ * Clears this buffer and fills its content with NUL.
+ * 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() );
+// }
- public abstract void Flip();
+ /**
+ * Clears this buffer and fills its content with value.
+ * 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() );
+// }
- public abstract void Rewind();
+ /**
+ * @see java.nio.Buffer#flip()
+ */
+ public abstract ByteBuffer flip();
- public abstract int Remaining
+ /**
+ * @see java.nio.Buffer#rewind()
+ */
+ public abstract ByteBuffer rewind();
+
+ /**
+ * @see java.nio.Buffer#remaining()
+ */
+ public int remaining()
{
- get;
+ return limit() - position();
}
-
- public bool HasRemaining()
+
+ /**
+ * @see java.nio.Buffer#hasRemaining()
+ */
+ public bool hasRemaining()
{
- return Remaining > 0;
+ return remaining() > 0;
}
- public abstract byte Get();
+ /**
+ * @see FixedByteBuffer#duplicate()
+ */
+ public abstract ByteBuffer duplicate();
- public abstract byte Get(int index);
-
- public abstract void Get(byte[] destination);
+ /**
+ * @see FixedByteBuffer#slice()
+ */
+ public abstract ByteBuffer slice();
- public abstract ushort GetUnsignedShort();
+ /**
+ * @see FixedByteBuffer#asReadOnlyBuffer()
+ */
+ public abstract ByteBuffer asReadOnlyBuffer();
- public abstract uint GetUnsignedInt();
+ /**
+ * @see FixedByteBuffer#array()
+ */
+ public abstract byte[] array();
- public abstract ulong GetUnsignedLong();
+ /**
+ * @see FixedByteBuffer#arrayOffset()
+ */
+ public abstract int arrayOffset();
- public abstract string GetString(uint length, Encoding encoder);
+ /**
+ * @see FixedByteBuffer#get()
+ */
+ public abstract byte get();
- public abstract void Put(byte data);
+ /**
+ * Reads one unsigned byte as a short integer.
+ */
+ public short getUnsigned()
+ {
+ return (short)( get() & 0xff );
+ }
- public abstract void Put(byte[] data);
- public abstract void Put(byte[] data, int offset, int size);
+ /**
+ * @see FixedByteBuffer#put(byte)
+ */
+ public abstract ByteBuffer put( byte b );
- public abstract void Put(ushort data);
+ /**
+ * @see FixedByteBuffer#get(int)
+ */
+ public abstract byte get( int index );
- public abstract void Put(uint data);
+ /**
+ * Reads one byte as an unsigned short integer.
+ */
+ public short getUnsigned( int index )
+ {
+ return (short)( get( index ) & 0xff );
+ }
- public abstract void Put(ulong data);
+ /**
+ * @see FixedByteBuffer#put(int, byte)
+ */
+ public abstract ByteBuffer put( int index, byte b );
- public abstract void Put(ByteBuffer buf);
-
- public abstract void Compact();
+ /**
+ * @see FixedByteBuffer#get(byte[], int, int)
+ */
+ public abstract ByteBuffer get( byte[] dst, int offset, int length );
- public abstract byte[] ToByteArray();
-
- public override string ToString()
+ /**
+ * @see FixedByteBuffer#get(byte[])
+ */
+ public abstract ByteBuffer get(byte[] dst);
+// {
+// return get( dst, 0, dst.Length );
+// }
+
+ /**
+ * Writes the content of the specified src into this buffer.
+ */
+ public abstract ByteBuffer put( FixedByteBuffer src );
+
+ /**
+ * Writes the content of the specified src 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);
- }
- }
- /// NUL-terminated string from this buffer using the
+ * specified decoder and returns it. This method reads
+ * until the limit of this buffer if no NUL 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 NUL-terminated string from this buffer using the
+ * specified decoder 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 in into this buffer using the
+ * specified encoder. This method doesn't terminate
+ * string with NUL. 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 in into this buffer as a
+ * NUL-terminated string using the specified
+ * encoder.
+ *
+ * If the charset name of the encoder is UTF-16, you cannot specify
+ * odd fieldSize, and this method will Append two
+ * NULs as a terminator.
+ *
+ * Please note that this method doesn't terminate with NUL
+ * if the input string is longer than fieldSize.
+ *
+ * @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 decoder and returns it.
+ * This method is a shortcut for getPrefixedString(2, decoder).
+ */
+// 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 decoder 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 in into this buffer as a
+ * string which has a 16-bit length field before the actual
+ * encoded string, using the specified encoder.
+ * This method is a shortcut for putPrefixedString(in, 2, 0, encoder).
+ *
+ * @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 in into this buffer as a
+ * string which has a 16-bit length field before the actual
+ * encoded string, using the specified encoder.
+ * This method is a shortcut for putPrefixedString(in, prefixLength, 0, encoder).
+ *
+ * @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 in into this buffer as a
+ * string which has a 16-bit length field before the actual
+ * encoded string, using the specified encoder.
+ * This method is a shortcut for putPrefixedString(in, prefixLength, padding, ( byte ) 0, encoder).
+ *
+ * @param prefixLength the length of the length field (1, 2, or 4)
+ * @param padding the number of padded NULs (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 in into this buffer as a
+ * string which has a 16-bit length field before the actual
+ * encoded string, using the specified encoder.
+ *
+ * @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 classLoader.
+ */
+// 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 true 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
+ * prefixedDataAvailable( prefixLength, Integer.MAX_VALUE ).
+ * 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 true 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 maxDataLength
+ */
+ public bool prefixedDataAvailable( int prefixLength, int maxDataLength )
+ {
+ if( remaining() < prefixLength )
{
- Put(0);
+ return false;
}
- q = r >> 1;
- r = r & 1;
-
- if(q > 0)
+ int dataLength;
+ switch( prefixLength )
{
- Put((ushort) 0);
+ 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 (r > 0)
+ if( dataLength < 0 || dataLength > maxDataLength )
{
- Put((byte) 0);
+ throw new BufferDataException( "dataLength: " + dataLength );
}
+
+ return remaining() - prefixLength >= dataLength;
}
-
- public void FillAndReset(int size)
+
+ //////////////////////////
+ // Skip or fill methods //
+ //////////////////////////
+
+ /**
+ * Forwards the position of this buffer as the specified size
+ * bytes.
+ */
+ public ByteBuffer skip( int size )
{
- AutoExpand(size);
- int pos = Position;
- try
- {
- Fill(size);
- }
- finally
- {
- Position = pos;
- }
+ autoExpand( size );
+ return position( position() + size );
}
-
- public void Skip(int 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 NUL (0x00).
+ * 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 NUL (0x00).
+ * 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
+ * autoExpand property is true.
+ */
+ protected ByteBuffer autoExpand( int expectedRemaining )
{
- AutoExpand(size);
- Position = Position + size;
+ if( isAutoExpand() )
+ {
+ expand( expectedRemaining );
+ }
+ return this;
}
-
- protected void AutoExpand(int expectedRemaining)
+
+ /**
+ * This method forwards the call to {@link #expand(int)} only when
+ * autoExpand property is true.
+ */
+ protected ByteBuffer autoExpand( int pos, int expectedRemaining )
{
- if (IsAutoExpand)
+ if( isAutoExpand() )
{
- Expand(expectedRemaining);
+ expand( pos, expectedRemaining );
}
+ return this;
}
-
- protected void AutoExpand(int pos, int expectedRemaining)
+
+ private static void checkFieldSize( int fieldSize )
{
- if (IsAutoExpand)
+ if( fieldSize < 0 )
{
- Expand(pos, expectedRemaining);
+ throw new ArgumentOutOfRangeException("fieldSize");
}
- }
+ }
+
+ 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();
}
}
-
diff --git a/dotnet/Qpid.Buffer/ByteBufferAllocator.cs b/dotnet/Qpid.Buffer/ByteBufferAllocator.cs
new file mode 100644
index 0000000000..2dabd0ef50
--- /dev/null
+++ b/dotnet/Qpid.Buffer/ByteBufferAllocator.cs
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Qpid.Buffer;
+
+namespace Qpid.Buffer
+{
+ /**
+ * Allocates {@link ByteBuffer}s and manages them. Please implement this
+ * interface if you need more advanced memory management scheme.
+ */
+ public interface ByteBufferAllocator
+ {
+ /**
+ * Returns the buffer which is capable of the specified size.
+ *
+ * @param capacity the capacity of the buffer
+ * @param direct true to get a direct buffer,
+ * false to get a heap buffer.
+ */
+ ByteBuffer allocate(int capacity, bool direct);
+
+ /**
+ * Wraps the specified NIO {@link FixedByteBuffer} into MINA buffer.
+ */
+ ByteBuffer wrap(FixedByteBuffer nioBuffer);
+
+ /**
+ * Dispose of this allocator.
+ */
+ void dispose();
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs b/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs
index a43331ff1a..459abc56ef 100644
--- a/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs
+++ b/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs
@@ -49,7 +49,7 @@ namespace Qpid.Buffer
public static string GetHexDump(ByteBuffer input)
{
- int size = input.Limit - input.Position;
+ int size = input.limit() - input.position();
if (size == 0)
{
return "empty";
@@ -57,7 +57,7 @@ namespace Qpid.Buffer
StringBuilder output = new StringBuilder(size * 3 - 1);
- byte[] data = input.ToByteArray();
+ byte[] data = input.array();
int byteValue = data[0] & 0xFF;
output.Append((char) highDigits[byteValue]);
output.Append((char) lowDigits[byteValue]);
diff --git a/dotnet/Qpid.Buffer/ByteBufferProxy.cs b/dotnet/Qpid.Buffer/ByteBufferProxy.cs
index 2dd4e73aa6..6fc46ab156 100644
--- a/dotnet/Qpid.Buffer/ByteBufferProxy.cs
+++ b/dotnet/Qpid.Buffer/ByteBufferProxy.cs
@@ -23,7 +23,7 @@ using System.Text;
namespace Qpid.Buffer
{
- public class ByteBufferProxy : ByteBuffer
+ public class ByteBufferProxy //: ByteBuffer
{
protected ByteBuffer _buf;
@@ -37,154 +37,154 @@ namespace Qpid.Buffer
}
- public override void Acquire()
- {
- _buf.Acquire();
- }
-
- public override void Release()
- {
- _buf.Release();
- }
-
- public override int Capacity
- {
- get { return _buf.Capacity; }
- }
-
- public override bool IsAutoExpand
- {
- get { return _buf.IsAutoExpand; }
- set { _buf.IsAutoExpand = value; }
- }
-
- public override void Expand(int expectedRemaining)
- {
- _buf.Expand(expectedRemaining);
- }
-
- public override void Expand(int pos, int expectedRemaining)
- {
- _buf.Expand(pos, expectedRemaining);
- }
-
- public override bool Pooled
- {
- get { return _buf.Pooled; }
- set { _buf.Pooled = value; }
- }
-
- public override int Position
- {
- get { return _buf.Position; }
- set { _buf.Position = value; }
- }
-
- public override int Limit
- {
- get { return _buf.Limit; }
- set { _buf.Limit = value; }
- }
-
- public override void Clear()
- {
- _buf.Clear();
- }
-
- public override void Flip()
- {
- _buf.Flip();
- }
-
- public override void Rewind()
- {
- _buf.Rewind();
- }
-
- public override int Remaining
- {
- get { return _buf.Remaining; }
- }
-
- public override byte Get()
- {
- return _buf.Get();
- }
-
- public override byte Get(int index)
- {
- return _buf.Get(index);
- }
-
- public override void Get(byte[] destination)
- {
- _buf.Get(destination);
- }
-
- public override ushort GetUnsignedShort()
- {
- return _buf.GetUnsignedShort();
- }
-
- public override uint GetUnsignedInt()
- {
- return _buf.GetUnsignedInt();
- }
-
- public override ulong GetUnsignedLong()
- {
- return _buf.GetUnsignedLong();
- }
-
- public override string GetString(uint length, Encoding encoder)
- {
- return _buf.GetString(length, encoder);
- }
-
- public override void Put(byte data)
- {
- _buf.Put(data);
- }
-
- public override void Put(byte[] data, int offset, int size)
- {
- _buf.Put(data, offset, size);
- }
-
- public override void Put(byte[] data)
- {
- _buf.Put(data);
- }
-
- public override void Put(ushort data)
- {
- _buf.Put(data);
- }
-
- public override void Put(uint data)
- {
- _buf.Put(data);
- }
-
- public override void Put(ulong data)
- {
- _buf.Put(data);
- }
-
- public override void Put(ByteBuffer buf)
- {
- _buf.Put(buf);
- }
-
- public override void Compact()
- {
- _buf.Compact();
- }
-
- public override byte[] ToByteArray()
- {
- return _buf.ToByteArray();
- }
+// public /*override*/ void Acquire()
+// {
+// _buf.Acquire();
+// }
+//
+// public /*override*/ void Release()
+// {
+// _buf.Release();
+// }
+//
+// public /*override*/ int Capacity
+// {
+// get { return _buf.Capacity; }
+// }
+//
+// public /*override*/ bool IsAutoExpand
+// {
+// get { return _buf.IsAutoExpand; }
+// set { _buf.IsAutoExpand = value; }
+// }
+//
+// public /*override*/ void Expand(int expectedRemaining)
+// {
+// _buf.Expand(expectedRemaining);
+// }
+//
+// public /*override*/ void Expand(int pos, int expectedRemaining)
+// {
+// _buf.Expand(pos, expectedRemaining);
+// }
+//
+// public /*override*/ bool Pooled
+// {
+// get { return _buf.Pooled; }
+// set { _buf.Pooled = value; }
+// }
+//
+// public /*override*/ int Position
+// {
+// get { return _buf.Position; }
+// set { _buf.Position = value; }
+// }
+//
+// public /*override*/ int Limit
+// {
+// get { return _buf.Limit; }
+// set { _buf.Limit = value; }
+// }
+//
+// public /*override*/ void Clear()
+// {
+// _buf.Clear();
+// }
+//
+// public /*override*/ void Flip()
+// {
+// _buf.Flip();
+// }
+//
+// public /*override*/ void Rewind()
+// {
+// _buf.Rewind();
+// }
+//
+// public /*override*/ int Remaining
+// {
+// get { return _buf.Remaining; }
+// }
+//
+// public /*override*/ byte Get()
+// {
+// return _buf.Get();
+// }
+//
+// public /*override*/ byte Get(int index)
+// {
+// return _buf.Get(index);
+// }
+//
+// public /*override*/ void Get(byte[] destination)
+// {
+// _buf.Get(destination);
+// }
+//
+// public /*override*/ ushort GetUnsignedShort()
+// {
+// return _buf.GetUnsignedShort();
+// }
+//
+// public /*override*/ uint GetUnsignedInt()
+// {
+// return _buf.GetUnsignedInt();
+// }
+//
+// public /*override*/ ulong GetUnsignedLong()
+// {
+// return _buf.GetUnsignedLong();
+// }
+//
+// public /*override*/ string GetString(uint length, Encoding encoder)
+// {
+// return _buf.GetString(length, encoder);
+// }
+//
+// public /*override*/ void Put(byte data)
+// {
+// _buf.Put(data);
+// }
+//
+// public /*override*/ void Put(byte[] data, int offset, int size)
+// {
+// _buf.Put(data, offset, size);
+// }
+//
+// public /*override*/ void Put(byte[] data)
+// {
+// _buf.Put(data);
+// }
+//
+// public /*override*/ void Put(ushort data)
+// {
+// _buf.Put(data);
+// }
+//
+// public /*override*/ void Put(uint data)
+// {
+// _buf.Put(data);
+// }
+//
+// public /*override*/ void Put(ulong data)
+// {
+// _buf.Put(data);
+// }
+//
+// public /*override*/ void Put(ByteBuffer buf)
+// {
+// _buf.Put(buf);
+// }
+//
+// public /*override*/ void Compact()
+// {
+// _buf.Compact();
+// }
+//
+// public /*override*/ byte[] ToByteArray()
+// {
+// return _buf.ToByteArray();
+// }
}
}
diff --git a/dotnet/Qpid.Buffer/FixedByteBuffer.cs b/dotnet/Qpid.Buffer/FixedByteBuffer.cs
new file mode 100644
index 0000000000..39a17a6fa7
--- /dev/null
+++ b/dotnet/Qpid.Buffer/FixedByteBuffer.cs
@@ -0,0 +1,367 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Qpid.Buffer
+{
+ public class FixedByteBuffer
+ {
+ private HeapByteBuffer _buf;
+
+ public FixedByteBuffer(int capacity)
+ {
+ _buf = new HeapByteBuffer(capacity);
+ }
+
+ public FixedByteBuffer(byte[] bytes)
+ {
+ _buf = HeapByteBuffer.wrap(bytes);
+ }
+
+ public static FixedByteBuffer wrap(byte[] array)
+ {
+ return new FixedByteBuffer(array);
+ }
+
+ public static FixedByteBuffer wrap(byte[] array, int offset, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ByteOrder order()
+ {
+ return ByteOrder.LittleEndian;
+ }
+
+ public void order(ByteOrder bo)
+ {
+ // Ignore endianess.
+ }
+
+ public void compact()
+ {
+ _buf.Compact();
+ }
+
+ public char getChar()
+ {
+ throw new NotImplementedException();
+ }
+
+ public char getChar(int index)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void putChar(char value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void putChar(int index, char value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool isDirect()
+ {
+ return false;
+ }
+
+ public bool isReadOnly()
+ {
+ throw new NotImplementedException();
+ }
+
+ public int capacity()
+ {
+ return _buf.Capacity;
+ }
+
+ public int limit()
+ {
+ return _buf.Limit;
+ }
+
+ public int limit(int limit)
+ {
+ int previousLimit = _buf.Limit;
+ _buf.Limit = limit;
+ return previousLimit;
+ }
+
+ public int position()
+ {
+ return _buf.Position;
+ }
+
+ public int position(int newPosition)
+ {
+ int prev = _buf.Position;
+ _buf.Position = newPosition;
+ return prev;
+ }
+
+ public void mark()
+ {
+ throw new NotImplementedException();
+ }
+
+ public static FixedByteBuffer allocateDirect(int capacity)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static FixedByteBuffer allocate(int capacity)
+ {
+ return new FixedByteBuffer(capacity);
+ }
+
+ public void clear()
+ {
+ _buf.Clear();
+ }
+
+ public void put(byte b)
+ {
+ _buf.Put(b);
+ }
+
+ public void put(int index, byte b)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void put(FixedByteBuffer buf)
+ {
+ _buf.Put(buf.array(), buf.position(), buf.limit() - buf.position());
+ }
+
+ public FixedByteBuffer duplicate()
+ {
+ throw new NotImplementedException();
+ }
+
+ public FixedByteBuffer slice()
+ {
+ throw new NotImplementedException();
+ }
+
+ public FixedByteBuffer asReadOnlyBuffer()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///