diff options
Diffstat (limited to 'src/codec-json')
-rw-r--r-- | src/codec-json/.nix/derivation.nix | 32 | ||||
-rw-r--r-- | src/codec-json/SConscript | 38 | ||||
-rw-r--r-- | src/codec-json/SConstruct | 66 | ||||
-rw-r--r-- | src/codec-json/json.h | 116 | ||||
-rw-r--r-- | src/codec-json/json.tmpl.h | 734 |
5 files changed, 0 insertions, 986 deletions
diff --git a/src/codec-json/.nix/derivation.nix b/src/codec-json/.nix/derivation.nix deleted file mode 100644 index 0f701c9..0000000 --- a/src/codec-json/.nix/derivation.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ lib -, stdenvNoCC -, scons -, clang -, clang-tools -, version -, forstio -}: - -let - -in stdenvNoCC.mkDerivation { - pname = "forstio-codec-json"; - inherit version; - src = ./..; - - enableParallelBuilding = true; - - nativeBuildInputs = [ - scons - clang - clang-tools - ]; - - buildInputs = [ - forstio.core - forstio.async - forstio.codec - ]; - - outputs = ["out" "dev"]; -} diff --git a/src/codec-json/SConscript b/src/codec-json/SConscript deleted file mode 100644 index 772ac0b..0000000 --- a/src/codec-json/SConscript +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/false - -import os -import os.path -import glob - - -Import('env') - -dir_path = Dir('.').abspath - -# Environment for base library -codec_json_env = env.Clone(); - -codec_json_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) -codec_json_env.headers = sorted(glob.glob(dir_path + "/*.h")) - -env.sources += codec_json_env.sources; -env.headers += codec_json_env.headers; - -## Shared lib -objects_shared = [] -codec_json_env.add_source_files(objects_shared, codec_json_env.sources, shared=True); -codec_json_env.library_shared = codec_json_env.SharedLibrary('#build/forstio-codec-json', [objects_shared]); - -## Static lib -objects_static = [] -codec_json_env.add_source_files(objects_static, codec_json_env.sources, shared=False); -codec_json_env.library_static = codec_json_env.StaticLibrary('#build/forstio-codec-json', [objects_static]); - -# Set Alias -env.Alias('library_codec_json', [codec_json_env.library_shared, codec_json_env.library_static]); - -env.targets += ['library_codec_json']; - -# Install -env.Install('$prefix/lib/', [codec_json_env.library_shared, codec_json_env.library_static]); -env.Install('$prefix/include/forstio/codec/json/', [codec_json_env.headers]); diff --git a/src/codec-json/SConstruct b/src/codec-json/SConstruct deleted file mode 100644 index edd5f57..0000000 --- a/src/codec-json/SConstruct +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import os.path -import glob -import re - - -if sys.version_info < (3,): - def isbasestring(s): - return isinstance(s,basestring) -else: - def isbasestring(s): - return isinstance(s, (str,bytes)) - -def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): - - if isbasestring(filetype): - dir_path = self.Dir('.').abspath - filetype = sorted(glob.glob(dir_path+"/"+filetype)) - - for path in filetype: - target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) - if shared: - target_name+='.os' - sources.append( self.SharedObject( target=target_name, source=path ) ) - else: - target_name+='.o' - sources.append( self.StaticObject( target=target_name, source=path ) ) - pass - -def isAbsolutePath(key, dirname, env): - assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) - -env_vars = Variables( - args=ARGUMENTS -) - -env_vars.Add('prefix', - help='Installation target location of build results and headers', - default='/usr/local/', - validator=isAbsolutePath -) - -env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], - CPPDEFINES=['SAW_UNIX'], - CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], - LIBS=['forstio-codec']) -env.__class__.add_source_files = add_kel_source_files -env.Tool('compilation_db'); -env.cdb = env.CompilationDatabase('compile_commands.json'); - -env.objects = []; -env.sources = []; -env.headers = []; -env.targets = []; - -Export('env') -SConscript('SConscript') - -env.Alias('cdb', env.cdb); -env.Alias('all', [env.targets]); -env.Default('all'); - -env.Alias('install', '$prefix') diff --git a/src/codec-json/json.h b/src/codec-json/json.h deleted file mode 100644 index 1fe6bb5..0000000 --- a/src/codec-json/json.h +++ /dev/null @@ -1,116 +0,0 @@ -#pragma once - -#include <forstio/core/buffer.h> -#include <forstio/core/common.h> -#include <forstio/codec/data.h> - -#include <algorithm> - -namespace saw { -namespace encode { -struct Json {}; -} - -template<typename Schema> -class data<Schema, encode::Json> { -private: - ring_buffer buffer_; -public: - data():buffer_{}{} - - data(std::size_t ring_size_):buffer_{ring_size_}{} - - data(const std::string_view& view__): - buffer_{view__.size()} - { - auto ptr = reinterpret_cast<const uint8_t*>(view__.data()); - if(!ptr){ - return; - } - buffer_.push(*ptr, view__.size()); - } - - buffer& get_buffer(){ - return buffer_; - } - - const buffer& get_buffer() const { - return buffer_; - } - - error push(uint8_t val){ - return buffer_.push(val); - } - - std::size_t get_size() const { - return buffer_.read_composite_length(); - } - - uint8_t& at(std::size_t i){ - return buffer_.read(i); - } - - const uint8_t& at(std::size_t i) const { - return buffer_.read(i); - } -}; -} - -#include "json.tmpl.h" - -namespace saw { - -/** - * Codec class for json - */ -template<typename Schema> -class codec<Schema, encode::Json> { -public: - struct config { - size_t depth = 16; - size_t length = 1024; - }; -private: - config cfg_; -public: - /** - * Default constructor - */ - codec(){} - - /** - * Constructor - */ - codec(config cfg__):cfg_{std::move(cfg__)}{} - - SAW_FORBID_COPY(codec); - SAW_DEFAULT_MOVE(codec); - - template <typename FromEncoding> - error_or<void> encode(const data<Schema, FromEncoding>& from_encode, data<Schema, encode::Json>& to_encode){ - // To Be encoded - buffer_view buff_v{to_encode.get_buffer()}; - auto eov = impl::json_encode<Schema, Schema, FromEncoding>::encode(from_encode, buff_v); - if(eov.is_error()){ - return std::move(eov.get_error()); - } - to_encode.get_buffer().write_advance(buff_v.write_offset()); - - return void_t{}; - } - - template <typename ToEncoding> - error_or<void> decode(data<Schema, encode::Json>& from_decode, data<Schema, ToEncoding>& to_decode){ - buffer_view buff_v{from_decode.get_buffer()}; - - auto eov = impl::json_decode<Schema, Schema, ToEncoding>::decode(buff_v, to_decode); - if(eov.is_error()){ - return std::move(eov.get_error()); - } - from_decode.get_buffer().read_advance(buff_v.read_offset()); - - return void_t {}; - } -}; -} - diff --git a/src/codec-json/json.tmpl.h b/src/codec-json/json.tmpl.h deleted file mode 100644 index 4b3a1a2..0000000 --- a/src/codec-json/json.tmpl.h +++ /dev/null @@ -1,734 +0,0 @@ -#pragma once - -#include <charconv> -#include <sstream> - -#include <iostream> - -namespace saw { -namespace impl { -template<typename Schema, typename RootSchema, typename FromEncode> -class json_encode { - static_assert(always_false<Schema, RootSchema, FromEncode>, "This schema type is not being handled by the json encoding."); -}; - -template<typename T, size_t N, typename RootSchema, typename FromEncode> -struct json_encode<schema::Primitive<T,N>, RootSchema, FromEncode> { - static error_or<void> encode(const data<schema::Primitive<T,N>, FromEncode>& from, buffer& to) { - auto val = from.get(); - std::array<uint8_t, 256> data; - auto tc_result = std::to_chars(reinterpret_cast<char*>(data.data()), reinterpret_cast<char*>(data.data())+data.size(), val); - - if(tc_result.ec != std::errc{}){ - return make_error<err::critical>(); - } - - size_t bytes_written = 0; - for(char* ptr = reinterpret_cast<char*>(data.data()); ptr != tc_result.ptr; ++ptr){ - ++bytes_written; - } - - auto& buff = to; - error err = buff.write_require_length(bytes_written); - if(!err.template is_type<err::no_error>()){ - return std::move(err); - } - - for(char* ptr = reinterpret_cast<char*>(data.data()); ptr != tc_result.ptr; ++ptr){ - uint8_t* un_ptr = reinterpret_cast<uint8_t*>(ptr); - buff.push(un_ptr[0]); - } - - return void_t{}; - } -}; - -template<typename RootSchema, typename FromEncode> -struct json_encode<schema::String, RootSchema, FromEncode> { - static error_or<void> encode(const data<schema::String, FromEncode>& from, buffer& to) { - { - auto err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - for(std::size_t i = 0; i < from.size(); ++i){ - auto err = to.push(from.get_at(i)); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - { - auto err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - - return void_t{}; - } -}; - -template<typename... T, typename RootSchema, typename FromEncode> -struct json_encode<schema::Tuple<T...>, RootSchema, FromEncode> { - template<size_t i> - static error_or<void> encode_element(const data<schema::Tuple<T...>, FromEncode>& from, buffer& to){ - auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<i>(), to); - - if(eov.is_error()){ - return eov; - } - - if constexpr ( (i+1) < sizeof...(T)){ - { - auto eov_ele = to.push(','); - if(!eov_ele.template is_type<err::no_error>()){ - return eov_ele; - } - } - { - auto eov_ele = encode_element<i+1>(from, to); - if(eov_ele.is_error()){ - return eov_ele; - } - } - - - } - return void_t{}; - } - - static error_or<void> encode(const data<schema::Tuple<T...>, FromEncode>& from, buffer& to) { - { - auto err = to.push('['); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - if constexpr ( sizeof...(T) > 0 ){ - auto eov = encode_element<0>(from, to); - if(eov.is_error()){ - return eov; - } - } - { - auto err = to.push(']'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - - return void_t{}; - } -}; - -template<typename T, size_t D, typename RootSchema, typename FromEncode> -struct json_encode<schema::Array<T,D>, RootSchema, FromEncode> { - template<size_t Level> - static error_or<void> encode_level(const data<schema::Array<T,D>, FromEncode>& from, buffer& to, std::array<std::size_t, D>& index){ - if constexpr (Level == D){ - auto eov = json_encode<T, RootSchema, FromEncode>::encode(from.at(index), to); - if(eov.is_error()){ - return eov; - } - } else { - { - auto err = to.push('['); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - for(std::size_t i = 0; i < from.get_dim_size(Level); ++i){ - if( i > 0 ){ - auto err = to.push(','); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - { - index[Level] = i; - auto eov = encode_level<Level+1>(from, to, index); - if(eov.is_error()){ - return eov; - } - } - } - { - auto err = to.push(']'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - } - return void_t{}; - } - - static error_or<void> encode(const data<schema::Array<T,D>, FromEncode>& from, buffer& to) { - std::array<std::size_t, D> index; - return encode_level<0>(from, to, index); - } -}; - -template<typename... T, string_literal... Key, typename RootSchema, typename FromEncode> -struct json_encode<schema::Struct<schema::Member<T,Key>...>, RootSchema, FromEncode> { - - template<size_t i> - static error_or<void> encode_element(const data<schema::Struct<schema::Member<T,Key>...>, FromEncode>& from, buffer& to){ - // Encode the name - { - std::string_view view = parameter_key_pack_type<i, Key...>::literal.view(); - error err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - err = to.push(*reinterpret_cast<const uint8_t *>(view.data()), view.size()); - if(!err.template is_type<err::no_error>()){ - return err; - } - err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - // Add the separator - { - auto eov_ele = to.push(':'); - if(!eov_ele.template is_type<err::no_error>()){ - return eov_ele; - } - } - - // Encode the value - auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to); - - // Go to the next element - if constexpr ( (i+1) < sizeof...(T)){ - { - auto eov_ele = to.push(','); - if(!eov_ele.template is_type<err::no_error>()){ - return eov_ele; - } - } - { - auto eov_ele = encode_element<i+1>(from, to); - if(eov_ele.is_error()){ - return eov_ele; - } - } - - - } - - return void_t{}; - } - static error_or<void> encode(const data<schema::Struct<schema::Member<T,Key>...>, FromEncode>& from, buffer& to) { - { - auto err = to.push('{'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - if constexpr ( sizeof...(T) > 0 ){ - auto eov = encode_element<0>(from, to); - if(eov.is_error()){ - return eov; - } - } - { - auto err = to.push('}'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - - return void_t{}; - } -}; - -template<typename... T, string_literal... Key, typename RootSchema, typename FromEncode> -struct json_encode<schema::Union<schema::Member<T,Key>...>, RootSchema, FromEncode> { - - template<size_t i> - static error_or<void> encode_element(const data<schema::Union<schema::Member<T,Key>...>, FromEncode>& from, buffer& to){ - if(from.template holds_alternative<typename parameter_key_pack_type<i, Key...>::literal>()){ - // Encode the name - { - std::string_view view = parameter_key_pack_type<i, Key...>::literal.view(); - error err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - err = to.push(*reinterpret_cast<const uint8_t *>(view.data()), view.size()); - if(!err.template is_type<err::no_error>()){ - return err; - } - err = to.push('"'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - // Add the separator - { - auto eov_ele = to.push(':'); - if(!eov_ele.template is_type<err::no_error>()){ - return eov_ele; - } - } - - // Encode the value - auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to); - } - // Go to the next element - if constexpr ( (i+1) < sizeof...(T)){ - { - auto eov_ele = encode_element<i+1>(from, to); - if(eov_ele.is_error()){ - return eov_ele; - } - } - - - } - - return void_t{}; - } - static error_or<void> encode(const data<schema::Union<schema::Member<T,Key>...>, FromEncode>& from, buffer& to) { - { - auto err = to.push('{'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - if constexpr ( sizeof...(T) > 0 ){ - auto eov = encode_element<0>(from, to); - if(eov.is_error()){ - return eov; - } - } - { - auto err = to.push('}'); - if(!err.template is_type<err::no_error>()){ - return err; - } - } - - return void_t{}; - } -}; - -struct json_helper { - static bool is_whitespace(int8_t ch) { - return ch == '\t' || ch == ' ' || ch == '\r' || ch == '\n'; - } - - static void skip_whitespace(buffer_view& buff) { - while(buff.read_composite_length() > 0 && json_helper::is_whitespace(buff.read())) { - buff.read_advance(1); - } - } -}; - -template<typename Schema, typename RootSchema, typename ToDecode> -struct json_decode; - -template<typename T, size_t N, typename RootSchema, typename ToDecode> -struct json_decode<schema::Primitive<T,N>, RootSchema, ToDecode> { - static error_or<void> decode(buffer_view& buff, data<schema::Primitive<T,N>, ToDecode>& to) { - assert( - ( buff.read() >= '0' && buff.read() <= '9') - || ( buff.read() == '+' || buff.read() == '-') - ); - - std::size_t offset = 0; - - if (buff.read() == '-'){ - ++offset; - } else if (buff.read() == '+'){ - return make_error<err::not_supported>(); - } - if (offset >= buff.read_composite_length()) { - return make_error<err::buffer_exhausted>(); - } - if (buff.read(offset) >= '1' && buff.read(offset) <= '9') { - ++offset; - - if(offset >= buff.read_composite_length()) { - return make_error<err::buffer_exhausted>(); - } - - while(1){ - if (buff.read(offset) >= '0' && buff.read(offset) <= '9') { - ++offset; - - if(offset >= buff.read_composite_length()) { - break; - } - continue; - } - break; - } - } else if (buff.read(offset) == '0' ) { - ++offset; - } else { - return make_error<err::buffer_exhausted>(); - } - - { - std::string_view num_view{reinterpret_cast<char*>(&buff.read()), offset}; - typename native_data_type<schema::Primitive<T,N>>::type result; - auto fc_result = std::from_chars(num_view.data(), num_view.data() + num_view.size(), result); - if(fc_result.ec != std::errc{}){ - return make_error<err::invalid_state>(); - } - - to.set(result); - } - buff.read_advance(offset); - - return void_t{}; - } -}; - -template<typename RootSchema, typename ToDecode> -struct json_decode<schema::String, RootSchema, ToDecode> { - static error_or<void> decode(buffer_view& buff, data<schema::String, ToDecode>& to){ - assert(buff.read() == '"'); - buff.read_advance(1); - - std::stringstream iss; - bool string_done = false; - while(!string_done){ - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - - switch(buff.read()){ - case '\\':{ - buff.read_advance(1); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - switch(buff.read()){ - case '\\': - case '/': - case '"': - iss<< buff.read(); - break; - case 'b': - iss<<'\b'; - break; - case 'f': - iss<<'\f'; - break; - case 'n': - iss<<'\n'; - break; - case 'r': - iss<<'\r'; - break; - case 't': - iss<<'\t'; - break; - case 'u': { - buff.read_advance(1); - if(buff.read_composite_length() < 4){ - return make_error<err::buffer_exhausted>(); - } - iss<<'?'; - iss<<'?'; - iss<<'?'; - iss<<'?'; - - buff.read_advance(3); - } break; - } - } break; - case '"': - string_done = true; - break; - default:{ - // Avoids Control sequences - if(buff.read() >= ' ' && buff.read() <= '~'){ - iss<<buff.read(); - } - // Avoid Unicode - else if (buff.read() < 0) { - do { - buff.read_advance(1); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - } while( buff.read() < 0 ); - iss<<'?'; - } - break; - } - } - buff.read_advance(1); - } - - std::string raw = iss.str(); - to.set(std::move(raw)); - - return void_t{}; - } -}; - -template<typename... T, string_literal... Lits, typename RootSchema, typename ToDecode> -struct json_decode<schema::Struct<schema::Member<T,Lits>...>, RootSchema, ToDecode> { - template<std::size_t i> - static error_or<void> decode_field_search(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to, std::array<bool, sizeof...(T)>& fields, const data<schema::String,ToDecode>& search_name){ - if constexpr ( i < sizeof...(T)){ - using Type = typename parameter_pack_type<i, T...>::type; - constexpr static string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; - if(search_name == Literal.view()){ - if(fields[i]){ - return make_error<err::invalid_state>(); - } - fields[i] = true; - auto eov = json_decode<Type, RootSchema, ToDecode>::decode(buff, to.template get<Literal>()); - if(eov.is_error()){ - return eov; - } - }else { - decode_field_search<i+1>(buff, to, fields, search_name); - } - }else { - return make_error<err::invalid_state>(); - } - return void_t{}; - } - - static error_or<void> decode_fields(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to, std::array<bool, sizeof...(T)>& fields){ - for(;;){ - data<schema::String, ToDecode> name; - auto eov = json_decode<schema::String, RootSchema, ToDecode>::decode(buff, name); - if(eov.is_error()){ - return eov; - } - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - if(buff.read() != ':'){ - return make_error<err::invalid_state>(); - } - buff.read_advance(1); - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - { - auto eov = decode_field_search<0>(buff, to, fields, name); - if(eov.is_error()){ - return eov; - } - } - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - if(buff.read() == ','){ - buff.read_advance(1); - }else if(buff.read() == '}'){ - // If not all fields are set, the dataset is incomplete - for(auto& iter : fields){ - if(!iter){ - return make_error<err::invalid_state>(); - } - } - buff.read_advance(1); - return void_t{}; - }else{ - return make_error<err::invalid_state>(); - } - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - } - return void_t{}; - } - - static error_or<void> decode(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to){ - std::array<bool, sizeof...(T)> found_fields; - std::fill(found_fields.begin(), found_fields.end(), false); - - assert(buff.read() == '{'); - buff.read_advance(1); - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - - // Check if there are no elements present in the JSON Struct - if(buff.read() == '}'){ - if(sizeof...(T) > 0){ - return make_error<err::invalid_state>(); - } - buff.read_advance(1); - return void_t{}; - } - - auto eov = decode_fields(buff, to, found_fields); - if(eov.is_error()){ - return eov; - } - - return void_t{}; - } -}; - -template<typename... T, typename RootSchema, typename ToDecode> -struct json_decode<schema::Tuple<T...>, RootSchema, ToDecode> { - template<std::size_t i> - static error_or<void> decode_element(buffer_view& buff, data<schema::Tuple<T...>, ToDecode>& to){ - if constexpr (i < sizeof...(T)){ - if constexpr ( i > 0 ){ - if(buff.read() != ','){ - return make_error<err::invalid_state>(); - } - buff.read_advance(1); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - } - using Type = typename parameter_pack_type<i, T...>::type; - - auto eov = json_decode<Type, RootSchema, ToDecode>::decode(buff, to.template get<i>()); - if(eov.is_error()){ - return eov; - } - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - - eov = decode_element<i+1>(buff, to); - if(eov.is_error()){ - return eov; - } - }else{ - if(buff.read() != ']'){ - return make_error<err::invalid_state>(); - } - buff.read_advance(1); - } - return void_t{}; - } - - static error_or<void> decode(buffer_view& buff, data<schema::Tuple<T...>, ToDecode>& to){ - assert(buff.read() == '['); - buff.read_advance(1); - - json_helper::skip_whitespace(buff); - if(buff.read_composite_length() == 0){ - return make_error<err::buffer_exhausted>(); - } - - auto eov = decode_element<0>(buff, to); - if(eov.is_error()){ - return eov; - } - - return void_t{}; - } -}; - -// The whole std::vector approach is hacky af. ToDo change it maybe? -template<typename T, size_t D, typename RootSchema, typename ToDecode> -struct json_decode<schema::Array<T,D>, RootSchema, ToDecode> { - template<size_t Level> - static error_or<void> decode_flat_level(buffer_view& buff, std::vector<data<T, encode::Native>>& to, std::array<std::size_t, D>& index, std::array<std::size_t, D>& dims, bool log_dim){ - if constexpr (Level == D) { - json_helper::skip_whitespace(buff); - try { - to.push_back({}); - }catch(std::exception& e){ - return make_error<err::out_of_memory>(); - } - auto eov = json_decode<T, RootSchema, ToDecode>::decode(buff, to.back()); - if(eov.is_error()){ - return eov; - } - } else { - assert(buff.read() == '['); - buff.read_advance(1); - - json_helper::skip_whitespace(buff); - if ( buff.read_composite_length() == 0 ){ - return make_error<err::buffer_exhausted>(); - } - - index[Level] = 0; - for(;;){ - // We should have an element right now - auto eov = decode_flat_level<Level+1>(buff,to,index,dims, index[Level] == 0 && log_dim); - if(eov.is_error()){ - return eov; - } - json_helper::skip_whitespace(buff); - if ( buff.read_composite_length() == 0 ){ - return make_error<err::buffer_exhausted>(); - } - - ++index[Level]; - if(buff.read() == ','){ - buff.read_advance(1); - } else if(buff.read() == ']'){ - buff.read_advance(1); - break; - } else { - return make_error<err::invalid_state>(); - } - json_helper::skip_whitespace(buff); - if ( buff.read_composite_length() == 0 ){ - return make_error<err::buffer_exhausted>(); - } - } - if(log_dim){ - dims[Level] = index[Level]; - }else if (dims[Level] != index[Level]){ - return make_error<err::invalid_state>(); - } - } - return void_t{}; - } - - template<std::size_t Level> - static error_or<void> decode_unflat_level(std::vector<data<T,encode::Native>>& flat, data<schema::Array<T,D>, ToDecode>& to, std::array<std::size_t, D>& index, std::size_t& flat_index) { - if constexpr ( Level == D ){ - auto& flat_data = flat.at(flat_index); - to.at(index) = std::move(flat_data); - ++flat_index; - }else { - const std::size_t dim_size = to.get_dim_size(Level); - for(index[Level] = 0; index[Level] < dim_size; ++index[Level]){ - - auto eov = decode_unflat_level<Level+1>(flat, to, index, flat_index); - if(eov.is_error()){ - return eov; - } - } - } - return void_t{}; - } - - static error_or<void> decode(buffer_view& buff, data<schema::Array<T,D>, ToDecode>& to){ - std::array<std::size_t, D> index; - std::array<std::size_t, D> dims; - std::fill(dims.begin(), dims.end(), 0); - std::vector<data<T,encode::Native>> flat_array; - auto eov = decode_flat_level<0>(buff, flat_array, index, dims, true); - if(eov.is_error()){ - return eov; - } - - to = {dims}; - std::size_t flat_index = 0; - - return decode_unflat_level<0>(flat_array, to, index, flat_index); - } -}; -} -} |