diff options
-rw-r--r-- | modules/codec/c++/base64.hpp | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/modules/codec/c++/base64.hpp b/modules/codec/c++/base64.hpp index 4c9ae18..56ba79e 100644 --- a/modules/codec/c++/base64.hpp +++ b/modules/codec/c++/base64.hpp @@ -40,7 +40,7 @@ public: }; namespace impl { -constexpr char base64_char_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +constexpr std::string_view base64_char_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; } template<> @@ -48,6 +48,23 @@ class codec<schema::String, encode::Base64> { public: using Schema = schema::String; private: + bool is_base64(char a) const { + for(auto iter : impl::base64_char_map){ + if(iter == a){ + return true; + } + } + return false; + } + + error_or<uint8_t> find_base64_char_pos(char a) const { + for(uint8_t i = 0; i < impl::base64_char_map.size(); ++i){ + if(impl::base64_char_map.at(i) == a){ + return i; + } + } + return make_error<err::not_found>("Didn't find base64 char"); + } public: template<typename FromEncode> static error_or<void> encode(const data<Schema, FromEncode>& from, data<Schema,encode::Base64>& to){ @@ -68,10 +85,10 @@ public: 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)]; + b64_str.at(k) = impl::base64_char_map.at((s[0u] & 0xFC) >> 2); + b64_str.at(k+1u) = impl::base64_char_map.at(((s[0u] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)); + b64_str.at(k+2u) = impl::base64_char_map.at(((s[1u] & 0x0F) << 2) | ((s[2] & 0xC0) >> 6)); + b64_str.at(k+3u) = impl::base64_char_map.at((s[2u] & 0x3F)); j = 0u; k+=4u; } @@ -82,14 +99,14 @@ public: 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)]; + b64_str.at(k+0u) = impl::base64_char_map.at((s[0u] & 0xFC) >> 2); + b64_str.at(k+1u) = impl::base64_char_map.at(((s[0u] & 0x03)<<4) + ((s[1u]&0xF0)>>4)); if(j == 2u){ - b64_str[k+2u] = impl::base64_char_map[ ((s[1u]&0x0F)<<2) ]; + b64_str.at(k+2u) = impl::base64_char_map.at( ((s[1u]&0x0F)<<2) ); }else { - b64_str[k+2u] = '='; + b64_str.at(k+2u) = '='; } - b64_str[k+3u] = '='; + b64_str.at(k+3u) = '='; } to = {std::move(b64_str)}; @@ -98,41 +115,39 @@ public: template<typename ToDecode> static error_or<void> decode(data<Schema,encode::Base64>& from, data<Schema, ToDecode>& to){ - return make_error<err::not_implemented>(); - /* uint64_t b64_len = from.size(); if((b64_len % 4) != 0){ - return make_error<err::invalid_state>("B64 is not padded"); + return make_error<err::invalid_state>("Base64 String is not padded"); } - uint64_t section_len = b64_len / 4u; + uint64_t j{0u}; + std::array<uint8_t,3> s{}; + std::array<uint8_t,4> t{}; std::string to_str; - for(uint64_t i = 0u; i < section_len; ++i){ - uint64_t j = 4u*i; - - std::array<char,3> to_bits{0,0,0}; - std::array<char,4> from_bits{ - from.at(j).get(), - from.at(j+1u).get(), - from.at(j+2u).get(), - from.at(j+3u).get() - }; - - for(char iter : from_bits){ - if(!is_base64(iter)){ - return make_error<err::invalid_state>("Not a base64 char"); - } + for(uint64_t i = 0u; i < b64_len && from.at(i) != '='; ++i){ + auto eo_pos = find_base64_char_pos(from.at(i)); + if(eo_pos.is_error()){ + return std::move(eo_pos.get_error()); + } + t[j] = eo_pos.get_value(); + + ++j; + if(j == 4u){ + s[0u] = (t[0u] << 2) + ((t[1] & 0x30) >> 4); + s[1u] = ((s[1u] & 0x0F) << 4) + ((s[2u] & 0x3c) >> 2); + s[2u] = ((s[2u] & 0x03) << 6) + s[3u]; + + to_str += s[0u]; + to_str += s[1u]; + to_str += s[2u]; + + j = 0u; } - - to_bits[0] = char_array } to = {std::move(to_str)}; - - return saw::make_void(); - */ + return make_void(); } - }; } |