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
|
#pragma once
namespace saw {
namespace encode {
struct Base64 {};
}
template<>
class data<schema::String, encode::Base64, storage::Default> {
public:
using Schema = schema::String;
private:
std::string data_;
public:
data() = default;
data(std::string data__):
data_{std::move(data__)}
{}
uint64_t size() const {
return data_.size();
}
char& at(uint64_t i){
return data_.at(i);
}
const char& at(uint64_t i) const {
return data_.at(i);
}
std::string stl_string() const {
return data_;
}
bool operator==(const data<Schema, encode::Base64>& rhs) const {
return data_ == rhs.data_;
}
};
namespace impl {
constexpr char base64_char_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
}
template<>
class codec<schema::String, encode::Base64> {
public:
using Schema = schema::String;
private:
public:
template<typename FromEncode>
static error_or<void> encode(const data<Schema, FromEncode>& from, data<Schema,encode::Base64>& to){
std::string b64_str;
try {
uint64_t unpadded_len = (from.size() * 4u + 2u) / 3u;
uint64_t padded_len = ( unpadded_len + 3u ) & ~3u;
b64_str.resize(padded_len);
}catch(const std::exception&){
return make_error<err::out_of_memory>();
}
uint64_t j{0u}, k{0u};
std::array<uint8_t,3> s{};
for(uint64_t i = 0u; i < from.size(); ++i){
s[j] = from.at(i);
++j;
if(j==3){
b64_str.at(k) = impl::base64_char_map[(s[0u] & 0xFC) >> 2];
b64_str.at(k+1u) = impl::base64_char_map[((s[0u] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)];
b64_str.at(k+2u) = impl::base64_char_map[((s[1u] & 0x0F) << 2) | ((s[2] & 0xC0) >> 6)];
b64_str.at(k+3u) = impl::base64_char_map[(s[2u] & 0x3F)];
j = 0u;
k+=4u;
}
}
if(j > 0){
if( j == 1u ){
s[1u] = 0u;
}
b64_str.at(k+0u) = impl::base64_char_map[(s[0u] & 0xFF) >> 2];
b64_str.at(k+1u) = impl::base64_char_map[((s[0u] & 0x03)<<4) + ((s[1u]&0xF0)>>4)];
if(j == 2u){
b64_str[k+2u] = impl::base64_char_map[ ((s[1u]&0x0F)<<2) ];
}else {
b64_str[k+2u] = '=';
}
b64_str[k+3u] = '=';
}
to = {std::move(b64_str)};
return void_t{};
}
template<typename ToDecode>
static error_or<void> decode(data<Schema,encode::Base64>& from, data<Schema, ToDecode>& to){
(void) to;
(void) from;
return make_error<err::not_implemented>();
}
};
}
|