summaryrefslogtreecommitdiff
path: root/modules/codec
diff options
context:
space:
mode:
Diffstat (limited to 'modules/codec')
-rw-r--r--modules/codec/c++/base64.hpp104
-rw-r--r--modules/codec/c++/data.hpp7
-rw-r--r--modules/codec/tests/base64.cpp24
3 files changed, 132 insertions, 3 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>();
+ }
+
+};
+}
diff --git a/modules/codec/c++/data.hpp b/modules/codec/c++/data.hpp
index 8eff115..b3e4fe2 100644
--- a/modules/codec/c++/data.hpp
+++ b/modules/codec/c++/data.hpp
@@ -590,13 +590,14 @@ private:
std::string value_;
public:
data() = default;
+ data(uint64_t size__){
+ value_.resize(size__);
+ }
+
SAW_DEFAULT_COPY(data);
SAW_DEFAULT_MOVE(data);
data(std::string value__):value_{std::move(value__)}{}
- data(std::size_t size_){
- value_.resize(size_);
- }
/**
* Return the length of the string.
diff --git a/modules/codec/tests/base64.cpp b/modules/codec/tests/base64.cpp
new file mode 100644
index 0000000..7fb986b
--- /dev/null
+++ b/modules/codec/tests/base64.cpp
@@ -0,0 +1,24 @@
+#include <forstio/test/suite.hpp>
+#include "../c++/data.hpp"
+#include "../c++/base64.hpp"
+
+#include <iostream>
+namespace {
+namespace sch {
+using namespace saw::schema;
+}
+SAW_TEST("Codec Base64 Encode String"){
+ using namespace saw;
+
+ data<sch::String> inp_data{"Hello, World!"};
+
+ data<sch::String, encode::Base64> base64_str;
+
+ codec<sch::String, encode::Base64> base64_codec;
+
+ auto eov = base64_codec.encode(inp_data, base64_str);
+ SAW_EXPECT(eov.is_value(), "Couldn't encode data");
+
+ SAW_EXPECT((base64_str == data<sch::String, encode::Base64>{"SGVsbG8sIFdvcmxkIQ=="}), "Base64 not expected value");
+}
+}