using System; using System.IO; namespace Quobject.EngineIoClientDotNet.Parser { public class ByteBuffer { private readonly MemoryStream _memoryStream; private long _limit = 0; public ByteBuffer(int length) { this._memoryStream = new MemoryStream(); _memoryStream.SetLength(length); _memoryStream.Capacity = length; _limit = length; } public static ByteBuffer Allocate(int length) { return new ByteBuffer(length); } internal void Put(byte[] buf) { _memoryStream.Write(buf,0,buf.Length); } internal byte[] Array() { return _memoryStream.ToArray(); } internal static ByteBuffer Wrap(byte[] data) { var result = new ByteBuffer(data.Length); result.Put(data); return result; } /// /// A buffer's capacity is the number of elements it contains. The capacity of a /// buffer is never negative and never changes. /// public int Capacity { get { return _memoryStream.Capacity; } } /// /// Absolute get method. Reads the byte at the given index. /// /// The index from which the byte will be read /// The byte at the given index internal byte Get(long index) { if (index > Capacity) { throw new IndexOutOfRangeException(); } _memoryStream.Position = index; return (byte) _memoryStream.ReadByte(); } /// /// Relative bulk get method. /// /// This method transfers bytes from this buffer into the given destination array. If there are fewer bytes /// remaining in the buffer than are required to satisfy the request, that is, if length > remaining(), then /// no bytes are transferred and a BufferUnderflowException is thrown. /// /// Otherwise, this method copies length bytes from this buffer into the given array, starting at the current /// position of this buffer and at the given offset in the array. The position of this buffer is then /// incremented by length. /// /// In other words, an invocation of this method of the form src.get(dst, off, len) has exactly the same effect as the loop /// /// for (int i = off; i < off + len; i++) /// dst[i] = src.get(); /// /// except that it first checks that there are sufficient bytes in this buffer and it is potentially much more efficient. /// /// /// /// /// This buffer internal ByteBuffer Get(byte[] dst, int offset, int length) { _memoryStream.Read(dst, offset, length); return this; } /// /// Relative bulk get method. /// /// This method transfers bytes from this buffer into the given destination array. /// An invocation of this method of the form src.get(a) behaves in exactly the same /// way as the invocation src.get(a, 0, a.length) /// /// /// This buffer internal ByteBuffer Get(byte[] dst) { return Get(dst, 0, dst.Length); } /// /// Sets this buffer's position. If the mark is defined and larger than the new /// position then it is discarded. /// /// The new position value; must be non-negative and no larger than the current limit internal void Position(long newPosition) { _memoryStream.Position = newPosition; } /// /// Sets this buffer's limit. If the position is larger than the new limit then it is set to the new limit. /// If the mark is defined and larger than the new limit then it is discarded. /// /// A buffer's limit is the index of the first element that should not be read or written. A buffer's limit is never negative and is never greater than its capacity. /// /// The new limit value; must be non-negative and no larger than this buffer's capacity internal void Limit(long newLimit) { _limit = newLimit; if (_memoryStream.Position > newLimit) { _memoryStream.Position = newLimit; } } /// /// Returns the number of elements between the current position and the limit. /// /// The number of elements remaining in this buffer internal long Remaining() { return (_limit - _memoryStream.Position); } /// /// Clears this buffer. The position is set to zero, the limit is set to the capacity, and the mark is discarded. /// /// This method does not actually erase the data in the buffer, but it is named as if /// it did because it will most often be used in situations in which that might as well be the case. /// internal void Clear() { Position(0); Limit(Capacity); } } }