using System;
using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.IO;
namespace Novacoin
{
+ [Serializable]
public class ByteQueueException : Exception
{
public ByteQueueException()
}
}
- public class ByteQueue
+ /// <summary>
+ /// Stream of bytes.
+ ///
+ /// TODO: rewrite using MemoryStream
+ /// </summary>
+ public class ByteQueue : IDisposable
{
- private int Index;
- private List<byte> Elements;
+ private bool disposed = false;
- public ByteQueue(IList<byte> List, int Start)
+ private MemoryStream _Stream;
+ private BinaryReader _Reader;
+
+ public ByteQueue(ref byte[] buffer, int Start)
{
- Elements = new List<byte>(List);
- Index = Start;
+ _Stream = new MemoryStream(buffer);
+ _Stream.Seek(Start, SeekOrigin.Begin);
+ _Reader = new BinaryReader(_Stream);
}
- public ByteQueue(IList<byte> List)
+ public ByteQueue(ref byte[] buffer)
{
- Elements = new List<byte>(List);
- Index = 0;
+ _Stream = new MemoryStream(buffer);
+ _Reader = new BinaryReader(_Stream);
}
- public byte Get()
+ public ByteQueue(ref List<byte> List, int Start)
{
- if (Elements.Count <= Index)
- {
- throw new ByteQueueException("No elements left.");
- }
+ _Stream = new MemoryStream(List.ToArray());
+ _Stream.Seek(Start, SeekOrigin.Begin);
+ _Reader = new BinaryReader(_Stream);
+ }
+
+ public ByteQueue(ref List<byte> List)
+ {
+ _Stream = new MemoryStream(List.ToArray());
+ _Reader = new BinaryReader(_Stream);
+ }
- return Elements[Index++];
+ ~ByteQueue()
+ {
+ Dispose(false);
}
- public byte GetCurrent()
+ public void Dispose()
{
- return Elements[Index];
+ Dispose(true);
+ GC.SuppressFinalize(this);
}
- public byte[] Get(int Count)
+ protected virtual void Dispose(bool disposing)
{
- if (Elements.Count - Index < Count)
+ if (!disposed)
{
- throw new ByteQueueException("Unable to read requested amount of data.");
+ if (disposing)
+ {
+ _Reader.Dispose();
+ _Stream.Dispose();
+ }
+
+ disposed = true;
}
+ }
- var result = Elements.GetRange(Index, Count).ToArray();
- Index += Count;
+ public byte Get()
+ {
+ if (_Stream.Position == _Stream.Length)
+ {
+ throw new ByteQueueException("No elements left.");
+ }
- return result;
+ return _Reader.ReadByte();
}
- public byte[] GetCurrent(int Count)
+ public bool TryGet(ref byte Element)
{
- if (Elements.Count - Index < Count)
+ if (_Stream.Position == _Stream.Length)
{
- throw new ByteQueueException("Unable to read requested amount of data.");
+ return false;
}
- var result = Elements.GetRange(Index, Count).ToArray();
+ Element = _Reader.ReadByte();
+
+ return true;
+ }
+
+ public byte[] Get(int nCount)
+ {
+ Contract.Requires<ArgumentException>(Count - Index >= nCount, "nCount is greater than amount of elements.");
+
+ return _Reader.ReadBytes(nCount);
+ }
- return result;
+ public bool TryGet(int nCount, ref byte[] Elements)
+ {
+ Elements = _Reader.ReadBytes(nCount);
+ return (Elements.Length == nCount);
}
/// <summary>
/// Current index value
/// </summary>
- public int CurrentIndex
+ public int Index
{
- get { return Index; }
+ get { return (int)_Stream.Position; }
}
- public ulong GetVarInt()
+ public int Count
{
- byte prefix = Get();
+ get { return (int)_Stream.Length; }
+ }
- switch (prefix)
+ public ulong GetVarInt()
+ {
+ try
{
- case 0xfd: // ushort
- return BitConverter.ToUInt16(Get(2), 0);
- case 0xfe: // uint
- return BitConverter.ToUInt32(Get(4), 0);
- case 0xff: // ulong
- return BitConverter.ToUInt64(Get(8), 0);
- default:
- return prefix;
+ byte prefix = _Reader.ReadByte();
+
+ switch (prefix)
+ {
+ case 0xfd: // ushort
+ return _Reader.ReadUInt16();
+ case 0xfe: // uint
+ return _Reader.ReadUInt32();
+ case 0xff: // ulong
+ return _Reader.ReadUInt64();
+ default:
+ return prefix;
+ }
+ }
+ catch (EndOfStreamException e)
+ {
+ throw new ByteQueueException("No elements left.", e);
}
}
}
}
+
+