blob: da72de1ebcc8306cff032d80ca1db2ee2a76c605 (
plain)
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
|
#include "common.hh"
#include "base64.hh"
namespace stuff {
namespace {
int8_t value(char c) {
if (c >= 'A' && c <= 'Z') {
return c - 'A';
}
if (c >= 'a' && c <= 'z') {
return 26 + c - 'a';
}
if (c >= '0' && c <= '9') {
return 52 + c - '0';
}
if (c == '+' || c == '-') {
return 62;
}
if (c == '/' || c == '_') {
return 63;
}
return -1;
}
bool decode_one(const int8_t buf[4], std::string* output) {
if (buf[1] == -1 || buf[0] == -1) {
// There is no reason for the first or the second char to be
// padding
return false;
}
output->push_back((buf[0] << 2) | (buf[1] >> 4));
if (buf[2] == -1) {
return buf[3] == -1; // No padding between non-padding
}
output->push_back(((buf[1] & 0xf) << 4) | (buf[2] >> 2));
if (buf[3] == -1) return true;
output->push_back(((buf[2] & 0x3) << 6) | buf[3]);
return true;
}
} // namespace
bool Base64::decode(const std::string& input, std::string* output) {
int8_t buf[4];
size_t fill = 0;
bool done = false;
output->clear();
for (auto it = input.begin(); it != input.end(); ++it) {
buf[fill] = value(*it);
if (buf[fill] != -1 || *it == '=') {
if (done) return false; // crap after padding
if (++fill == 4) {
if (!decode_one(buf, output)) return false;
done = buf[3] == -1;
fill = 0;
}
}
}
if (fill != 0) {
while (fill < 4) buf[fill] = -1;
if (!decode_one(buf, output)) return false;
}
return true;
}
} // namespace stuff
|