Turn ByteQueue into MemoryStream wrapper, use MemoryStream for serialization of COutP...
[NovacoinLibrary.git] / Novacoin / ByteQueue.cs
1 \feff/**
2  *  Novacoin classes library
3  *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
4
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 using System;
20 using System.Collections.Generic;
21 using System.Diagnostics.Contracts;
22 using System.IO;
23
24 namespace Novacoin
25 {
26     [Serializable]
27     public class ByteQueueException : Exception
28     {
29         public ByteQueueException()
30         {
31         }
32
33         public ByteQueueException(string message)
34             : base(message)
35         {
36         }
37
38         public ByteQueueException(string message, Exception inner)
39             : base(message, inner)
40         {
41         }
42     }
43
44     /// <summary>
45     /// Stream of bytes.
46     /// 
47     /// TODO: rewrite using MemoryStream
48     /// </summary>
49     public class ByteQueue : IDisposable
50     {
51         private bool disposed = false;
52
53         private MemoryStream _Stream;
54         private BinaryReader _Reader;
55
56         public ByteQueue(ref byte[] buffer, int Start)
57         {
58             _Stream = new MemoryStream(buffer);
59             _Stream.Seek(Start, SeekOrigin.Begin);
60             _Reader = new BinaryReader(_Stream);
61         }
62
63         public ByteQueue(ref byte[] buffer)
64         {
65             _Stream = new MemoryStream(buffer);
66             _Reader = new BinaryReader(_Stream);
67         }
68
69         public ByteQueue(ref List<byte> List, int Start)
70         {
71             _Stream = new MemoryStream(List.ToArray());
72             _Stream.Seek(Start, SeekOrigin.Begin);
73             _Reader = new BinaryReader(_Stream);
74         }
75
76         public ByteQueue(ref List<byte> List)
77         {
78             _Stream = new MemoryStream(List.ToArray());
79             _Reader = new BinaryReader(_Stream);
80         }
81
82         ~ByteQueue()
83         {
84             Dispose(false);
85         }
86
87         public void Dispose()
88         {
89             Dispose(true);
90             GC.SuppressFinalize(this);
91         }
92
93         protected virtual void Dispose(bool disposing)
94         {
95             if (!disposed)
96             {
97                 if (disposing)
98                 {
99                     _Reader.Dispose();
100                     _Stream.Dispose();
101                 }
102
103                 disposed = true;
104             }
105         }
106
107         public byte Get()
108         {
109             if (_Stream.Position == _Stream.Length)
110             {
111                 throw new ByteQueueException("No elements left.");
112             }
113
114             return _Reader.ReadByte();
115         }
116
117         public bool TryGet(ref byte Element)
118         {
119             if (_Stream.Position == _Stream.Length)
120             {
121                 return false;
122             }
123
124             Element = _Reader.ReadByte();
125
126             return true;
127         }
128
129         public byte[] Get(int nCount)
130         {
131             Contract.Requires<ArgumentException>(Count - Index >= nCount, "nCount is greater than amount of elements.");
132
133             return _Reader.ReadBytes(nCount);
134         }
135
136         public bool TryGet(int nCount, ref byte[] Elements)
137         {
138             Elements = _Reader.ReadBytes(nCount);
139             return (Elements.Length == nCount);
140         }
141
142         /// <summary>
143         /// Current index value
144         /// </summary>
145         public int Index
146         {
147             get { return (int)_Stream.Position; }
148         }
149
150         public int Count
151         {
152             get { return (int)_Stream.Length; }
153         }
154
155         public ulong GetVarInt()
156         {
157             try
158             {
159                 byte prefix = _Reader.ReadByte();
160
161                 switch (prefix)
162                 {
163                     case 0xfd: // ushort
164                         return _Reader.ReadUInt16();
165                     case 0xfe: // uint
166                         return _Reader.ReadUInt32();
167                     case 0xff: // ulong
168                         return _Reader.ReadUInt64();
169                     default:
170                         return prefix;
171                 }
172             }
173             catch (EndOfStreamException e)
174             {
175                 throw new ByteQueueException("No elements left.", e);
176             }
177         }
178     }
179 }
180
181