e78d107ffc76dd3210fb644078481a9c58fb4ef4
[NovacoinLibrary.git] / Novacoin / VarInt.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
22 namespace Novacoin
23 {
24     public class VarInt
25     {
26         /// <summary>
27         /// Encodes unsigned integer value into compact representation.
28         /// 
29         /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
30         /// </summary>
31         /// <param name="n">Unsigned integer value</param>
32         /// <returns>Byte sequence</returns>
33         public static byte[] EncodeVarInt(ulong n)
34         {
35             var resultBytes = new List<byte>();
36
37             if (n <= 0xfc)
38             {
39                 // Values up to 0xfc are stored directly without any prefix
40                 resultBytes.Add((byte)n);
41             }
42             else
43             {
44                 byte prefix;
45                 byte[] valueBytes;
46
47                 if (n <= ushort.MaxValue)
48                 {
49                     // ushort flag
50                     prefix = 0xfd;
51                     valueBytes = BitConverter.GetBytes((ushort)n);
52                 }
53                 else if (n <= uint.MaxValue)
54                 {
55                     // uint flag
56                     prefix = 0xfe;
57                     valueBytes = BitConverter.GetBytes((uint)n);
58                 }
59                 else
60                 {
61                     // ulong flag
62                     prefix = 0xff;
63                     valueBytes = BitConverter.GetBytes(n);
64                 }
65
66                 resultBytes.Add(prefix);
67                 resultBytes.AddRange(valueBytes);
68             }
69
70             return resultBytes.ToArray();
71         }
72
73         /// <summary>
74         /// Encodes integer value into compact representation.
75         /// 
76         /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
77         /// </summary>
78         /// <param name="n">Integer value</param>
79         /// <returns>Byte sequence</returns>
80         public static byte[] EncodeVarInt(long n)
81         {
82             return EncodeVarInt((ulong)n);
83         }
84
85         public static int GetEncodedSize(long n)
86         {
87             if (n <= 0xfc)
88             {
89                 return 1;
90             }
91             else if (n <= ushort.MaxValue)
92             {
93                 return 3;
94             }
95             else if (n <= uint.MaxValue)
96             {
97                 return 5;
98             }
99             else
100             {
101                 return 9;
102             }
103         }
104
105         /// <summary>
106         /// Decodes integer value from compact representation
107         /// 
108         /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
109         /// </summary>
110         /// <param name="bytes">Byte sequence</param>
111         /// <returns>Integer value</returns>
112         public static ulong DecodeVarInt(byte[] bytes)
113         {
114             var prefix = bytes[0];
115             var bytesArray = new byte[bytes.Length - 1];
116
117             bytes.CopyTo(bytesArray, 1);  // Get rid of prefix
118
119             switch (prefix)
120             {
121                 case 0xfd: // ushort flag
122                     return BitConverter.ToUInt16(bytesArray, 0);
123                 case 0xfe: // uint flag
124                     return BitConverter.ToUInt32(bytesArray, 0);
125                 case 0xff: // ulong flag
126                     return BitConverter.ToUInt64(bytesArray, 0);
127                 default:
128                     return prefix;
129             }
130         }
131     }
132 }