diff options
Diffstat (limited to 'qpid/dotnet/Qpid.Buffer')
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/BufferOverflowException.cs | 41 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/BufferUnderflowException.cs | 42 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/ByteBuffer.cs | 982 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs | 79 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs | 50 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/Properties/AssemblyInfo.cs | 53 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj | 59 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/SimpleByteBuffer.cs | 120 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs | 58 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/SlicedByteBuffer.cs | 86 | ||||
-rw-r--r-- | qpid/dotnet/Qpid.Buffer/default.build | 25 |
11 files changed, 1595 insertions, 0 deletions
diff --git a/qpid/dotnet/Qpid.Buffer/BufferOverflowException.cs b/qpid/dotnet/Qpid.Buffer/BufferOverflowException.cs new file mode 100644 index 0000000000..5a2fff74a7 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/BufferOverflowException.cs @@ -0,0 +1,41 @@ +/* + * + * 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 Apache.Qpid.Buffer +{ + [Serializable] + public class BufferOverflowException : Exception + { + public BufferOverflowException(string message) : base(message) + { + } + + protected BufferOverflowException(SerializationInfo info, StreamingContext ctxt) + : base(info, ctxt) + { + } + } +} + + + diff --git a/qpid/dotnet/Qpid.Buffer/BufferUnderflowException.cs b/qpid/dotnet/Qpid.Buffer/BufferUnderflowException.cs new file mode 100644 index 0000000000..13939b77a8 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/BufferUnderflowException.cs @@ -0,0 +1,42 @@ +/* + * + * 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 Apache.Qpid.Buffer +{ + [Serializable] + public class BufferUnderflowException : Exception + { + public BufferUnderflowException(string message) + : base(message) + { + } + + protected BufferUnderflowException(SerializationInfo info, StreamingContext ctxt) + : base(info, ctxt) + { + } + } +} + + + diff --git a/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs new file mode 100644 index 0000000000..67f0edd440 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/ByteBuffer.cs @@ -0,0 +1,982 @@ +/* + * + * 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 Apache.Qpid.Buffer +{ + /// <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 new file mode 100644 index 0000000000..4c2856c333 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs @@ -0,0 +1,79 @@ +/* + * + * 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.Text; + +namespace Apache.Qpid.Buffer +{ + public class ByteBufferHexDumper + { + private static byte[] highDigits; + + private static byte[] lowDigits; + + static ByteBufferHexDumper() + { + byte[] digits = { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', + (byte)'7', (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', + (byte)'E', (byte)'F' }; + int i; + byte[] high = new byte[256]; + byte[] low = new byte[256]; + + for (i = 0; i < 256; i++) + { + high[i] = digits[i >> 4]; + low[i] = digits[i & 0x0F]; + } + + highDigits = high; + lowDigits = low; + } + + public static string GetHexDump(ByteBuffer input) + { + int size = input.Remaining; + if (size == 0) + { + return "empty"; + } + + StringBuilder output = new StringBuilder(size * 3 - 1); + + byte[] data = input.Array; + int byteValue = data[0] & 0xFF; + output.Append((char) highDigits[byteValue]); + output.Append((char) lowDigits[byteValue]); + + for (int i = 1 ; i < size; i++) + { + output.Append(' '); + byteValue = data[i] & 0xFF; + output.Append((char) highDigits[byteValue]); + output.Append((char) lowDigits[byteValue]); + } + + return output.ToString(); + } + } +} + + + diff --git a/qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs b/qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs new file mode 100644 index 0000000000..0f457df065 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/IByteBufferAllocator.cs @@ -0,0 +1,50 @@ +/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+
+namespace Apache.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 : IDisposable
+ {
+ /// <summary>
+ /// Returns the buffer which is capable of the specified size.
+ /// </summary>
+ /// <param name="capacity">The capacity of the buffer</param>
+ /// <returns>A new buffer</returns>
+ ByteBuffer Allocate(int capacity);
+
+ /// <summary>
+ /// Wrap the specified byte array in a new buffer
+ /// </summary>
+ /// <param name="src">Source array</param>
+ /// <returns>A new buffer</returns>
+ ByteBuffer Wrap(byte[] src);
+
+ } // interface IByteBufferAllocator
+}
+
+
+
diff --git a/qpid/dotnet/Qpid.Buffer/Properties/AssemblyInfo.cs b/qpid/dotnet/Qpid.Buffer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..f8fa3f97b9 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/Properties/AssemblyInfo.cs @@ -0,0 +1,53 @@ +/* + * + * 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.Reflection; +using System.Runtime.InteropServices; +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Apache.Qpid.ByteBuffer")] +[assembly: AssemblyDescription("Built from svn revision number: ")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Apache Software Foundation")] +[assembly: AssemblyProduct("Apache.Qpid.ByteBuffer")] +[assembly: AssemblyCopyright("Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2b3333e5-03b5-4f00-9215-66009f8a5c47")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("2.1.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj b/qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj new file mode 100644 index 0000000000..9320438f6f --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/Qpid.Buffer.csproj @@ -0,0 +1,59 @@ +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Buffer</RootNamespace>
+ <AssemblyName>Apache.Qpid.Buffer</AssemblyName>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>
+ </AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BufferOverflowException.cs" />
+ <Compile Include="BufferUnderflowException.cs" />
+ <Compile Include="ByteBuffer.cs" />
+ <Compile Include="ByteBufferHexDumper.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.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/qpid/dotnet/Qpid.Buffer/SimpleByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/SimpleByteBuffer.cs new file mode 100644 index 0000000000..d3b7245cb1 --- /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 Apache.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 new file mode 100644 index 0000000000..e772e59ae3 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs @@ -0,0 +1,58 @@ +/* + * + * 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. + * + */ + +namespace Apache.Qpid.Buffer +{ + /// <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 ByteBuffer Allocate(int capacity) + { + return new SimpleByteBuffer(capacity); + } + + public ByteBuffer Wrap(byte[] src) + { + return new SimpleByteBuffer(src); + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + // no need to do anaything + } + + #endregion + + } // class SimpleByteBufferAllocator +} + + + diff --git a/qpid/dotnet/Qpid.Buffer/SlicedByteBuffer.cs b/qpid/dotnet/Qpid.Buffer/SlicedByteBuffer.cs new file mode 100644 index 0000000000..c27b7949b6 --- /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 Apache.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
+}
diff --git a/qpid/dotnet/Qpid.Buffer/default.build b/qpid/dotnet/Qpid.Buffer/default.build new file mode 100644 index 0000000000..c2d36d15e6 --- /dev/null +++ b/qpid/dotnet/Qpid.Buffer/default.build @@ -0,0 +1,25 @@ +<?xml version="1.0"?>
+<project name="Apache.Qpid.Buffer" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ unsafe="true"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ </references>
+ </csc>
+ </target>
+</project>
+
|