/* * * 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; /// /// The position of the next value to be read or written /// private int _position; /// /// The index of the first element that should not be read or written /// 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; } } /// /// Sets this buffer's limit. If the position is larger than the new limit then it is set to the new limit. /// /// The new limit value; must be non-negative and no larger than this buffer's capacity 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; } } } /// /// Returns the number of elements between the current position and the limit /// /// The number of elements remaining in this buffer 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); } } /// /// Writes the given byte into this buffer at the current position, and then increments the position. /// /// The byte to be written /// If this buffer's current position is not smaller than its limit public /*override*/ void Put(byte data) { CheckSpace(1); _underlyingData[_position++] = data; } /// /// Writes all the data in the given byte array into this buffer at the current /// position and then increments the position. /// /// The data to copy. /// If this buffer's current position plus the array length is not smaller than its limit 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; } /// /// Writes the given ushort into this buffer at the current position, and then increments the position. /// /// The ushort to be written 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; } /// /// Read the byte at the current position and increment the position /// /// a byte /// if there are no bytes left to read public /*override*/ byte Get() { CheckSpaceForReading(1); return _underlyingData[_position++]; } /// /// Reads bytes from the buffer into the supplied array /// /// The destination array. The array must not /// be bigger than the remaining space in the buffer, nor can it be null. 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; } /// /// Reads and returns an unsigned short (two bytes, big endian) from this buffer /// /// an unsigned short /// If there are fewer than two bytes remaining in this buffer public /*override*/ ushort GetUnsignedShort() { CheckSpaceForReading(2); byte upper = _underlyingData[_position++]; byte lower = _underlyingData[_position++]; return (ushort) ((upper << 8) + lower); } /// /// Reads and returns an unsigned int (four bytes, big endian) from this buffer /// /// an unsigned integer /// If there are fewer than four bytes remaining in this buffer 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++]; return (ulong)((b1 << 56) + (b2 << 48) + (b3 << 40) + (b4 << 32) + (b5 << 24) + (b6 << 16) + (b7 << 8) + b8); } 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); } } }