forked from renmengye/base62-csharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
EncodingExtensions.cs
113 lines (104 loc) · 4.3 KB
/
EncodingExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
using System;
using System.IO;
using System.Text;
namespace Base62
{
public static class EncodingExtensions
{
private static string Base62CodingSpace = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/// <summary>
/// Convert a byte array
/// </summary>
/// <param name="original">Byte array</param>
/// <returns>Base62 string</returns>
public static string ToBase62(this byte[] original)
{
StringBuilder sb = new StringBuilder();
BitStream stream = new BitStream(original); // Set up the BitStream
byte[] read = new byte[1]; // Only read 6-bit at a time
while (true)
{
read[0] = 0;
int length = stream.Read(read, 0, 6); // Try to read 6 bits
if (length == 6) // Not reaching the end
{
if ((int)(read[0] >> 3) == 0x1f) // First 5-bit is 11111
{
sb.Append(Base62CodingSpace[61]);
stream.Seek(-1, SeekOrigin.Current); // Leave the 6th bit to next group
}
else if ((int)(read[0] >> 3) == 0x1e) // First 5-bit is 11110
{
sb.Append(Base62CodingSpace[60]);
stream.Seek(-1, SeekOrigin.Current);
}
else // Encode 6-bit
{
sb.Append(Base62CodingSpace[(int)(read[0] >> 2)]);
}
}
else if (length == 0) // Reached the end completely
{
break;
}
else // Reached the end with some bits left
{
// Padding 0s to make the last bits to 6 bit
sb.Append(Base62CodingSpace[(int)(read[0] >> (int)(8 - length))]);
break;
}
}
return sb.ToString();
}
/// <summary>
/// Convert a Base62 string to byte array
/// </summary>
/// <param name="base62">Base62 string</param>
/// <returns>Byte array</returns>
public static byte[] FromBase62(this string base62)
{
// Character count
int count = 0;
// Set up the BitStream
BitStream stream = new BitStream(base62.Length * 6 / 8);
foreach (char c in base62)
{
// Look up coding table
int index = Base62CodingSpace.IndexOf(c);
// If end is reached
if (count == base62.Length - 1)
{
// Check if the ending is good
int mod = (int)(stream.Position % 8);
if (mod == 0)
throw new InvalidDataException("an extra character was found");
if ((index >> (8 - mod)) > 0)
throw new InvalidDataException("invalid ending character was found");
stream.Write(new byte[] { (byte)(index << mod) }, 0, 8 - mod);
}
else
{
// If 60 or 61 then only write 5 bits to the stream, otherwise 6 bits.
if (index == 60)
{
stream.Write(new byte[] { 0xf0 }, 0, 5);
}
else if (index == 61)
{
stream.Write(new byte[] { 0xf8 }, 0, 5);
}
else
{
stream.Write(new byte[] { (byte)index }, 2, 6);
}
}
count++;
}
// Dump out the bytes
byte[] result = new byte[stream.Position / 8];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(result, 0, result.Length * 8);
return result;
}
}
}