-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathbase.cpp
145 lines (123 loc) · 2.85 KB
/
base.cpp
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "base.h"
#define B64DIGITS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
std::string b64_encode(const bytes& in, bool padded) {
std::string out;
out.reserve(4 + (4*in.size()/3));
int val = 0;
int bits = 0;
for (auto c : in) {
val = (val << 8) + c;
bits += 8;
while (bits >= 6) {
out.push_back(B64DIGITS[(val>>(bits-6))&0x3F]);
bits -= 6;
}
}
if (bits > 0)
out.push_back(B64DIGITS[(val<<(6-bits))&0x3F]);
while (padded && out.size() % 4)
out.push_back('=');
return out;
}
std::vector<int> decode64_digits() {
std::vector<int> table(256, -1);
for (int i=0; i<64; i++)
table[B64DIGITS[i]] = i;
return table;
}
bytes b64_decode(const std::string &in) {
static std::vector<int> dd = decode64_digits();
bytes out;
out.reserve(3*in.size()/4);
int val = 0;
int bits = 0;
for (auto c : in) {
if (dd[c] == -1) // bail on any non-b64 digit
break;
val = (val << 6) + dd[c];
bits += 6;
if (bits >= 8) {
out.push_back(char((val>>(bits-8))&0xFF));
bits -= 8;
}
}
return out;
}
// Surely I should write an implementation that avoids the almost
// cutnpaste job here.
#define B32DIGITS "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
std::string b32_encode(const bytes& in) {
std::string out;
out.reserve(8 + (8*in.size()/5));
int val = 0;
int bits = 0;
for (auto c : in) {
val = (val << 8) + c;
bits += 8;
while (bits >= 5) {
out.push_back(B32DIGITS[(val>>(bits-5))&0x1F]);
bits -= 5;
}
}
if (bits > 0)
out.push_back(B32DIGITS[(val<<(5-bits))&0x1F]);
return out;
}
std::vector<int> decode32_digits() {
std::vector<int> table(256, -1);
for (int i=0; i<32; i++)
table[B32DIGITS[i]] = i;
return table;
}
bytes b32_decode(const std::string &in) {
static std::vector<int> dd = decode32_digits();
bytes out;
out.reserve(5*in.size()/8);
int val = 0;
int bits = 0;
for (auto c : in) {
if (dd[c] == -1) // bail on any non-b32 digit
break;
val = (val << 5) + dd[c];
bits += 5;
if (bits >= 8) {
out.push_back(char((val>>(bits-8))&0xFF));
bits -= 8;
}
}
return out;
}
std::vector<uint16_t> b2048_encode(const bytes& in) {
std::vector<uint16_t> out;
out.reserve(1+8*in.size()/11);
unsigned val = 0;
int bits = 0;
for (auto b : in) {
val |= (b << bits);
bits += 8;
if (bits >= 11) {
out.push_back(val & 0x7FF);
val >>= 11;
bits -= 11;
}
}
if (bits > 0)
out.push_back(val & 0x7FF);
return out;
}
bytes b2048_decode(const std::vector<uint16_t> &in) {
bytes out;
out.reserve(1+11*in.size()/8);
int val = 0;
int bits = 0;
for (auto i : in) {
val |= (i << bits);
bits += 11;
while (bits >= 8) {
out.push_back(val & 0xFF);
val >>= 8;
bits -= 8;
}
}
return out;
}