diff options
author | Robert Greig <rgreig@apache.org> | 2007-02-26 17:46:07 +0000 |
---|---|---|
committer | Robert Greig <rgreig@apache.org> | 2007-02-26 17:46:07 +0000 |
commit | a019367dc582d61fa3739f385592c0baf9b972b8 (patch) | |
tree | 5ce170123120f788d07d472e2febf6b32f17dc29 /qpid/dotnet/Qpid.Buffer | |
parent | 2e9743ac06fc05609155769bf04f4fa442d848c2 (diff) | |
download | qpid-python-a019367dc582d61fa3739f385592c0baf9b972b8.tar.gz |
(Patch submitted by Tomas Restrepo) QPID-ByteBuffer.diff.
Completely refactors the byte buffer implementation, doing away with a complex inheritance hierarchy.
Fixes reading and writing of field table to permit interop with Java client.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@511923 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/dotnet/Qpid.Buffer')
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/BaseByteBuffer.cs | 460 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/BufferDataException.cs | 54 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/ByteBuffer.cs | 3317 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs | 5 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/ByteBufferProxy.cs | 190 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/FixedByteBuffer.cs | 367 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/HeapByteBuffer.cs | 474 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs | 25 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj | 7 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/SimpleByteBuffer.cs | 120 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs | 181 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/SlicedByteBuffer.cs | 86 |
12 files changed, 1205 insertions, 4081 deletions
diff --git a/qpid/dotnet/Qpid.Buffer/BaseByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/BaseByteBuffer.cs deleted file mode 100644 index 3a6beabae8..0000000000 --- a/qpid/dotnet/Qpid.Buffer/BaseByteBuffer.cs +++ /dev/null @@ -1,460 +0,0 @@ -/* - * - * 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.support; -// -//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 org.apache.mina.common.ByteBuffer; -//import org.apache.mina.common.ByteBufferAllocator; - -namespace Qpid.Buffer -{ - /// <summary> - /// A base implementation of <see cref="ByteBuffer"/>. This implementation - /// assumes that <see cref="ByteBuffer.Buf"/> always returns a correct NIO - /// <see cref="FixedByteBuffer"/> instance. Most implementations could - /// extend this class and implement their own buffer management mechanism. - /// </summary> - /// <seealso cref="ByteBufferAllocator"/> - public abstract class BaseByteBuffer : ByteBuffer - { - private bool _autoExpand; - - /// <summary> - /// We don't have any access to Buffer.markValue(), - /// so we need to track it down, which will cause small extra overhead. - /// </summary> - private int _mark = -1; - - protected BaseByteBuffer() - { - } - - public override bool isDirect() - { - return buf().isDirect(); - } - - public override bool isReadOnly() - { - return buf().isReadOnly(); - } - - public override int capacity() - { - return buf().capacity(); - } - - public override ByteBuffer capacity(int newCapacity) - { - if( newCapacity > capacity() ) - { - // Allocate a new buffer and transfer all settings to it. - int pos = position(); - int lim = limit(); - ByteOrder bo = order(); - - capacity0( newCapacity ); - buf().limit( lim ); - if( _mark >= 0 ) - { - buf().position( _mark ); - buf().mark(); - } - buf().position( pos ); - buf().order( bo ); - } - - return this; - } - - - /// <summary> - /// Implement this method to increase the capacity of this buffer. - /// </summary> - /// <param name="newCapacity">is always greater than the current capacity.</param> - protected abstract void capacity0( int newCapacity ); - - public override bool isAutoExpand() - { - return _autoExpand; - } - - public override ByteBuffer setAutoExpand(bool autoExpand) - { - _autoExpand = autoExpand; - return this; - } - - public override ByteBuffer expand(int pos, int expectedRemaining) - { - int end = pos + expectedRemaining; - if( end > capacity() ) - { - // The buffer needs expansion. - capacity( end ); - } - - if( end > limit() ) - { - // We call limit() directly to prevent StackOverflowError - buf().limit( end ); - } - return this; - } - - public override int position() - { - return buf().position(); - } - - public override ByteBuffer position(int newPosition) - { - autoExpand( newPosition, 0 ); - buf().position( newPosition ); - if( _mark > newPosition ) - { - _mark = -1; - } - return this; - } - - public override int limit() - { - return buf().limit(); - } - - public override ByteBuffer limit(int newLimit) - { - autoExpand( newLimit, 0 ); - buf().limit( newLimit ); - if( _mark > newLimit ) - { - _mark = -1; - } - return this; - } - - public override ByteBuffer mark() - { - buf().mark(); - _mark = position(); - return this; - } - - public override int markValue() - { - return _mark; - } - - public override ByteBuffer reset() - { - buf().reset(); - return this; - } - - public override ByteBuffer clear() - { - buf().clear(); - _mark = -1; - return this; - } - - public override ByteBuffer flip() - { - buf().flip(); - _mark = -1; - return this; - } - - public override ByteBuffer rewind() - { - buf().rewind(); - _mark = -1; - return this; - } - - public override byte get() - { - return buf().get(); - } - - public override ByteBuffer put(byte b) - { - autoExpand( 1 ); - buf().put( b ); - return this; - } - - public override byte get(int index) - { - return buf().get( index ); - } - - public override ByteBuffer put(int index, byte b) - { - autoExpand( index, 1 ); - buf().put( index, b ); - return this; - } - - public override ByteBuffer get(byte[] dst, int offset, int length) - { - buf().get( dst, offset, length ); - return this; - } - - public override ByteBuffer get(byte[] dst) - { - buf().get(dst); - return this; - } - - public override ByteBuffer put(FixedByteBuffer src) - { - autoExpand( src.remaining() ); - buf().put( src ); - return this; - } - - public override ByteBuffer put(byte[] src, int offset, int length) - { - autoExpand( length ); - buf().put( src, offset, length ); - return this; - } - - public override ByteBuffer compact() - { - buf().compact(); - _mark = -1; - return this; - } - - public override ByteOrder order() - { - return buf().order(); - } - - public override ByteBuffer order(ByteOrder bo) - { - buf().order( bo ); - return this; - } - - public override char getChar() - { - return buf().getChar(); - } - - public override ByteBuffer putChar(char value) - { - autoExpand( 2 ); - buf().putChar( value ); - return this; - } - - public override char getChar(int index) - { - return buf().getChar( index ); - } - - public override ByteBuffer putChar(int index, char value) - { - autoExpand( index, 2 ); - buf().putChar( index, value ); - return this; - } - -// public CharBuffer asCharBuffer() -// { -// return buf().asCharBuffer(); -// } - - public override short getShort() - { - return buf().getShort(); - } - - public override ByteBuffer putShort(short value) - { - autoExpand( 2 ); - buf().putShort( value ); - return this; - } - - public override short getShort(int index) - { - return buf().getShort( index ); - } - - public override ByteBuffer putShort(int index, short value) - { - autoExpand( index, 2 ); - buf().putShort( index, value ); - return this; - } - - public override ushort GetUnsignedShort() - { - return buf().getUnsignedShort(); - } - - -// public ShortBuffer asShortBuffer() -// { -// return buf().asShortBuffer(); -// } - - public override int getInt() - { - return buf().getInt(); - } - - public override uint GetUnsignedInt() - { - return buf().getUnsignedInt(); - } - - public override ByteBuffer putInt(int value) - { - autoExpand( 4 ); - buf().putInt( value ); - return this; - } - - public override int getInt(int index) - { - return buf().getInt( index ); - } - - public override ByteBuffer putInt(int index, int value) - { - autoExpand( index, 4 ); - buf().putInt( index, value ); - return this; - } - -// public IntBuffer asIntBuffer() -// { -// return buf().asIntBuffer(); -// } - - public override long getLong() - { - return buf().getLong(); - } - - public override ByteBuffer putLong(long value) - { - autoExpand( 8 ); - buf().putLong( value ); - return this; - } - - public override long getLong(int index) - { - return buf().getLong( index ); - } - - public override ByteBuffer putLong(int index, long value) - { - autoExpand( index, 8 ); - buf().putLong( index, value ); - return this; - } - -// public LongBuffer asLongBuffer() -// { -// return buf().asLongBuffer(); -// } - - public override float getFloat() - { - return buf().getFloat(); - } - - public override ByteBuffer putFloat(float value) - { - autoExpand( 4 ); - buf().putFloat( value ); - return this; - } - - public override float getFloat(int index) - { - return buf().getFloat( index ); - } - - public override ByteBuffer putFloat(int index, float value) - { - autoExpand( index, 4 ); - buf().putFloat( index, value ); - return this; - } - -// public FloatBuffer asFloatBuffer() -// { -// return buf().asFloatBuffer(); -// } - - public override double getDouble() - { - return buf().getDouble(); - } - - public override ByteBuffer putDouble(double value) - { - autoExpand( 8 ); - buf().putDouble( value ); - return this; - } - - public override double getDouble(int index) - { - return buf().getDouble( index ); - } - - public override ByteBuffer putDouble(int index, double value) - { - autoExpand( index, 8 ); - buf().putDouble( index, value ); - return this; - } - - public override ByteBuffer put(byte[] src) - { - buf().put(src); - return this; - } - -// public DoubleBuffer asDoubleBuffer() -// { -// return buf().asDoubleBuffer(); -// } - } -} diff --git a/qpid/dotnet/Qpid.Buffer/BufferDataException.cs b/qpid/dotnet/Qpid.Buffer/BufferDataException.cs deleted file mode 100644 index c76441dde0..0000000000 --- a/qpid/dotnet/Qpid.Buffer/BufferDataException.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * 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; -using System.Runtime.Serialization; - -namespace Qpid.Buffer -{ - /// <summary> - /// An exception thrown when the data the <see cref="ByteBuffer"/> - /// contains is corrupt - /// </summary> - [Serializable] - public class BufferDataException : Exception - { - public BufferDataException() - { - } - - public BufferDataException( String message ) : base(message) - { - } - - public BufferDataException( String message, Exception cause ) : base(message, cause) - { - } - - public BufferDataException( Exception cause ) : base("", cause) - { - } - - protected BufferDataException(SerializationInfo info, StreamingContext ctxt) - : base(info, ctxt) - { - } - } -} diff --git a/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs index 1a4f0072d6..1bfc749746 100644 --- a/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs +++ b/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs @@ -19,2367 +19,964 @@ * */ using System; -using System.Text; namespace Qpid.Buffer { - 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 - { - //private static ByteBufferAllocator allocator = new PooledByteBufferAllocator(); - private static IByteBufferAllocator allocator = new SimpleByteBufferAllocator(); - - private static bool _useDirectBuffers = false; - - public string HexDump - { - get - { - return ByteBufferHexDumper.GetHexDump(this); - } - } - - /** - * Returns the current allocator which manages the allocated buffers. - */ - public static IByteBufferAllocator getAllocator() - { - return allocator; - } - - /** - * Changes the current allocator with the specified one to manage - * the allocated buffers from now. - */ - public static void setAllocator( IByteBufferAllocator newAllocator ) - { - if( newAllocator == null ) - { - throw new NullReferenceException("allocator cannot be null"); - } - - IByteBufferAllocator oldAllocator = allocator; - - allocator = newAllocator; - - if( null != oldAllocator ) - { - oldAllocator.Dispose(); - } - } - - public static bool isUseDirectBuffers() - { - return _useDirectBuffers; - } - - public static void setUseDirectBuffers( bool useDirectBuffers ) - { - _useDirectBuffers = useDirectBuffers; - } - - /** - * 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 ) - { - if( _useDirectBuffers ) - { - try - { - // first try to allocate direct buffer - return allocate( capacity, true ); - } - catch (OutOfMemoryException) - { - // fall through to heap buffer - } - } - - return allocate( capacity, false ); - } - - /** - * 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 ) - { - return allocator.Allocate( capacity, direct ); - } - - /** - * Wraps the specified NIO {@link FixedByteBuffer} into MINA buffer. - */ - public static ByteBuffer wrap( FixedByteBuffer nioBuffer ) - { - return allocator.Wrap( nioBuffer ); - } - - /** - * Wraps the specified byte array into MINA heap buffer. - */ - public static ByteBuffer wrap( byte[] byteArray ) - { - return wrap( FixedByteBuffer.wrap( byteArray ) ); - } - - /** - * 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 ) - { - return wrap( FixedByteBuffer.wrap( byteArray, offset, length ) ); - } - - protected ByteBuffer() - { - } - - /** - * 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(); - - /** - * Releases the specified buffer to buffer pool. - * - * @throws IllegalStateException if you attempt to release already - * released buffer. - */ - public abstract void release(); - - /** - * Returns the underlying NIO buffer instance. - */ - public abstract FixedByteBuffer buf(); - - /** - * @see FixedByteBuffer#isDirect() - */ - public abstract bool isDirect(); - - /** - * @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 ); - - /** - * 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 expand( position(), expectedRemaining ); - } - - /** - * 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 ); - - /** - * @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(); - - /** - * 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(); - 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 int hashCode() - { - int h = 1; - int p = position(); - for( int i = limit() - 1; i >= p; i -- ) - { - h = 31 * h + get( i ); - } - return h; - } - - public bool equals( Object o ) - { - if( !( o is ByteBuffer ) ) - { - return false; - } - - ByteBuffer that = (ByteBuffer)o; - if( this.remaining() != that.remaining() ) - { - return false; - } - - int p = this.position(); - for( int i = this.limit() - 1, j = that.limit() - 1; i >= p; i --, j -- ) - { - byte v1 = this.get( i ); - byte v2 = that.get( j ); - if( v1 != v2 ) - { - return false; - } - } - return true; - } - - 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 ) - { - continue; - } - if( v1 < v2 ) - { - return -1; - } - - return +1; - } - return this.remaining() - that.remaining(); - } - - /** - * @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 ) - { - if( remaining() < prefixLength ) - { - return false; - } - - int dataLength; - switch( prefixLength ) - { - case 1: - dataLength = getUnsigned( position() ); - break; - case 2: - dataLength = getUnsignedShort( position() ); - break; - case 4: - dataLength = getInt( position() ); - break; - default: - throw new 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; - } - - 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(); - } + /// <summary> + /// Abstract class implementing a byte buffer + /// </summary> + public abstract class ByteBuffer + { + private int _position; + private int _limit; + private bool _isAutoExpand; + private static IByteBufferAllocator _allocator = + new SimpleByteBufferAllocator(); + + #region Properties + // + // Properties + // + + /// <summary> + /// The maximum number of bytes the buffer can hold + /// </summary> + public abstract int Capacity + { + get; + } + + /// <summary> + /// Return the backing array of this buffer + /// </summary> + public abstract byte[] Array + { + get; + } + + /// <summary> + /// The current position inside this buffer + /// </summary> + public int Position + { + get { return _position; } + set { Seek(value); } + } + + /// <summary> + /// Index of the first element that should not be read or written. + /// A buffer's limit is never negative and is never greater than the its capacity. + /// </summary> + public int Limit + { + get { return _limit; } + set { SetLimit(value); } + } + + /// <summary> + /// Number of bytes remaining in the buffer from the current position + /// </summary> + public int Remaining + { + get { return Limit - Position; } + } + + /// <summary> + /// True if there are bytes remaining in the buffer + /// </summary> + public bool HasRemaining + { + get { return Remaining > 0; } + } + + /// <summary> + /// If true, the buffer will be resized as necessary + /// to allow space for writing. By default is false. + /// </summary> + public bool IsAutoExpand + { + get { return _isAutoExpand; } + set { _isAutoExpand = value; } + } + + #endregion // Properties + + #region Buffer Manipulation + // + // Buffer Manipulation + // + + /// <summary> + /// Move the buffer to Position 0 + /// </summary> + /// <returns>This instance</returns> + public ByteBuffer Rewind() + { + Seek(0); + return this; + } + + /// <summary> + /// Prepare the buffer to read back what's been written + /// </summary> + /// <returns>This instance</returns> + public ByteBuffer Flip() + { + Limit = Position; + Position = 0; + return this; + } + + /// <summary> + /// Compact this buffer. + /// </summary> + /// <returns>This instance</returns> + /// <remarks> + /// The bytes between the buffer's current position and its limit, if any, + /// are copied to the beginning of the buffer. + /// </remarks> + public ByteBuffer Compact() + { + DoCompact(); + return this; + } + + /// <summary> + /// Clears this buffer. The position is set to zero, the limit is set to the capacity + /// </summary> + /// <returns>This instance</returns> + public ByteBuffer Clear() + { + Limit = Capacity; + Position = 0; + return this; + } + + /// <summary> + /// Expands this buffer's capacity so that + /// Remaining == expectedRemaining + /// </summary> + /// <param name="expectedRemaining">Number of bytes that should be accessable after resizing</param> + /// <returns>This instance</returns> + public ByteBuffer Expand(int expectedRemaining) + { + return Expand(Position, expectedRemaining); + } + + /// <summary> + /// Expands this buffer's capacity so that + /// Remaining == expectedRemaining + /// </summary> + /// <param name="position">Position from which to start the resize</param> + /// <param name="expectedRemaining">Number of bytes that should be accessable after resizing</param> + /// <returns>This instance</returns> + public ByteBuffer Expand(int position, int expectedRemaining) + { + if ( expectedRemaining <= 0 ) + throw new ArgumentException("expectedRemaining must be greater than 0"); + + int end = position + expectedRemaining; + if ( end > Capacity ) + { + DoResize(end); + } + if ( end > Limit ) + Limit = end; + return this; + } + + /// <summary> + /// Creates a new byte buffer whose content is a shared + /// subsequence of this buffer's content. + /// </summary> + /// <remarks> + /// The content of the new buffer will start at this buffer's current position. + /// Changes to this buffer's content will be visible in the new buffer, + /// and vice versa; the two buffers' position and limit values will be independent. + /// <para> + /// The new buffer's position will be zero, its capacity and its limit will + /// be the number of bytes remaining in this buffer. + /// </para> + /// </remarks> + /// <returns>A view on top of this instance</returns> + public ByteBuffer Slice() + { + return new SlicedByteBuffer(this); + } + + /// <summary> + /// Skip the specified number of bytes + /// </summary> + /// <param name="numBytes">Number of bytes to move forward by</param> + /// <returns>This instance</returns> + public ByteBuffer Skip(int numBytes) + { + Position += numBytes; + return this; + } + + /// <summary> + /// Acquire this buffer to keep it alive. + /// </summary> + public virtual void Acquire() + { + // override in subclass if supported + } + + /// <summary> + /// Release this buffer instance + /// </summary> + public virtual void Release() + { + // override in subclass if supported + } + + /// <summary> + /// Return a string with a Hex Dump of this buffer's contents + /// </summary> + /// <returns>The hex dump</returns> + public string GetHexDump() + { + return ByteBufferHexDumper.GetHexDump(this); + } + + public override string ToString() + { + return GetHexDump(); + } + #endregion // Buffer Manipulation + + #region Static Operations + // + // Static Operations + // + /// <summary> + /// Replaces the default allocator with your own implementation + /// </summary> + /// <param name="allocator">New allocator</param> + public static void SetAllocator(IByteBufferAllocator allocator) + { + if ( allocator == null ) + throw new ArgumentNullException("allocator"); + _allocator = allocator; + } + + /// <summary> + /// Allocate a new buffer with the specified capacity + /// using the default allocator + /// </summary> + /// <param name="capacity">Desired capacity</param> + /// <returns>The new buffer</returns> + public static ByteBuffer Allocate(int capacity) + { + return _allocator.Allocate(capacity); + } + + /// <summary> + /// Wraps the specified arrat into a new buffer + /// </summary> + /// <param name="buffer"></param> + /// <returns></returns> + public static ByteBuffer Wrap(byte[] buffer) + { + return _allocator.Wrap(buffer); + } + #endregion // Static Operations + + #region Data Accessors + // + // Data Accessors + // + + // Byte Stuff + + /// <summary> + /// Read the next byte in the buffer + /// </summary> + /// <returns>The next byte available</returns> + public byte GetByte() + { + byte value = GetByte(Position); + Position += 1; + return value; + } + /// <summary> + /// Read the byte at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public byte GetByte(int position) + { + CheckSpaceForReading(position, 1); + return ReadByte(position); + } + /// <summary> + /// Write a byte at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(byte value) + { + Put(Position, value); + Position++; + return this; + } + /// <summary> + /// Write a byte at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, byte value) + { + CheckSpaceForWriting(position, 1); + Write(position, value); + return this; + } + + // SByte Stuff + + /// <summary> + /// Read the next signed byte in the buffer + /// </summary> + /// <returns>The next signed byte available</returns> + public sbyte GetSByte() + { + sbyte value = GetSByte(Position); + Position += 1; + return value; + } + /// <summary> + /// Read the signed byte at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public sbyte GetSByte(int position) + { + CheckSpaceForReading(position, 1); + return (sbyte)ReadByte(position); + } + + /// <summary> + /// Write a signed byte at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(sbyte value) + { + Put(Position, value); + Position += 1; + return this; + } + + /// <summary> + /// Write a signed byte at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, sbyte value) + { + CheckSpaceForWriting(position, 1); + Write(position, (byte)value); + return this; + } + + // UInt16 Stuff + + /// <summary> + /// Read the next uint16 in the buffer + /// </summary> + /// <returns>The next uint16 available</returns> + public ushort GetUInt16() + { + ushort value = GetUInt16(Position); + Position += 2; + return value; + } + /// <summary> + /// Read the uint16 at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public ushort GetUInt16(int position) + { + CheckSpaceForReading(position, 2); + byte upper = ReadByte(position); + byte lower = ReadByte(position+1); + return (ushort)(((ushort)upper << 8) + lower); + } + + /// <summary> + /// Write a uint16 at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(ushort value) + { + Put(Position, value); + Position += 2; + return this; + } + + /// <summary> + /// Write a uint16 at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, ushort value) + { + CheckSpaceForWriting(position, 2); + Write(position, (byte)(value >> 8)); + Write(position+1, (byte)(value)); + return this; + } + + // Int16 Stuff + + /// <summary> + /// Read the next int16 in the buffer + /// </summary> + /// <returns>The next int16 available</returns> + public short GetInt16() + { + return (short) GetUInt16(); + } + /// <summary> + /// Read the int16 at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public short GetInt16(int position) + { + return (short)GetUInt16(position); + } + + /// <summary> + /// Write a int16 at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(short value) + { + return Put((ushort) value); + } + + /// <summary> + /// Write a int16 at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, short value) + { + return Put(position, (ushort)value); + } + + + // UInt32 Stuff + + /// <summary> + /// Read the next uint32 in the buffer + /// </summary> + /// <returns>The next uint32 available</returns> + public uint GetUInt32() + { + uint value = GetUInt32(Position); + Position += 4; + return value; + } + /// <summary> + /// Read the uint32 at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public uint GetUInt32(int position) + { + CheckSpaceForReading(position, 4); + byte b1 = ReadByte(position); + byte b2 = ReadByte(position + 1); + byte b3 = ReadByte(position + 2); + byte b4 = ReadByte(position + 3); + return (uint)((b1 << 24) + (b2 << 16) + (b3 << 8) + b4); + } + + /// <summary> + /// Write a uint32 at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(uint value) + { + Put(Position, value); + Position += 4; + return this; + } + + /// <summary> + /// Write a uint32 at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, uint value) + { + CheckSpaceForWriting(position, 4); + Write(position, (byte)(value >> 24)); + Write(position + 1, (byte)(value >> 16)); + Write(position + 2, (byte)(value >> 8)); + Write(position + 3, (byte)(value)); + return this; + } + + // Int32 Stuff + + /// <summary> + /// Read the next int32 in the buffer + /// </summary> + /// <returns>The next int32 available</returns> + public int GetInt32() + { + return (int)GetUInt32(); + } + /// <summary> + /// Read the int32 at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public int GetInt32(int position) + { + return (int)GetUInt32(position); + } + + /// <summary> + /// Write a int32 at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int value) + { + return Put((uint)value); + } + + /// <summary> + /// Write a int32 at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, int value) + { + return Put(position, (uint)value); + } + + // UInt64 Stuff + + /// <summary> + /// Read the next uint64 in the buffer + /// </summary> + /// <returns>The next uint64 available</returns> + public ulong GetUInt64() + { + ulong value = GetUInt64(Position); + Position += 8; + return value; + } + /// <summary> + /// Read the uint64 at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public ulong GetUInt64(int position) + { + CheckSpaceForReading(position, 8); + byte b1 = ReadByte(position); + byte b2 = ReadByte(position + 1); + byte b3 = ReadByte(position + 2); + byte b4 = ReadByte(position + 3); + byte b5 = ReadByte(position + 4); + byte b6 = ReadByte(position + 5); + byte b7 = ReadByte(position + 6); + byte b8 = ReadByte(position + 7); + // all the casts necessary because otherwise each subexpression + // only gets promoted to uint and cause incorrect results + return (((ulong)b1 << 56) + ((ulong)b2 << 48) + ((ulong)b3 << 40) + + ((ulong)b4 << 32) + ((ulong)b5 << 24) + + ((ulong)b6 << 16) + ((ulong)b7 << 8) + b8); + } + + /// <summary> + /// Write a uint64 at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(ulong value) + { + Put(Position, value); + Position += 8; + return this; + } + + /// <summary> + /// Write a uint64 at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, ulong value) + { + CheckSpaceForWriting(position, 8); + Write(position, (byte)(value >> 56)); + Write(position + 1, (byte)(value >> 48)); + Write(position + 2, (byte)(value >> 40)); + Write(position + 3, (byte)(value >> 32)); + Write(position + 4, (byte)(value >> 24)); + Write(position + 5, (byte)(value >> 16)); + Write(position + 6, (byte)(value >> 8)); + Write(position + 7, (byte)(value)); + return this; + } + + // Int64 Stuff + + /// <summary> + /// Read the next int64 in the buffer + /// </summary> + /// <returns>The next int64 available</returns> + public long GetInt64() + { + return (long)GetUInt64(); + } + /// <summary> + /// Read the int64 at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public long GetInt64(int position) + { + return (long)GetUInt64(position); + } + + /// <summary> + /// Write a int64 at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(long value) + { + return Put((ulong)value); + } + + /// <summary> + /// Write a int64 at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, long value) + { + return Put(position, (ulong)value); + } + + + // Float Stuff + + /// <summary> + /// Read the next float in the buffer + /// </summary> + /// <returns>The next float available</returns> + public float GetFloat() + { + unsafe + { + uint val = GetUInt32(); + return *((float*)&val); + } + } + /// <summary> + /// Read the float at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public float GetFloat(int position) + { + unsafe + { + uint val = GetUInt32(position); + return *((float*)&val); + } + } + + /// <summary> + /// Write a float at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(float value) + { + unsafe + { + uint val = *((uint*)&value); + return Put(val); + } + } + + /// <summary> + /// Write a float at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, float value) + { + unsafe + { + uint val = *((uint*)&value); + return Put(position, val); + } + } + + // Double Stuff + + /// <summary> + /// Read the next double in the buffer + /// </summary> + /// <returns>The next double available</returns> + public double GetDouble() + { + unsafe + { + ulong val = GetUInt64(); + return *((double*)&val); + } + } + /// <summary> + /// Read the double at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public double GetDouble(int position) + { + unsafe + { + ulong val = GetUInt64(position); + return *((double*)&val); + } + } + + /// <summary> + /// Write a double at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(double value) + { + unsafe + { + ulong val = *((ulong*)&value); + return Put(val); + } + } + + /// <summary> + /// Write a double at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, double value) + { + unsafe + { + ulong val = *((ulong*)&value); + return Put(position, val); + } + } + + // Char Stuff + + /// <summary> + /// Read the next char in the buffer + /// </summary> + /// <returns>The next char available</returns> + public char GetChar() + { + return (char)GetUInt16(); + } + /// <summary> + /// Read the char at the specified position + /// </summary> + /// <param name="position">Position to read from</param> + /// <returns>The value at the position</returns> + public char getChar(int position) + { + return (char)GetUInt16(position); + } + + /// <summary> + /// Write a char at the current position + /// </summary> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(char value) + { + return Put((ushort) value); + } + + /// <summary> + /// Write a char at the specified position + /// </summary> + /// <param name="position">Position to write to</param> + /// <param name="value">Value to write</param> + /// <returns>This instance</returns> + public ByteBuffer Put(int position, char value) + { + return Put(position, (ushort)value); + } + + // Byte[] stuff + + public void GetBytes(byte[] buffer) + { + GetBytes(buffer, 0, buffer.Length); + } + + public void GetBytes(byte[] buffer, int offset, int length) + { + GetBytes(Position, buffer, offset, length); + Position += length; + } + public void GetBytes(int position, byte[] buffer, int offset, int length) + { + CheckSpaceForReading(position, length); + if ( offset + length > buffer.Length ) + throw new ArgumentException("Invalid offset + length"); + ReadBytes(position, buffer, offset, length); + } + + public ByteBuffer Put(byte[] buffer) + { + return Put(buffer, 0, buffer.Length); + } + + public ByteBuffer Put(byte[] buffer, int offset, int length) + { + Put(Position, buffer, offset, length); + Position += length; + return this; + } + + public ByteBuffer Put(int position, byte[] buffer, int offset, int length) + { + CheckSpaceForWriting(position, length); + if ( offset + length > buffer.Length ) + throw new ArgumentException("Invalid offset + length"); + + Write(position, buffer, offset, length); + return this; + } + + public ByteBuffer Put(ByteBuffer data) + { + Put(Position, data); + Position += data.Remaining; + return this; + } + + public ByteBuffer Put(int position, ByteBuffer data) + { + CheckSpaceForWriting(position, data.Remaining); + Write(position, data.Array, data.Position, data.Remaining); + return this; + } + + #endregion // Data Accessors + + #region Core Overrides + // + // Core Overrides + // + + protected abstract void DoWrite(int position, byte value); + protected abstract void DoWrite(int position, byte[] src, int offset, int length); + protected abstract byte DoReadByte(int position); + protected abstract void DoReadBytes(int position, byte[] dest, int offset, int length); + protected abstract void DoCompact(); + protected abstract void DoResize(int newSize); + + #endregion // Core Overrides + + #region Private Methods + // + // Private Methods + // + + private void Seek(int offset) + { + if ( offset > Capacity ) + throw new ArgumentException("Cannot position beyond end of buffer"); + _position = offset; + AdjustLimit(); + } + + private void SetLimit(int newLimit) + { + if ( newLimit < 0 ) + throw new ArgumentOutOfRangeException("The new limit must be a positive value"); + if ( newLimit > Capacity ) + throw new ArgumentOutOfRangeException("The new limit must not be greater than the capacity"); + _limit = newLimit; + if ( _position > newLimit ) + _position = newLimit; + } + + private void AdjustLimit() + { + if ( _limit < _position ) + _limit = _position; + } + + private void CheckSpaceForReading(int position, int length) + { + if ( position + length > Limit ) + { + throw new BufferUnderflowException("Attempt to read " + length + " byte(s) to buffer where position is " + _position + + " and limit is " + Limit); + } + } + + private void CheckSpaceForWriting(int position, int length) + { + if ( IsAutoExpand ) + { + Expand(position, length); + } + if ( position + length > Limit ) + { + throw new BufferOverflowException("Attempt to write " + length + " byte(s) to buffer where position is " + _position + + " and limit is " + Limit); + } + } + + private void Write(int position, byte value) + { + DoWrite(position, value); + } + private void Write(int position, byte[] src, int offset, int length) + { + DoWrite(position, src, offset, length); + } + private byte ReadByte(int position) + { + return DoReadByte(position); + } + private void ReadBytes(int position, byte[] dest, int offset, int length) + { + DoReadBytes(position, dest, offset, length); + } + + #endregion // Private Methods + + } // class ByteBuffer } diff --git a/qpid/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs b/qpid/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs index 459abc56ef..bf7c738041 100644 --- a/qpid/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs +++ b/qpid/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.Remaining; if (size == 0) { return "empty"; @@ -57,7 +57,7 @@ namespace Qpid.Buffer StringBuilder output = new StringBuilder(size * 3 - 1); - byte[] data = input.array(); + byte[] data = input.Array; int byteValue = data[0] & 0xFF; output.Append((char) highDigits[byteValue]); output.Append((char) lowDigits[byteValue]); @@ -75,3 +75,4 @@ namespace Qpid.Buffer } } + diff --git a/qpid/dotnet/Qpid.Buffer/ByteBufferProxy.cs b/qpid/dotnet/Qpid.Buffer/ByteBufferProxy.cs deleted file mode 100644 index 6fc46ab156..0000000000 --- a/qpid/dotnet/Qpid.Buffer/ByteBufferProxy.cs +++ /dev/null @@ -1,190 +0,0 @@ -/* - * - * 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; -using System.Text; - -namespace Qpid.Buffer -{ - public class ByteBufferProxy //: ByteBuffer - { - protected ByteBuffer _buf; - - protected ByteBufferProxy(ByteBuffer buf) - { - if (buf == null) - { - throw new ArgumentNullException("buf"); - } - _buf = buf; - } - - -// 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/qpid/dotnet/Qpid.Buffer/FixedByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/FixedByteBuffer.cs deleted file mode 100644 index d2f3ca8a3c..0000000000 --- a/qpid/dotnet/Qpid.Buffer/FixedByteBuffer.cs +++ /dev/null @@ -1,367 +0,0 @@ -/* - * - * 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(); - } - - /// <summary> - /// Returns backing array. - /// </summary> - /// <returns></returns> - public byte[] array() - { - return _buf.array(); - } - - public int arrayOffset() - { - throw new NotImplementedException(); - } - - public void reset() - { - throw new NotImplementedException(); - } - - public void flip() - { - _buf.Flip(); - } - - public void rewind() - { - _buf.Rewind(); - } - - public byte get() - { - return _buf.Get(); - } - - public byte get(int index) - { - throw new NotImplementedException(); - } - - public short getShort() - { - return _buf.GetShort(); - } - - public short getShort(int index) - { - throw new NotImplementedException(); - } - - public void putShort(short value) - { - _buf.Put(value); - } - - public void putShort(int index, short value) - { - throw new NotImplementedException(); - } - - public int getInt() - { - return _buf.GetInt(); - } - - public int getInt(int index) - { - throw new NotImplementedException(); - } - - public void putInt(int value) - { - _buf.Put(value); - } - - public void putInt(int index, int value) - { - throw new NotImplementedException(); - } - - public ByteBuffer get(byte[] dst, int offset, int length) - { - throw new NotImplementedException(); - } - - public ByteBuffer put(byte[] src, int offset, int length) - { - throw new NotImplementedException(); - } - - public long getLong() - { - return _buf.GetLong(); - } - - public long getLong(int index) - { - throw new NotImplementedException(); - } - - public void putLong(long value) - { - _buf.Put(value); - } - - public void putLong(int index, long value) - { - throw new NotImplementedException(); - } - - public int remaining() - { - return _buf.Remaining; - } - - public float getFloat() - { - return _buf.GetFloat(); - } - - public float getFloat(int index) - { - throw new NotImplementedException(); - } - - public void putFloat(float value) - { - _buf.Put(value); - } - - public void putFloat(int index, float value) - { - throw new NotImplementedException(); - } - - public double getDouble() - { - return _buf.GetDouble(); - } - - public double getDouble(int index) - { - throw new NotImplementedException(); - } - - public void putDouble(double value) - { - _buf.Put(value); - } - - public void putDouble(int index, double value) - { - throw new NotImplementedException(); - } - - public ushort getUnsignedShort() - { - return _buf.GetUnsignedShort(); - } - - public uint getUnsignedInt() - { - return _buf.GetUnsignedInt(); - } - - public void get(byte[] dst) - { - _buf.Get(dst); - } - - public void put(ushort value) - { - _buf.Put(value); - } - - public void put(uint max) - { - _buf.Put(max); - } - - public void put(ulong tag) - { - _buf.Put(tag); - } - - public void put(byte[] src) - { - _buf.Put(src); - } - - public ulong getUnsignedLong() - { - return _buf.GetUnsignedLong(); - } - } -} diff --git a/qpid/dotnet/Qpid.Buffer/HeapByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/HeapByteBuffer.cs deleted file mode 100644 index f95fe1c241..0000000000 --- a/qpid/dotnet/Qpid.Buffer/HeapByteBuffer.cs +++ /dev/null @@ -1,474 +0,0 @@ -/* - * - * 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; -using System.Text; - -namespace Qpid.Buffer -{ - public class HeapByteBuffer //: ByteBuffer - { - private byte[] _underlyingData; - - /// <summary> - /// The position of the next value to be read or written - /// </summary> - private int _position; - - /// <summary> - /// The index of the first element that should not be read or written - /// </summary> - private int _limit; - - public HeapByteBuffer(int size) : this(new byte[size], 0) - { - } - - private HeapByteBuffer(byte[] bytes, int length) - { - _underlyingData = bytes; - _limit = bytes.Length; - _position = length; - } - - public /*override*/ int Capacity - { - get - { - return _underlyingData.Length; - } - } - - public /*override*/ int Position - { - get - { - return _position; - } - set - { - _position = value; - } - } - - /// <summary> - /// Sets this buffer's limit. If the position is larger than the new limit then it is set to the new limit. - /// </summary> - /// <value>The new limit value; must be non-negative and no larger than this buffer's capacity</value> - public /*override*/ int Limit - { - get - { - return _limit; - } - set - { - if (value < 0) - { - throw new ArgumentException("Limit must not be negative"); - } - if (value > Capacity) - { - throw new ArgumentException("Limit must not be greater than Capacity"); - } - _limit = value; - if (_position > value) - { - _position = value; - } - } - } - - /// <summary> - /// Returns the number of elements between the current position and the limit - /// </summary> - /// <value>The number of elements remaining in this buffer</value> - public /*override*/ int Remaining - { - get - { - return (_limit - _position); - } - } - - public /*override*/ void Clear() - { - _position = 0; - _limit = Capacity; - } - - public /*override*/ void Flip() - { - _limit = _position; - _position = 0; - } - - public /*override*/ void Rewind() - { - _position = 0; - } - - public byte[] array() - { - return _underlyingData; - } - - public /*override*/ byte[] ToByteArray() - { - // Return copy of bytes remaining. - byte[] result = new byte[Remaining]; - Array.Copy(_underlyingData, _position, result, 0, Remaining); - return result; - } - - private void CheckSpace(int size) - { - if (_position + size > _limit) - { - throw new BufferOverflowException("Attempt to write " + size + " byte(s) to buffer where position is " + _position + - " and limit is " + _limit); - } - } - - private void CheckSpaceForReading(int size) - { - if (_position + size > _limit) - { - throw new BufferUnderflowException("Attempt to read " + size + " byte(s) to buffer where position is " + _position + - " and limit is " + _limit); - } - } - - /// <summary> - /// Writes the given byte into this buffer at the current position, and then increments the position. - /// </summary> - /// <param name="data">The byte to be written</param> - /// <exception cref="BufferOverflowException">If this buffer's current position is not smaller than its limit</exception> - public /*override*/ void Put(byte data) - { - CheckSpace(1); - _underlyingData[_position++] = data; - } - - /// <summary> - /// Writes all the data in the given byte array into this buffer at the current - /// position and then increments the position. - /// </summary> - /// <param name="data">The data to copy.</param> - /// <exception cref="BufferOverflowException">If this buffer's current position plus the array length is not smaller than its limit</exception> - public /*override*/ void Put(byte[] data) - { - Put(data, 0, data.Length); - } - - public /*override*/ void Put(byte[] data, int offset, int size) - { - if (data == null) - { - throw new ArgumentNullException("data"); - } - CheckSpace(size); - Array.Copy(data, offset, _underlyingData, _position, size); - _position += size; - } - - /// <summary> - /// Writes the given ushort into this buffer at the current position, and then increments the position. - /// </summary> - /// <param name="data">The ushort to be written</param> - public /*override*/ void Put(ushort data) - { - CheckSpace(2); - _underlyingData[_position++] = (byte) (data >> 8); - _underlyingData[_position++] = (byte) data; - } - - public /*override*/ void Put(uint data) - { - CheckSpace(4); - _underlyingData[_position++] = (byte) (data >> 24); - _underlyingData[_position++] = (byte) (data >> 16); - _underlyingData[_position++] = (byte) (data >> 8); - _underlyingData[_position++] = (byte) data; - } - - public /*override*/ void Put(ulong data) - { - CheckSpace(8); - _underlyingData[_position++] = (byte) (data >> 56); - _underlyingData[_position++] = (byte) (data >> 48); - _underlyingData[_position++] = (byte) (data >> 40); - _underlyingData[_position++] = (byte) (data >> 32); - _underlyingData[_position++] = (byte) (data >> 24); - _underlyingData[_position++] = (byte) (data >> 16); - _underlyingData[_position++] = (byte) (data >> 8); - _underlyingData[_position++] = (byte) data; - } - - public void Put(short data) - { - Put((ushort)data); - } - - public void Put(int data) - { - Put((uint)data); - } - - public void Put(long data) - { - Put((ulong)data); - } - - public void Put(float data) - { - unsafe - { - uint val = *((uint*)&data); - Put(val); - } - } - - public void Put(double data) - { - unsafe - { - ulong val = *((ulong*)&data); - Put(val); - } - } - - - /// <summary> - /// Read the byte at the current position and increment the position - /// </summary> - /// <returns>a byte</returns> - /// <exception cref="BufferUnderflowException">if there are no bytes left to read</exception> - public /*override*/ byte Get() - { - CheckSpaceForReading(1); - return _underlyingData[_position++]; - } - - /// <summary> - /// Reads bytes from the buffer into the supplied array - /// </summary> - /// <param name="destination">The destination array. The array must not - /// be bigger than the remaining space in the buffer, nor can it be null.</param> - public /*override*/ void Get(byte[] destination) - { - if (destination == null) - { - throw new ArgumentNullException("destination"); - } - int len = destination.Length; - CheckSpaceForReading(len); - Array.Copy(_underlyingData, _position, destination, 0, len); - _position += len; - } - - /// <summary> - /// Reads and returns an unsigned short (two bytes, big endian) from this buffer - /// </summary> - /// <returns>an unsigned short</returns> - /// <exception cref="BufferUnderflowException">If there are fewer than two bytes remaining in this buffer</exception> - public /*override*/ ushort GetUnsignedShort() - { - CheckSpaceForReading(2); - byte upper = _underlyingData[_position++]; - byte lower = _underlyingData[_position++]; - return (ushort) ((upper << 8) + lower); - } - - /// <summary> - /// Reads and returns an unsigned int (four bytes, big endian) from this buffer - /// </summary> - /// <returns>an unsigned integer</returns> - /// <exception cref="BufferUnderflowException">If there are fewer than four bytes remaining in this buffer</exception> - public /*override*/ uint GetUnsignedInt() - { - CheckSpaceForReading(4); - byte b1 = _underlyingData[_position++]; - byte b2 = _underlyingData[_position++]; - byte b3 = _underlyingData[_position++]; - byte b4 = _underlyingData[_position++]; - return (uint) ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4); - } - - public /*override*/ ulong GetUnsignedLong() - { - CheckSpaceForReading(8); - byte b1 = _underlyingData[_position++]; - byte b2 = _underlyingData[_position++]; - byte b3 = _underlyingData[_position++]; - byte b4 = _underlyingData[_position++]; - byte b5 = _underlyingData[_position++]; - byte b6 = _underlyingData[_position++]; - byte b7 = _underlyingData[_position++]; - byte b8 = _underlyingData[_position++]; - // all the casts necessary because otherwise each subexpression - // only gets promoted to uint and cause incorrect results - return (((ulong)b1 << 56) + ((ulong)b2 << 48) + ((ulong)b3 << 40) + - ((ulong)b4 << 32) + ((ulong)b5 << 24) + - ((ulong)b6 << 16) + ((ulong)b7 << 8) + b8); - } - - public short GetShort() - { - return (short) GetUnsignedShort(); - } - - public int GetInt() - { - return (int) GetUnsignedInt(); - } - - public long GetLong() - { - return (long) GetUnsignedLong(); - } - - public float GetFloat() - { - unsafe - { - uint val = GetUnsignedInt(); - return *((float*)&val); - } - } - - public double GetDouble() - { - unsafe - { - ulong val = GetUnsignedLong(); - return *((double*)&val); - } - } - - public /*override*/ string GetString(uint length, Encoding encoder) - { - CheckSpaceForReading((int)length); - string result = encoder.GetString(_underlyingData, _position, (int)length); - _position += (int)length; - return result; - } - - public /*override*/ void Acquire() - { - } - - public /*override*/ void Release() - { - } - - public /*override*/ bool IsAutoExpand - { - get { return false; } - set { } - } - - public /*override*/ void Expand(int expectedRemaining) - { - throw new NotImplementedException(); - } - - public /*override*/ void Expand(int pos, int expectedRemaining) - { - throw new NotImplementedException(); - } - - public /*override*/ bool Pooled - { - get { return false; } - set { } - } - - public void Mark() - { - throw new NotImplementedException(); - } - - public void Reset() - { - throw new NotImplementedException(); - } - - public /*override*/ byte Get(int index) - { - throw new NotImplementedException(); - } - -// public /*override*/ void Put(ByteBuffer src) -// { -// if (src == this) -// { -// throw new ArgumentException("Cannot copy self into self!"); -// } -// -// HeapByteBuffer sb; -// if (src is HeapByteBuffer) -// { -// sb = (HeapByteBuffer) src; -// } -// else -// { -// sb = (HeapByteBuffer)((RefCountingByteBuffer) src).Buf; -// } -// int n = sb.Remaining; -// if (n > Remaining) -// { -// throw new BufferOverflowException("Not enought capacity in this buffer for " + n + " elements - only " + Remaining + " remaining"); -// } -// Array.Copy(sb._underlyingData, sb._position, _underlyingData, _position, n); -// sb._position += n; -// _position += n; -// } - - public /*override*/ void Compact() - { - if (Remaining > 0) - { - if (_position > 0) - { - Array.Copy(_underlyingData, _position, _underlyingData, 0, Remaining); - } - _position = Remaining; - } - else - { - _position = 0; - } - _limit = Capacity; - } - - public static HeapByteBuffer wrap(byte[] bytes, int length) - { - return new HeapByteBuffer(bytes, length); - } - - public static HeapByteBuffer wrap(byte[] bytes) - { - return new HeapByteBuffer(bytes, bytes.Length); - } - } -} - - diff --git a/qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs b/qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs index c7c2f563aa..0cc0811a5c 100644 --- a/qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs +++ b/qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs @@ -19,32 +19,31 @@ *
*/
+using System;
+
namespace Qpid.Buffer
{
/// <summary>
/// Allocates <see cref="ByteBuffer"/>'s and manages them. Please
/// implement this interface if you need more advanced memory management scheme
/// </summary>
- public interface IByteBufferAllocator
+ public interface IByteBufferAllocator : IDisposable
{
/// <summary>
/// Returns the buffer which is capable of the specified size.
/// </summary>
/// <param name="capacity">The capacity of the buffer</param>
- /// <param name="direct">true to get a direct buffer, false to get a heap buffer</param>
- ByteBuffer Allocate(int capacity, bool direct);
+ /// <returns>A new buffer</returns>
+ ByteBuffer Allocate(int capacity);
/// <summary>
- /// Wraps the specified buffer
+ /// Wrap the specified byte array in a new buffer
/// </summary>
- /// <param name="nioBuffer">fixed byte buffer</param>
- /// <returns>The wrapped buffer</returns>
- ByteBuffer Wrap(FixedByteBuffer nioBuffer);
+ /// <param name="src">Source array</param>
+ /// <returns>A new buffer</returns>
+ ByteBuffer Wrap(byte[] src);
+
+ } // interface IByteBufferAllocator
+}
- /// <summary>
- /// Dispose of this allocator.
- /// </summary>
- void Dispose();
- }
-}
\ No newline at end of file diff --git a/qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj b/qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj index e6bade037b..a03bf348b2 100644 --- a/qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj +++ b/qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj @@ -38,18 +38,15 @@ <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
- <Compile Include="BaseByteBuffer.cs" />
- <Compile Include="BufferDataException.cs" />
<Compile Include="BufferOverflowException.cs" />
<Compile Include="BufferUnderflowException.cs" />
<Compile Include="ByteBuffer.cs" />
<Compile Include="ByteBufferHexDumper.cs" />
- <Compile Include="ByteBufferProxy.cs" />
- <Compile Include="FixedByteBuffer.cs" />
- <Compile Include="HeapByteBuffer.cs" />
<Compile Include="IByteBufferAllocator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SimpleByteBuffer.cs" />
<Compile Include="SimpleByteBufferAllocator.cs" />
+ <Compile Include="SlicedByteBuffer.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
diff --git a/qpid/dotnet/Qpid.Buffer/SimpleByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/SimpleByteBuffer.cs new file mode 100644 index 0000000000..d91f7747d2 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/SimpleByteBuffer.cs @@ -0,0 +1,120 @@ +/*
+ *
+ * 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
+{
+ internal sealed class SimpleByteBuffer : ByteBuffer
+ {
+ private byte[] _buffer;
+
+ public override int Capacity
+ {
+ get { return _buffer.Length; }
+ }
+
+ public override byte[] Array
+ {
+ get { return _buffer; }
+ }
+
+ /// <summary>
+ /// Initialize a new instance with the desired size
+ /// </summary>
+ /// <param name="desiredSize">Initial Length of the array</param>
+ internal SimpleByteBuffer(int desiredSize)
+ {
+ _buffer = new byte[desiredSize];
+ Position = 0;
+ Limit = Capacity;
+ }
+
+ /// <summary>
+ /// Initialize a new instance with the data from
+ /// an underlying array
+ /// </summary>
+ /// <param name="buffer">Initial data</param>
+ /// <remarks>The original array is copied during construction and is not modified</remarks>
+ internal SimpleByteBuffer(byte[] buffer)
+ {
+ _buffer = (byte[])buffer.Clone();
+ // position at end
+ Position = Limit = Capacity;
+ }
+
+ protected override void DoWrite(int position, byte value)
+ {
+ // available space is already handled by base class
+ _buffer[position] = value;
+ }
+
+ protected override void DoWrite(int position, byte[] src, int offset, int length)
+ {
+ // available space is already handled by base class
+ for ( int i = 0; i < length; i++ )
+ {
+ _buffer[position+i] = src[offset+i];
+ }
+ }
+
+ protected override byte DoReadByte(int position)
+ {
+ return _buffer[position];
+ }
+
+ protected override void DoReadBytes(int position, byte[] dest, int offset, int length)
+ {
+ System.Array.Copy(_buffer, position, dest, offset, length);
+ }
+
+ protected override void DoCompact()
+ {
+ if ( Remaining > 0 )
+ {
+ if ( Position > 0 )
+ {
+ System.Array.Copy(_buffer, Position, _buffer, 0, Remaining);
+ }
+ Position = Remaining;
+ } else
+ {
+ Position = 0;
+ }
+ Limit = Capacity;
+ }
+
+ protected override void DoResize(int newSize)
+ {
+ if ( newSize < Capacity )
+ throw new NotSupportedException("Cannot resize a buffer to make it smaller");
+
+ int newCapacity = 1;
+ while ( newCapacity < newSize )
+ {
+ newCapacity <<= 1;
+ }
+
+ byte[] newBuffer = new byte[newCapacity];
+ System.Array.Copy(_buffer, newBuffer, _buffer.Length);
+ _buffer = newBuffer;
+ }
+ } // class SimpleByteBuffer
+}
diff --git a/qpid/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs b/qpid/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs index 2de3a13560..6933480c92 100644 --- a/qpid/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs +++ b/qpid/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs @@ -18,171 +18,40 @@ * under the License. * */ -using System; -using System.Runtime.CompilerServices; namespace Qpid.Buffer { - /// <summary> - /// A simplistic <see cref="ByteBufferAllocator"/> which simply allocates a new - /// buffer every time - /// </summary> - public class SimpleByteBufferAllocator : IByteBufferAllocator - { - private const int MINIMUM_CAPACITY = 1; + /// <summary> + /// Allocates <see cref="ByteBuffer"/>'s and manages them. + /// This is a simple implementation that just returns buffers + /// as they are. Buffers are not reused or refcounted + /// </summary> + public class SimpleByteBufferAllocator : IByteBufferAllocator + { + #region IByteBufferAllocator Members - public SimpleByteBufferAllocator() - { - } - - public ByteBuffer Allocate( int capacity, bool direct ) - { - FixedByteBuffer nioBuffer; - if( direct ) - { - nioBuffer = FixedByteBuffer.allocateDirect( capacity ); - } - else - { - nioBuffer = FixedByteBuffer.allocate( capacity ); - } - return new SimpleByteBuffer( nioBuffer ); - } - - public ByteBuffer Wrap( FixedByteBuffer nioBuffer ) - { - return new SimpleByteBuffer( nioBuffer ); - } + public ByteBuffer Allocate(int capacity) + { + return new SimpleByteBuffer(capacity); + } - public void Dispose() - { - } + public ByteBuffer Wrap(byte[] src) + { + return new SimpleByteBuffer(src); + } - private class SimpleByteBuffer : BaseByteBuffer - { - private FixedByteBuffer _buf; - private int refCount = 1; + #endregion - internal SimpleByteBuffer( FixedByteBuffer buf ) - { - this._buf = buf; - buf.order( ByteOrder.BigEndian ); - refCount = 1; - } + #region IDisposable Members - [MethodImpl(MethodImplOptions.Synchronized)] - public override void acquire() - { - if( refCount <= 0 ) - { - throw new InvalidOperationException("Already released buffer."); - } + public void Dispose() + { + // no need to do anaything + } - refCount ++; - } + #endregion - public override void release() - { - lock( this ) - { - if( refCount <= 0 ) - { - refCount = 0; - throw new InvalidOperationException( - "Already released buffer. You released the buffer too many times." ); - } - - refCount --; - if( refCount > 0) - { - return; - } - } - } - - public override FixedByteBuffer buf() - { - return _buf; - } - - public override bool isPooled() - { - return false; - } - - public override void setPooled(bool pooled) - { - } - - protected override void capacity0(int requestedCapacity) - { - int newCapacity = MINIMUM_CAPACITY; - while( newCapacity < requestedCapacity ) - { - newCapacity <<= 1; - } - - FixedByteBuffer oldBuf = this._buf; - FixedByteBuffer newBuf; - if( isDirect() ) - { - newBuf = FixedByteBuffer.allocateDirect( newCapacity ); - } - else - { - newBuf = FixedByteBuffer.allocate( newCapacity ); - } - - newBuf.clear(); - oldBuf.clear(); - newBuf.put( oldBuf ); - this._buf = newBuf; - } - - public override ByteBuffer duplicate() { - return new SimpleByteBuffer( this._buf.duplicate() ); - } - - public override ByteBuffer slice() - { - return new SimpleByteBuffer( this._buf.slice() ); - } - - public override ByteBuffer asReadOnlyBuffer() - { - return new SimpleByteBuffer( this._buf.asReadOnlyBuffer() ); - } - - public override byte[] array() - { - return _buf.array(); - } - - public override int arrayOffset() - { - return _buf.arrayOffset(); - } - - public override void put(ushort value) - { - _buf.put(value); - } - - public override void put(uint max) - { - _buf.put(max); - } - - public override void put(ulong tag) - { - _buf.put(tag); - } + } // class SimpleByteBufferAllocator +} - public override ulong GetUnsignedLong() - { - return _buf.getUnsignedLong(); - } - } - } -} diff --git a/qpid/dotnet/Qpid.Buffer/SlicedByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/SlicedByteBuffer.cs new file mode 100644 index 0000000000..414da94a8d --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/SlicedByteBuffer.cs @@ -0,0 +1,86 @@ +/*
+ *
+ * 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
+{
+ internal sealed class SlicedByteBuffer : ByteBuffer
+ {
+ private ByteBuffer _buffer;
+ private int _capacity;
+ private int _startPos;
+
+ public override int Capacity
+ {
+ get { return _capacity; }
+ }
+
+ public override byte[] Array
+ {
+ get { return _buffer.Array; }
+ }
+
+ /// <summary>
+ /// Initialize a new instance
+ /// </summary>
+ /// <param name="buffer">Underlying byte buffer</param>
+ internal SlicedByteBuffer(ByteBuffer buffer)
+ {
+ _buffer = buffer;
+ _startPos = buffer.Position;
+ Position = 0;
+ _capacity = buffer.Remaining;
+ Limit = Capacity;
+ // cannot autoexpand
+ IsAutoExpand = false;
+ }
+
+ protected override void DoWrite(int position, byte value)
+ {
+ _buffer.Put(_startPos + position, value);
+ }
+
+ protected override void DoWrite(int position, byte[] src, int offset, int length)
+ {
+ _buffer.Put(_startPos + position, src, offset, length);
+ }
+
+ protected override byte DoReadByte(int position)
+ {
+ return _buffer.GetByte(_startPos + position);
+ }
+
+ protected override void DoReadBytes(int position, byte[] dest, int offset, int length)
+ {
+ _buffer.GetBytes(_startPos + position, dest, offset, length);
+ }
+
+ protected override void DoCompact()
+ {
+ throw new NotSupportedException();
+ }
+
+ protected override void DoResize(int newSize)
+ {
+ throw new NotSupportedException();
+ }
+ } // class SlicedByteBuffer
+}
|