From 0c0f2e44b5bad1be335d68b35965ef05eb905e90 Mon Sep 17 00:00:00 2001 From: Julian Becker Date: Sat, 15 Sep 2018 03:23:54 +0200 Subject: [PATCH] BSON: support doubles --- .../nlohmann/detail/input/binary_reader.hpp | 12 ++-- .../nlohmann/detail/output/binary_writer.hpp | 29 ++++++++- single_include/nlohmann/json.hpp | 41 ++++++++++-- test/src/unit-bson.cpp | 64 +++++++++++++------ 4 files changed, 115 insertions(+), 31 deletions(-) diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 54833cc3..dc9015b8 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -137,8 +137,6 @@ class binary_reader } /*! - @param[in] len the length of the array or std::size_t(-1) for an - array of indefinite size @return whether array creation completed */ bool get_bson_str(string_t& result) @@ -179,15 +177,19 @@ class binary_reader string_t key; get_bson_str(key); sax->key(key); - sax->boolean(static_cast(get())); - } break; + double number; + get_number_little_endian(number); + sax->number_float(static_cast(number), ""); + } + break; case 0x08: { string_t key; get_bson_str(key); sax->key(key); sax->boolean(static_cast(get())); - } break; + } + break; } } diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 98e6104b..283c2cf2 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -676,8 +676,7 @@ class binary_writer } } - - std::size_t write_bson_object_entry(const typename BasicJsonType::string_t& name, const BasicJsonType& j) + std::size_t write_bson_boolean(const typename BasicJsonType::string_t& name, const BasicJsonType& j) { oa->write_character(static_cast(0x08)); // boolean oa->write_characters( @@ -687,6 +686,32 @@ class binary_writer return /*id*/ 1ul + name.size() + 1u + /*boolean value*/ 1u; } + std::size_t write_bson_double(const typename BasicJsonType::string_t& name, const BasicJsonType& j) + { + oa->write_character(static_cast(0x01)); // boolean + oa->write_characters( + reinterpret_cast(name.c_str()), + name.size() + 1u); + write_number_little_endian(j.m_value.number_float); + return /*id*/ 1ul + name.size() + 1u + /*double value*/ 8u; + } + + std::size_t write_bson_object_entry(const typename BasicJsonType::string_t& name, const BasicJsonType& j) + { + switch (j.type()) + { + default: + JSON_THROW(type_error::create(317, "JSON value cannot be serialized to requested format")); + break; + case value_t::boolean: + return write_bson_boolean(name, j); + case value_t::number_float: + return write_bson_double(name, j); + }; + + return 0ul; + } + /*! @param[in] j JSON value to serialize @pre j.type() == value_t::object diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 6b81d354..3da42389 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -6121,8 +6121,6 @@ class binary_reader } /*! - @param[in] len the length of the array or std::size_t(-1) for an - array of indefinite size @return whether array creation completed */ bool get_bson_str(string_t& result) @@ -6158,6 +6156,16 @@ class binary_reader { switch (entry_type) { + case 0x01: + { + string_t key; + get_bson_str(key); + sax->key(key); + double number; + get_number_little_endian(number); + sax->number_float(static_cast(number), ""); + } + break; case 0x08: { string_t key; @@ -8461,8 +8469,7 @@ class binary_writer } } - - std::size_t write_bson_object_entry(const typename BasicJsonType::string_t& name, const BasicJsonType& j) + std::size_t write_bson_boolean(const typename BasicJsonType::string_t& name, const BasicJsonType& j) { oa->write_character(static_cast(0x08)); // boolean oa->write_characters( @@ -8472,6 +8479,32 @@ class binary_writer return /*id*/ 1ul + name.size() + 1u + /*boolean value*/ 1u; } + std::size_t write_bson_double(const typename BasicJsonType::string_t& name, const BasicJsonType& j) + { + oa->write_character(static_cast(0x01)); // boolean + oa->write_characters( + reinterpret_cast(name.c_str()), + name.size() + 1u); + write_number_little_endian(j.m_value.number_float); + return /*id*/ 1ul + name.size() + 1u + /*double value*/ 8u; + } + + std::size_t write_bson_object_entry(const typename BasicJsonType::string_t& name, const BasicJsonType& j) + { + switch (j.type()) + { + default: + JSON_THROW(type_error::create(317, "JSON value cannot be serialized to requested format")); + break; + case value_t::boolean: + return write_bson_boolean(name, j); + case value_t::number_float: + return write_bson_double(name, j); + }; + + return 0ul; + } + /*! @param[in] j JSON value to serialize @pre j.type() == value_t::object diff --git a/test/src/unit-bson.cpp b/test/src/unit-bson.cpp index 9a710707..97746807 100644 --- a/test/src/unit-bson.cpp +++ b/test/src/unit-bson.cpp @@ -136,28 +136,52 @@ TEST_CASE("BSON") CHECK(json::from_bson(result, true, false) == j); } - // SECTION("non-empty object with double") - // { - // json j = - // { - // { "entry", true } - // }; + SECTION("non-empty object with bool") + { + json j = + { + { "entry", false } + }; - // std::vector expected = - // { - // 0x14, 0x00, 0x00, 0x00, // size (little endian) - // 0x01, /// entry: double - // 'e', 'n', 't', 'r', 'y', '\x00', - // 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0x40, - // 0x00 // end marker - // }; + std::vector expected = + { + 0x0D, 0x00, 0x00, 0x00, // size (little endian) + 0x08, // entry: boolean + 'e', 'n', 't', 'r', 'y', '\x00', + 0x00, // value = false + 0x00 // end marker + }; - // const auto result = json::to_bson(j); - // CHECK(result == expected); + const auto result = json::to_bson(j); + CHECK(result == expected); - // // roundtrip - // //CHECK(json::from_bson(result) == j); - // //CHECK(json::from_bson(result, true, false) == j); - // } + // roundtrip + CHECK(json::from_bson(result) == j); + CHECK(json::from_bson(result, true, false) == j); + } + + SECTION("non-empty object with double") + { + json j = + { + { "entry", 4.2 } + }; + + std::vector expected = + { + 0x14, 0x00, 0x00, 0x00, // size (little endian) + 0x01, /// entry: double + 'e', 'n', 't', 'r', 'y', '\x00', + 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0x40, + 0x00 // end marker + }; + + const auto result = json::to_bson(j); + CHECK(result == expected); + + // roundtrip + CHECK(json::from_bson(result) == j); + CHECK(json::from_bson(result, true, false) == j); + } } }