diff options
Diffstat (limited to 'modules/codec/c++/base64.hpp')
-rw-r--r-- | modules/codec/c++/base64.hpp | 104 |
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>(); + } + +}; +} |