Turn ByteQueue into MemoryStream wrapper, use MemoryStream for serialization of COutP...
[NovacoinLibrary.git] / Novacoin / ByteQueue.cs
index 813d187..8af351f 100644 (file)
 
 using System;
 using System.Collections.Generic;
-using System.Linq;
+using System.Diagnostics.Contracts;
+using System.IO;
 
 namespace Novacoin
 {
+    [Serializable]
     public class ByteQueueException : Exception
     {
         public ByteQueueException()
@@ -39,86 +41,141 @@ namespace Novacoin
         }
     }
 
-    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;
             }
+        }
 
-            byte[] result = Elements.Skip(Index).Take(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;
             }
 
-            byte[] result = Elements.Skip(Index).Take(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);
             }
         }
     }
 }
+
+