summaryrefslogtreecommitdiff
path: root/modules/codec/c++/base64.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/codec/c++/base64.hpp')
-rw-r--r--modules/codec/c++/base64.hpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/modules/codec/c++/base64.hpp b/modules/codec/c++/base64.hpp
new file mode 100644
index 0000000..fcd2f75
--- /dev/null
+++ b/modules/codec/c++/base64.hpp
@@ -0,0 +1,104 @@
+#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);
+ }
+
+ 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>();
+ }
+
+};
+}