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