Turn ByteQueue into MemoryStream wrapper, use MemoryStream for serialization of COutP...
[NovacoinLibrary.git] / Novacoin / VarInt.cs
index ee6652d..0f77b18 100644 (file)
@@ -1,8 +1,24 @@
-\feffusing System;
+\feff/**
+ *  Novacoin classes library
+ *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
+
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Affero General Public License as
+ *  published by the Free Software Foundation, either version 3 of the
+ *  License, or (at your option) any later version.
+
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Affero General Public License for more details.
+
+ *  You should have received a copy of the GNU Affero General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.IO;
 
 namespace Novacoin
 {
@@ -15,9 +31,9 @@ namespace Novacoin
         /// </summary>
         /// <param name="n">Unsigned integer value</param>
         /// <returns>Byte sequence</returns>
-        public static IList<byte> EncodeVarInt(ulong n)
+        public static byte[] EncodeVarInt(ulong n)
         {
-            List<byte> resultBytes = new List<byte>();
+            var resultBytes = new List<byte>();
 
             if (n <= 0xfc)
             {
@@ -33,26 +49,26 @@ namespace Novacoin
                 {
                     // ushort flag
                     prefix = 0xfd;
-                    valueBytes = Interop.LEBytes((ushort)n);
+                    valueBytes = BitConverter.GetBytes((ushort)n);
                 }
                 else if (n <= uint.MaxValue)
                 {
                     // uint flag
                     prefix = 0xfe;
-                    valueBytes = Interop.LEBytes((uint)n);
+                    valueBytes = BitConverter.GetBytes((uint)n);
                 }
                 else
                 {
                     // ulong flag
                     prefix = 0xff;
-                    valueBytes = Interop.LEBytes(n);
+                    valueBytes = BitConverter.GetBytes(n);
                 }
 
                 resultBytes.Add(prefix);
                 resultBytes.AddRange(valueBytes);
             }
 
-            return resultBytes;
+            return resultBytes.ToArray();
         }
 
         /// <summary>
@@ -62,11 +78,31 @@ namespace Novacoin
         /// </summary>
         /// <param name="n">Integer value</param>
         /// <returns>Byte sequence</returns>
-        public static IList<byte> EncodeVarInt(long n)
+        public static byte[] EncodeVarInt(long n)
         {
             return EncodeVarInt((ulong)n);
         }
 
+        public static int GetEncodedSize(long n)
+        {
+            if (n <= 0xfc)
+            {
+                return 1;
+            }
+            else if (n <= ushort.MaxValue)
+            {
+                return 3;
+            }
+            else if (n <= uint.MaxValue)
+            {
+                return 5;
+            }
+            else
+            {
+                return 9;
+            }
+        }
+
         /// <summary>
         /// Decodes integer value from compact representation
         /// 
@@ -74,74 +110,42 @@ namespace Novacoin
         /// </summary>
         /// <param name="bytes">Byte sequence</param>
         /// <returns>Integer value</returns>
-        public static ulong DecodeVarInt(IList<byte> bytes)
+        public static ulong DecodeVarInt(byte[] bytes)
         {
-            byte prefix = bytes[0];
+            var prefix = bytes[0];
+            var bytesArray = new byte[bytes.Length - 1];
 
-            bytes.RemoveAt(0); // Remove prefix
+            bytes.CopyTo(bytesArray, 1);  // Get rid of prefix
 
-            byte[] bytesArray = bytes.ToArray();
-
-            if (BitConverter.IsLittleEndian)
-            {
-                switch (prefix)
-                {
-                    case 0xfd: // ushort flag
-                        return BitConverter.ToUInt16(bytesArray, 0);
-                    case 0xfe: // uint flag
-                        return BitConverter.ToUInt32(bytesArray, 0);
-                    case 0xff: // ulong flag
-                        return BitConverter.ToUInt64(bytesArray, 0);
-                    default:
-                        return prefix;
-                }
-            }
-            else
+            switch (prefix)
             {
-                // Values are stored in little-endian order
-                switch (prefix)
-                {
-                    case 0xfd: // ushort flag
-                        Array.Resize<byte>(ref bytesArray, 2);
-                        Array.Reverse(bytesArray);
-                        return BitConverter.ToUInt16(bytesArray, 0);
-                    case 0xfe: // uint flag
-                        Array.Resize<byte>(ref bytesArray, 4);
-                        Array.Reverse(bytesArray);
-                        return BitConverter.ToUInt32(bytesArray, 0);
-                    case 0xff: // ulong flag
-                        Array.Resize<byte>(ref bytesArray, 8);
-                        Array.Reverse(bytesArray);
-                        return BitConverter.ToUInt64(bytesArray, 0);
-                    default:
-                        return prefix;
-                }
+                case 0xfd: // ushort flag
+                    return BitConverter.ToUInt16(bytesArray, 0);
+                case 0xfe: // uint flag
+                    return BitConverter.ToUInt32(bytesArray, 0);
+                case 0xff: // ulong flag
+                    return BitConverter.ToUInt64(bytesArray, 0);
+                default:
+                    return prefix;
             }
         }
 
-        /// <summary>
-        /// Read and decode variable integer from wrapped list object.
-        /// 
-        /// Note: Should be used only if there is some variable integer data at current position. Otherwise you will get undefined behavior, so make sure that you know what you are doing.
-        /// </summary>
-        /// <param name="wBytes"></param>
-        /// <returns></returns>
-        public static ulong ReadVarInt(ref WrappedList<byte> wBytes)
+        public static ulong ReadVarInt(ref BinaryReader reader)
         {
-            byte prefix = wBytes.GetItem();
+            byte prefix = reader.ReadByte();
 
             switch (prefix)
             {
                 case 0xfd: // ushort
-                    return Interop.LEBytesToUInt16(wBytes.GetItems(2));
+                    return reader.ReadUInt16();
                 case 0xfe: // uint
-                    return Interop.LEBytesToUInt32(wBytes.GetItems(4));
+                    return reader.ReadUInt32();
                 case 0xff: // ulong
-                    return Interop.LEBytesToUInt64(wBytes.GetItems(8));
+                    return reader.ReadUInt64();
                 default:
                     return prefix;
             }
-
         }
+
     }
 }