#pragma once #include #include #include "data.hpp" #include "stream_value.hpp" namespace saw { namespace encode { struct Csv {}; } namespace impl { template struct csv_encode { static_assert(always_false, "Case not supported"); }; template struct csv_encode, FromDecode> { static_assert(Dim == 1, "Only one dimension is allowed."); static_assert(!is_array::value, "Array of an array is not allowed."); static_assert(is_tuple::value || is_struct::value, "Only struct or tuples allowed inside a csv array"); using Schema = schema::Array; static error_or encode(const data& from, buffer& to){ if constexpr (is_struct::value){ auto eov = csv_encode::encode_header(to); if(eov.is_error()){ return eov; } } for(std::size_t i = 0; i < from.size(); ++i){ auto eov = csv_encode::encode(from.at(i), to); if(eov.is_error()){ return eov; } } return void_t{}; } }; template struct csv_encode...>, FromDecode> { using Schema = schema::Struct...>; template static error_or encode_header_i(buffer& to){ // Encode string // constexpr auto str_view = parameter_key_pack_type::literal; for(auto& iter : str_view.view()){ auto eov = stream_value::encode(iter, to); if(eov.is_error()){ return eov; } } // Go to next string if constexpr ( (i+1) < sizeof...(K)){ /** * Replace this with col separator */ constexpr std::string_view lit = ","; for(int8_t iter : lit){ auto eov = stream_value::encode(iter, to); if(eov.is_error()){ return eov; } } return encode_header_i(to); } { /** * Replace this with row separator */ constexpr std::string_view lit = "\r\n"; for(int8_t iter : lit){ auto eov = stream_value::encode(iter, to); if ( eov.is_error()){ return eov; } } } return make_void(); } static error_or encode_header(buffer& to){ return encode_header_i<0>(to); } template static error_or encode_i(const data& from, buffer& to){ constexpr auto str_view = parameter_key_pack_type::literal; { auto eov = csv_encode::type, FromDecode>::encode(from.template get(), to); if(eov.is_error()){ return eov; } } if constexpr ( (i+1) < sizeof...(K)){ /** * Replace this with col separator */ constexpr std::string_view lit = ","; for(int8_t iter : lit){ auto eov = stream_value::encode(iter, to); if(eov.is_error()){ return eov; } } return encode_i(from, to); } { /** * Replace this with row separator */ constexpr std::string_view lit = "\r\n"; for(int8_t iter : lit){ auto eov = stream_value::encode(iter, to); if ( eov.is_error()){ return eov; } } } return make_void(); } static error_or encode(const data& from, buffer& to){ return encode_i<0>(from, to); } }; template struct csv_encode { using Schema = schema::String; static error_or encode(const data& from, buffer& to){ for(size_t i = 0; i < from.size(); ++i){ auto eov = stream_value::encode(from.at(i), to); if(eov.is_error()){ return eov; } } return make_void(); } }; template struct csv_encode, FromDecode> { using Schema = schema::Primitive; static error_or encode(const data& from, buffer& to){ std::string to_str; try { to_str = std::to_string(from.get()); }catch(const std::exception& ){ return make_error(); } for(auto iter : to_str){ auto eov = stream_value::encode(iter, to); if(eov.is_error()){ return eov; } } return make_void(); } }; } template class data { private: ring_buffer buffer_; public: data() = default; buffer& get_buffer(){ return buffer_; } }; template class codec { static_assert(is_array::value, "Only an Array is allowed as a base value"); public: template static error_or encode(const data& from, data& to){ buffer_view buff_v{to.get_buffer()}; auto eov = impl::csv_encode::encode(from, buff_v); if(eov.is_error()){ return eov; } to.get_buffer().write_advance(buff_v.write_offset()); return eov; } template static error_or decode(data& from, data& to){ return make_error(); } }; }