diff --git a/source/cpp/json.hh b/source/cpp/json.hh index 3bea149..6df45ab 100644 --- a/source/cpp/json.hh +++ b/source/cpp/json.hh @@ -415,6 +415,86 @@ void clear( T &value ) { json::clear(value); } template> bool empty( const T &value ) { return json::empty(value); } +// +// Deserialization of arrays +// + +template::value, int>::type = 0> +bool deserialize_array( T& container, protogen_X_Y_Z::istream& in, protogen_X_Y_Z::Parameters *params = nullptr ) +{ + protogen_X_Y_Z::json_context ctx; + if (params != nullptr) { + params->error.clear(); + ctx.params = *params; + } + protogen_X_Y_Z::tokenizer tok(in, ctx.params); + ctx.tok = &tok; + int result = json::read(ctx, container); + if (result == protogen_X_Y_Z::PGR_OK) return true; + if (params != nullptr) params->error = std::move(ctx.params.error); + return false; +} + +template::value, int>::type = 0> +bool deserialize_array( T& container, const std::string &in, Parameters *params = nullptr ) +{ + iterator_istream is(in.begin(), in.end()); + return deserialize_array(container, is, params); +} + +template::value, int>::type = 0> +bool deserialize_array( T& container, const char *in, size_t len, Parameters *params = nullptr ) +{ + auto begin = mem_iterator(in, len); + auto end = mem_iterator(in + len, 0); + iterator_istream> is(begin, end); + return deserialize_array(container, is, params); +} + +template::value, int>::type = 0> +bool deserialize_array( T& container, const std::vector &in, Parameters *params = nullptr ) +{ + iterator_istream::const_iterator> is(in.begin(), in.end()); + return deserialize_array(container, is, params); +} + +// +// Serialization of arrays +// + +template::value, int>::type = 0> +bool serialize_array( const T& container, protogen_X_Y_Z::ostream &out, protogen_X_Y_Z::Parameters *params = nullptr ) +{ + protogen_X_Y_Z::json_context ctx; + ctx.os = &out; + if (params != nullptr) { + params->error.clear(); + ctx.params = *params; + } + int result = json::write(ctx, container); + if (result == protogen_X_Y_Z::PGR_OK) return true; + if (params != nullptr) params->error = std::move(ctx.params.error); + return false; +} + +template::value, int>::type = 0> +bool serialize_array( const T& container, std::string &out, Parameters *params = nullptr ) +{ + typedef std::back_insert_iterator ittype; + ittype begin(out); + iterator_ostream os(begin); + return serialize_array(container, os, params); +} + +template::value, int>::type = 0> +bool serialize_array( const T& container, std::vector &out, Parameters *params = nullptr ) +{ + typedef std::back_insert_iterator> ittype; + ittype begin(out); + iterator_ostream os(begin); + return serialize_array(container, os, params); +} + #define PG_X_Y_Z_ENTITY(N,O,S) \ struct N : public O, public protogen_X_Y_Z::message< O, S > \ { \ diff --git a/tests/tests.cc b/tests/tests.cc index 52e66f3..210aa37 100644 --- a/tests/tests.cc +++ b/tests/tests.cc @@ -384,6 +384,74 @@ bool RUN_TEST8( int argc, char **argv) return true; } +bool RUN_TEST9( int argc, char **argv) +{ + (void) argc; + (void) argv; + + std::list people; + for (int i = 0; i < 5; ++i) + { + phonebook::Person person; + person.email = "test@example.com"; + person.id = 1234 + i; + person.name = "Person " + std::to_string(i); + people.push_back(std::move(person)); + } + + std::string json1; + protogen_3_0_0::serialize_array(people, json1); + + people.clear(); + auto result = protogen_3_0_0::deserialize_array(people, json1); + std::string json2; + protogen_3_0_0::serialize_array(people, json2); + + if (!result || json1 != json2) + { + std::cerr << "[TEST #9] Failed!" << std::endl; + std::cerr << " " << json1 << '\n'; + std::cerr << " " << json2 << '\n'; + return false; + } + else + { + std::cerr << "[TEST #9] Passed!" << std::endl; + std::cerr << " " << json1 << '\n'; + return true; + } +} + +bool RUN_TEST10( int argc, char **argv) +{ + (void) argc; + (void) argv; + + std::list people; + + std::string json1; + std::vector json2; + + if (!protogen_3_0_0::serialize_array(people, json1)) + goto FAILED; + //if (!protogen_3_0_0::deserialize_array(people, json1.c_str(), json1.length())) + // goto FAILED; + if (!protogen_3_0_0::deserialize_array(people, json1)) + goto FAILED; + + if (!protogen_3_0_0::serialize_array(people, json2)) + goto FAILED; + if (!protogen_3_0_0::deserialize_array(people, json2)) + goto FAILED; + + std::cerr << "[TEST #10] Passed!" << std::endl; + return true; + + FAILED: + std::cerr << "[TEST #10] Failed!" << std::endl; + return false; +} + int main( int argc, char **argv) { bool result = true; @@ -395,5 +463,7 @@ int main( int argc, char **argv) result &= RUN_TEST7A(argc, argv); result &= RUN_TEST7B(argc, argv); result &= RUN_TEST8(argc, argv); + result &= RUN_TEST9(argc, argv); + result &= RUN_TEST10(argc, argv); return (int) !result; }