From 5851daa5760a640371c1c52ee7162694249a82dd Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 28 Jul 2017 00:21:55 +0200 Subject: [PATCH] :sparkles: binary formats can be stored in std::string, std::ofstreams or std::ostringstream #477 --- src/json.hpp | 132 ++++++++++++++++++++------------------ test/src/unit-cbor.cpp | 19 ++++++ test/src/unit-msgpack.cpp | 19 ++++++ 3 files changed, 109 insertions(+), 61 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index cbcdef93f..b79914b94 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -5796,7 +5796,7 @@ class binary_reader /*! @brief serialization to CBOR and MessagePack values */ -template +template class binary_writer { public: @@ -5805,7 +5805,7 @@ class binary_writer @param[in] adapter output adapter to write to */ - explicit binary_writer(output_adapter_t adapter) + explicit binary_writer(output_adapter_t adapter) : is_little_endian(binary_reader::little_endianess()), oa(adapter) { assert(oa); @@ -5820,13 +5820,15 @@ class binary_writer { case value_t::null: { - oa->write_character(0xf6); + oa->write_character(static_cast(0xf6)); break; } case value_t::boolean: { - oa->write_character(j.m_value.boolean ? 0xf5 : 0xf4); + oa->write_character(j.m_value.boolean + ? static_cast(0xf5) + : static_cast(0xf4)); break; } @@ -5843,22 +5845,22 @@ class binary_writer } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(0x18); + oa->write_character(static_cast(0x18)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(0x19); + oa->write_character(static_cast(0x19)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(0x1a); + oa->write_character(static_cast(0x1a)); write_number(static_cast(j.m_value.number_integer)); } else { - oa->write_character(0x1b); + oa->write_character(static_cast(0x1b)); write_number(static_cast(j.m_value.number_integer)); } } @@ -5873,22 +5875,22 @@ class binary_writer } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(0x38); + oa->write_character(static_cast(0x38)); write_number(static_cast(positive_number)); } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(0x39); + oa->write_character(static_cast(0x39)); write_number(static_cast(positive_number)); } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(0x3a); + oa->write_character(static_cast(0x3a)); write_number(static_cast(positive_number)); } else { - oa->write_character(0x3b); + oa->write_character(static_cast(0x3b)); write_number(static_cast(positive_number)); } } @@ -5903,22 +5905,22 @@ class binary_writer } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(0x18); + oa->write_character(static_cast(0x18)); write_number(static_cast(j.m_value.number_unsigned)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(0x19); + oa->write_character(static_cast(0x19)); write_number(static_cast(j.m_value.number_unsigned)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(0x1a); + oa->write_character(static_cast(0x1a)); write_number(static_cast(j.m_value.number_unsigned)); } else { - oa->write_character(0x1b); + oa->write_character(static_cast(0x1b)); write_number(static_cast(j.m_value.number_unsigned)); } break; @@ -5927,7 +5929,7 @@ class binary_writer case value_t::number_float: { // Double-Precision Float - oa->write_character(0xfb); + oa->write_character(static_cast(0xfb)); write_number(j.m_value.number_float); break; } @@ -5942,30 +5944,30 @@ class binary_writer } else if (N <= 0xff) { - oa->write_character(0x78); + oa->write_character(static_cast(0x78)); write_number(static_cast(N)); } else if (N <= 0xffff) { - oa->write_character(0x79); + oa->write_character(static_cast(0x79)); write_number(static_cast(N)); } else if (N <= 0xffffffff) { - oa->write_character(0x7a); + oa->write_character(static_cast(0x7a)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= 0xffffffffffffffff) { - oa->write_character(0x7b); + oa->write_character(static_cast(0x7b)); write_number(static_cast(N)); } // LCOV_EXCL_STOP // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), + reinterpret_cast(j.m_value.string->c_str()), j.m_value.string->size()); break; } @@ -5980,23 +5982,23 @@ class binary_writer } else if (N <= 0xff) { - oa->write_character(0x98); + oa->write_character(static_cast(0x98)); write_number(static_cast(N)); } else if (N <= 0xffff) { - oa->write_character(0x99); + oa->write_character(static_cast(0x99)); write_number(static_cast(N)); } else if (N <= 0xffffffff) { - oa->write_character(0x9a); + oa->write_character(static_cast(0x9a)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= 0xffffffffffffffff) { - oa->write_character(0x9b); + oa->write_character(static_cast(0x9b)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -6019,23 +6021,23 @@ class binary_writer } else if (N <= 0xff) { - oa->write_character(0xb8); + oa->write_character(static_cast(0xb8)); write_number(static_cast(N)); } else if (N <= 0xffff) { - oa->write_character(0xb9); + oa->write_character(static_cast(0xb9)); write_number(static_cast(N)); } else if (N <= 0xffffffff) { - oa->write_character(0xba); + oa->write_character(static_cast(0xba)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= 0xffffffffffffffff) { - oa->write_character(0xbb); + oa->write_character(static_cast(0xbb)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -6066,14 +6068,16 @@ class binary_writer case value_t::null: { // nil - oa->write_character(0xc0); + oa->write_character(static_cast(0xc0)); break; } case value_t::boolean: { // true and false - oa->write_character(j.m_value.boolean ? 0xc3 : 0xc2); + oa->write_character(j.m_value.boolean + ? static_cast(0xc3) + : static_cast(0xc2)); break; } @@ -6092,25 +6096,25 @@ class binary_writer else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 - oa->write_character(0xcc); + oa->write_character(static_cast(0xcc)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 - oa->write_character(0xcd); + oa->write_character(static_cast(0xcd)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 - oa->write_character(0xce); + oa->write_character(static_cast(0xce)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 - oa->write_character(0xcf); + oa->write_character(static_cast(0xcf)); write_number(static_cast(j.m_value.number_integer)); } } @@ -6125,28 +6129,28 @@ class binary_writer j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 - oa->write_character(0xd0); + oa->write_character(static_cast(0xd0)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 - oa->write_character(0xd1); + oa->write_character(static_cast(0xd1)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 - oa->write_character(0xd2); + oa->write_character(static_cast(0xd2)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 - oa->write_character(0xd3); + oa->write_character(static_cast(0xd3)); write_number(static_cast(j.m_value.number_integer)); } } @@ -6163,25 +6167,25 @@ class binary_writer else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 - oa->write_character(0xcc); + oa->write_character(static_cast(0xcc)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 - oa->write_character(0xcd); + oa->write_character(static_cast(0xcd)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 - oa->write_character(0xce); + oa->write_character(static_cast(0xce)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 - oa->write_character(0xcf); + oa->write_character(static_cast(0xcf)); write_number(static_cast(j.m_value.number_integer)); } break; @@ -6190,7 +6194,7 @@ class binary_writer case value_t::number_float: { // float 64 - oa->write_character(0xcb); + oa->write_character(static_cast(0xcb)); write_number(j.m_value.number_float); break; } @@ -6207,25 +6211,25 @@ class binary_writer else if (N <= 255) { // str 8 - oa->write_character(0xd9); + oa->write_character(static_cast(0xd9)); write_number(static_cast(N)); } else if (N <= 65535) { // str 16 - oa->write_character(0xda); + oa->write_character(static_cast(0xda)); write_number(static_cast(N)); } else if (N <= 4294967295) { // str 32 - oa->write_character(0xdb); + oa->write_character(static_cast(0xdb)); write_number(static_cast(N)); } // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), + reinterpret_cast(j.m_value.string->c_str()), j.m_value.string->size()); break; } @@ -6242,13 +6246,13 @@ class binary_writer else if (N <= 0xffff) { // array 16 - oa->write_character(0xdc); + oa->write_character(static_cast(0xdc)); write_number(static_cast(N)); } else if (N <= 0xffffffff) { // array 32 - oa->write_character(0xdd); + oa->write_character(static_cast(0xdd)); write_number(static_cast(N)); } @@ -6272,13 +6276,13 @@ class binary_writer else if (N <= 65535) { // map 16 - oa->write_character(0xde); + oa->write_character(static_cast(0xde)); write_number(static_cast(N)); } else if (N <= 4294967295) { // map 32 - oa->write_character(0xdf); + oa->write_character(static_cast(0xdf)); write_number(static_cast(N)); } @@ -6312,7 +6316,7 @@ class binary_writer template void write_number(NumberType n) { // step 1: write number to array of length NumberType - std::array vec; + std::array vec; std::memcpy(vec.data(), &n, sizeof(NumberType)); // step 2: write array to output (with possible reordering) @@ -6330,7 +6334,7 @@ class binary_writer const bool is_little_endian = true; /// the output - output_adapter_t oa = nullptr; + output_adapter_t oa = nullptr; }; /////////////////// @@ -7510,7 +7514,8 @@ class basic_json friend ::nlohmann::detail::serializer; template friend class ::nlohmann::detail::iter_impl; - friend ::nlohmann::detail::binary_writer; + template + friend class ::nlohmann::detail::binary_writer; /// workaround type for MSVC using basic_json_t = NLOHMANN_BASIC_JSON_TPL; @@ -7531,7 +7536,7 @@ class basic_json using output_adapter_t = ::nlohmann::detail::output_adapter_t; using binary_reader = ::nlohmann::detail::binary_reader; - using binary_writer = ::nlohmann::detail::binary_writer; + template using binary_writer = ::nlohmann::detail::binary_writer; using serializer = ::nlohmann::detail::serializer; @@ -13172,7 +13177,12 @@ class basic_json static void to_cbor(const basic_json& j, detail::output_adapter o) { - binary_writer(o).write_cbor(j); + binary_writer(o).write_cbor(j); + } + + static void to_cbor(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_cbor(j); } /*! @@ -13258,12 +13268,12 @@ class basic_json static void to_msgpack(const basic_json& j, detail::output_adapter o) { - binary_writer(o).write_msgpack(j); + binary_writer(o).write_msgpack(j); } - static void to_msgpack(const basic_json& j, std::vector& result) + static void to_msgpack(const basic_json& j, detail::output_adapter o) { - binary_writer((detail::output_adapter(result))).write_msgpack(j); + binary_writer(o).write_msgpack(j); } /*! diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 934ce55f9..ae3e39b60 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1284,6 +1284,25 @@ TEST_CASE("single CBOR roundtrip") // compare parsed JSON values CHECK(j1 == j2); + SECTION("roundtrips") + { + SECTION("std::ostringstream") + { + std::ostringstream ss; + json::to_cbor(j1, ss); + json j3 = json::from_cbor(ss.str()); + CHECK(j1 == j3); + } + + SECTION("std::string") + { + std::string s; + json::to_cbor(j1, s); + json j3 = json::from_cbor(s); + CHECK(j1 == j3); + } + } + // check with different start index packed.insert(packed.begin(), 5, 0xff); CHECK(j1 == json::from_cbor(packed, 5)); diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index f4b403541..730fc7ddc 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1126,6 +1126,25 @@ TEST_CASE("single MessagePack roundtrip") // compare parsed JSON values CHECK(j1 == j2); + SECTION("roundtrips") + { + SECTION("std::ostringstream") + { + std::ostringstream ss; + json::to_msgpack(j1, ss); + json j3 = json::from_msgpack(ss.str()); + CHECK(j1 == j3); + } + + SECTION("std::string") + { + std::string s; + json::to_msgpack(j1, s); + json j3 = json::from_msgpack(s); + CHECK(j1 == j3); + } + } + // check with different start index packed.insert(packed.begin(), 5, 0xff); CHECK(j1 == json::from_msgpack(packed, 5));