diff options
author | Claudius Holeksa <mail@keldu.de> | 2023-06-27 19:16:46 +0200 |
---|---|---|
committer | Claudius Holeksa <mail@keldu.de> | 2023-06-27 19:16:46 +0200 |
commit | 0bd38cdec70c3a07467fccd81b570b754996eb95 (patch) | |
tree | e45adfb584cb0a5a1650be164751cb74e5f7c7b8 /src/codec-json | |
parent | 5688c721c610e2a8931d6ec6f84dee2d4d65c763 (diff) |
c++,codec-json,codec: Working on fixes for JSON Array decoding. Test
failing currently
Diffstat (limited to 'src/codec-json')
-rw-r--r-- | src/codec-json/json.tmpl.h | 147 |
1 files changed, 141 insertions, 6 deletions
diff --git a/src/codec-json/json.tmpl.h b/src/codec-json/json.tmpl.h index 063595d..4f4d6f4 100644 --- a/src/codec-json/json.tmpl.h +++ b/src/codec-json/json.tmpl.h @@ -1,6 +1,7 @@ #pragma once #include <charconv> +#include <sstream> namespace saw { namespace impl { @@ -387,30 +388,164 @@ struct json_decode<schema::Primitive<T,N>, RootSchema, ToDecode> { } }; +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: + iss<<buff.read(); + break; + } + buff.read_advance(1); + } + + std::string raw = iss.str(); + to.set(std::move(raw)); + + return void_t{}; + } +}; + +// The whole std::vector approach is hacky af 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_level(buffer_view& buff, data<schema::Array<T,D>, ToDecode>& to, std::array<std::size_t, D>& index){ + 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) { - auto eov = json_decode<T, RootSchema, ToDecode>::decode(buff, to.at(index)); + json_helper::skip_whitespace(buff); + to.push_back({}); + 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); - if( buff.read_composite_length() == 0 ){ - return make_error<err::buffer_exhausted>(); - } 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(const 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 ){ + to.at(index) = flat.at(flat_index); + ++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; + } + } + } + } + static error_or<void> decode(buffer_view& buff, data<schema::Array<T,D>, ToDecode>& to){ std::array<std::size_t, D> index; - return decode_level<0>(buff, to, 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); } }; } |