From a485aa8d272f3656c1fb5840ce100f3288f7e2da Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 30 Aug 2016 23:44:15 +0200 Subject: [PATCH] cleanup and improvement of branch coverage --- src/json.hpp | 218 ++++++++++--------------- src/json.hpp.re2c | 218 ++++++++++--------------- test/src/unit-class_const_iterator.cpp | 16 ++ test/src/unit-deserialization.cpp | 104 ++++++++---- 4 files changed, 265 insertions(+), 291 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index d6f8925f..2f0f02d5 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1164,11 +1164,10 @@ class basic_json @since version 1.0.0 */ - template ::value and - std::is_constructible::value, int>::type - = 0> + template::value and + std::is_constructible::value, int>::type + = 0> basic_json(const CompatibleObjectType& val) : m_type(value_t::object) { @@ -1229,16 +1228,15 @@ class basic_json @since version 1.0.0 */ - template ::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - std::is_constructible::value, int>::type - = 0> + template::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + std::is_constructible::value, int>::type + = 0> basic_json(const CompatibleArrayType& val) : m_type(value_t::array) { @@ -1324,10 +1322,9 @@ class basic_json @since version 1.0.0 */ - template ::value, int>::type - = 0> + template::value, int>::type + = 0> basic_json(const CompatibleStringType& val) : basic_json(string_t(val)) { @@ -1377,8 +1374,7 @@ class basic_json @since version 1.0.0 */ - template::value) and std::is_same::value , int>::type @@ -1477,8 +1473,7 @@ class basic_json @since version 2.0.0 */ - template::value) and std::is_same::value , int>::type @@ -1509,13 +1504,11 @@ class basic_json @since version 2.0.0 */ - template ::value and - std::numeric_limits::is_integer and - not std::numeric_limits::is_signed, - CompatibleNumberUnsignedType>::type - = 0> + template::value and + std::numeric_limits::is_integer and + not std::numeric_limits::is_signed, CompatibleNumberUnsignedType>::type + = 0> basic_json(const CompatibleNumberUnsignedType val) noexcept : m_type(value_t::number_unsigned), m_value(static_cast(val)) @@ -1591,11 +1584,9 @@ class basic_json @since version 1.0.0 */ - template::value and - std::is_floating_point::value>::type - > + std::is_floating_point::value>::type> basic_json(const CompatibleNumberFloatType val) noexcept : basic_json(number_float_t(val)) { @@ -1672,8 +1663,8 @@ class basic_json @since version 1.0.0 */ basic_json(std::initializer_list init, - bool type_deduction = true, - value_t manual_type = value_t::array) + const bool type_deduction = true, + const value_t manual_type = value_t::array) { // check if each element is an array with two elements whose first // element is a string @@ -1862,12 +1853,9 @@ class basic_json @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> + template::value or + std::is_same::value>::type> basic_json(InputIT first, InputIT last) { assert(first.m_object != nullptr); @@ -2616,11 +2604,10 @@ class basic_json ////////////////// /// get an object (explicit) - template ::value and - std::is_convertible::value - , int>::type = 0> + template::value and + std::is_convertible::value + , int>::type = 0> T get_impl(T*) const { if (is_object()) @@ -2647,14 +2634,13 @@ class basic_json } /// get an array (explicit) - template ::value and - not std::is_same::value and - not std::is_arithmetic::value and - not std::is_convertible::value and - not has_mapped_type::value - , int>::type = 0> + template::value and + not std::is_same::value and + not std::is_arithmetic::value and + not std::is_convertible::value and + not has_mapped_type::value + , int>::type = 0> T get_impl(T*) const { if (is_array()) @@ -2674,11 +2660,10 @@ class basic_json } /// get an array (explicit) - template ::value and - not std::is_same::value - , int>::type = 0> + template::value and + not std::is_same::value + , int>::type = 0> std::vector get_impl(std::vector*) const { if (is_array()) @@ -2699,11 +2684,10 @@ class basic_json } /// get an array (explicit) - template ::value and - not has_mapped_type::value - , int>::type = 0> + template::value and + not has_mapped_type::value + , int>::type = 0> T get_impl(T*) const { if (is_array()) @@ -2730,10 +2714,9 @@ class basic_json } /// get a string (explicit) - template ::value - , int>::type = 0> + template::value + , int>::type = 0> T get_impl(T*) const { if (is_string()) @@ -2747,10 +2730,8 @@ class basic_json } /// get a number (explicit) - template::value - , int>::type = 0> + template::value, int>::type = 0> T get_impl(T*) const { switch (m_type) @@ -2939,10 +2920,8 @@ class basic_json @since version 1.0.0 */ - template::value - , int>::type = 0> + template::value>::type> ValueType get() const { return get_impl(static_cast(nullptr)); @@ -2975,10 +2954,8 @@ class basic_json @since version 1.0.0 */ - template::value - , int>::type = 0> + template::value>::type> PointerType get() noexcept { // delegate the call to get_ptr @@ -2989,10 +2966,8 @@ class basic_json @brief get a pointer value (explicit) @copydoc get() */ - template::value - , int>::type = 0> + template::value>::type> constexpr const PointerType get() const noexcept { // delegate the call to get_ptr @@ -3025,10 +3000,8 @@ class basic_json @since version 1.0.0 */ - template::value - , int>::type = 0> + template::value>::type> PointerType get_ptr() noexcept { // get the type of the PointerType (remove pointer and const) @@ -3054,11 +3027,9 @@ class basic_json @brief get a pointer value (implicit) @copydoc get_ptr() */ - template::value - and std::is_const::type>::value - , int>::type = 0> + and std::is_const::type>::value>::type> constexpr const PointerType get_ptr() const noexcept { // get the type of the PointerType (remove pointer and const) @@ -3106,10 +3077,8 @@ class basic_json @since version 1.1.0 */ - template::value - , int>::type = 0> + template::value>::type> ReferenceType get_ref() { // delegate call to get_ref_impl @@ -3120,11 +3089,9 @@ class basic_json @brief get a reference value (implicit) @copydoc get_ref() */ - template::value - and std::is_const::type>::value - , int>::type = 0> + and std::is_const::type>::value>::type> ReferenceType get_ref() const { // delegate call to get_ref_impl @@ -3159,14 +3126,13 @@ class basic_json @since version 1.0.0 */ - template < typename ValueType, typename - std::enable_if < + template < typename ValueType, typename = typename std::enable_if < not std::is_pointer::value and not std::is_same::value #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 and not std::is_same>::value #endif - , int >::type = 0 > + >::type > operator ValueType() const { // delegate the call to get<>() const @@ -3752,10 +3718,8 @@ class basic_json @since version 1.0.0 */ - template ::value - , int>::type = 0> + template::value>::type> ValueType value(const typename object_t::key_type& key, ValueType default_value) const { // at only works for objects @@ -3828,10 +3792,8 @@ class basic_json @since version 2.0.2 */ - template ::value - , int>::type = 0> + template::value>::type> ValueType value(const json_pointer& ptr, ValueType default_value) const { // at only works for objects @@ -3992,12 +3954,9 @@ class basic_json @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> + template::value or + std::is_same::value>::type> InteratorType erase(InteratorType pos) { // make sure iterator fits the current value @@ -4101,12 +4060,9 @@ class basic_json @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> + template::value or + std::is_same::value>::type> InteratorType erase(InteratorType first, InteratorType last) { // make sure iterator fits the current value @@ -6267,7 +6223,7 @@ class basic_json const unsigned int current_indent = 0) const { // variable to hold indentation for recursive calls - unsigned int new_indent = current_indent; + auto new_indent = current_indent; switch (m_type) { @@ -7561,7 +7517,7 @@ class basic_json const std::size_t codepoint2 = 0) { // calculate the code point from the given code points - std::size_t codepoint = codepoint1; + auto codepoint = codepoint1; // check if codepoint1 is a high surrogate if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF) @@ -9524,7 +9480,7 @@ basic_json_parser_63: auto reference_token = reference_string.substr(start, slash - start); // check reference tokens are properly escaped - for (size_t pos = reference_token.find_first_of("~"); + for (auto pos = reference_token.find_first_of("~"); pos != std::string::npos; pos = reference_token.find_first_of("~", pos + 1)) { @@ -9569,7 +9525,7 @@ basic_json_parser_63: assert(not f.empty()); for ( - size_t pos = s.find(f); // find first occurrence of f + auto pos = s.find(f); // find first occurrence of f pos != std::string::npos; // make sure f was found s.replace(pos, f.size(), t), // replace with t pos = s.find(f, pos + t.size()) // find next occurrence of f @@ -9969,7 +9925,7 @@ basic_json_parser_63: else { // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); + auto top_pointer = ptr.top(); if (top_pointer != ptr) { basic_json& x = result.at(top_pointer); @@ -10377,7 +10333,7 @@ namespace std @since version 1.0.0 */ -template <> +template<> inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( is_nothrow_move_constructible::value and @@ -10388,7 +10344,7 @@ inline void swap(nlohmann::json& j1, } /// hash value for JSON objects -template <> +template<> struct hash { /*! diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 75fc27e5..28532a8d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1164,11 +1164,10 @@ class basic_json @since version 1.0.0 */ - template ::value and - std::is_constructible::value, int>::type - = 0> + template::value and + std::is_constructible::value, int>::type + = 0> basic_json(const CompatibleObjectType& val) : m_type(value_t::object) { @@ -1229,16 +1228,15 @@ class basic_json @since version 1.0.0 */ - template ::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - not std::is_same::value and - std::is_constructible::value, int>::type - = 0> + template::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + std::is_constructible::value, int>::type + = 0> basic_json(const CompatibleArrayType& val) : m_type(value_t::array) { @@ -1324,10 +1322,9 @@ class basic_json @since version 1.0.0 */ - template ::value, int>::type - = 0> + template::value, int>::type + = 0> basic_json(const CompatibleStringType& val) : basic_json(string_t(val)) { @@ -1377,8 +1374,7 @@ class basic_json @since version 1.0.0 */ - template::value) and std::is_same::value , int>::type @@ -1477,8 +1473,7 @@ class basic_json @since version 2.0.0 */ - template::value) and std::is_same::value , int>::type @@ -1509,13 +1504,11 @@ class basic_json @since version 2.0.0 */ - template ::value and - std::numeric_limits::is_integer and - not std::numeric_limits::is_signed, - CompatibleNumberUnsignedType>::type - = 0> + template::value and + std::numeric_limits::is_integer and + not std::numeric_limits::is_signed, CompatibleNumberUnsignedType>::type + = 0> basic_json(const CompatibleNumberUnsignedType val) noexcept : m_type(value_t::number_unsigned), m_value(static_cast(val)) @@ -1591,11 +1584,9 @@ class basic_json @since version 1.0.0 */ - template::value and - std::is_floating_point::value>::type - > + std::is_floating_point::value>::type> basic_json(const CompatibleNumberFloatType val) noexcept : basic_json(number_float_t(val)) { @@ -1672,8 +1663,8 @@ class basic_json @since version 1.0.0 */ basic_json(std::initializer_list init, - bool type_deduction = true, - value_t manual_type = value_t::array) + const bool type_deduction = true, + const value_t manual_type = value_t::array) { // check if each element is an array with two elements whose first // element is a string @@ -1862,12 +1853,9 @@ class basic_json @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> + template::value or + std::is_same::value>::type> basic_json(InputIT first, InputIT last) { assert(first.m_object != nullptr); @@ -2616,11 +2604,10 @@ class basic_json ////////////////// /// get an object (explicit) - template ::value and - std::is_convertible::value - , int>::type = 0> + template::value and + std::is_convertible::value + , int>::type = 0> T get_impl(T*) const { if (is_object()) @@ -2647,14 +2634,13 @@ class basic_json } /// get an array (explicit) - template ::value and - not std::is_same::value and - not std::is_arithmetic::value and - not std::is_convertible::value and - not has_mapped_type::value - , int>::type = 0> + template::value and + not std::is_same::value and + not std::is_arithmetic::value and + not std::is_convertible::value and + not has_mapped_type::value + , int>::type = 0> T get_impl(T*) const { if (is_array()) @@ -2674,11 +2660,10 @@ class basic_json } /// get an array (explicit) - template ::value and - not std::is_same::value - , int>::type = 0> + template::value and + not std::is_same::value + , int>::type = 0> std::vector get_impl(std::vector*) const { if (is_array()) @@ -2699,11 +2684,10 @@ class basic_json } /// get an array (explicit) - template ::value and - not has_mapped_type::value - , int>::type = 0> + template::value and + not has_mapped_type::value + , int>::type = 0> T get_impl(T*) const { if (is_array()) @@ -2730,10 +2714,9 @@ class basic_json } /// get a string (explicit) - template ::value - , int>::type = 0> + template::value + , int>::type = 0> T get_impl(T*) const { if (is_string()) @@ -2747,10 +2730,8 @@ class basic_json } /// get a number (explicit) - template::value - , int>::type = 0> + template::value, int>::type = 0> T get_impl(T*) const { switch (m_type) @@ -2939,10 +2920,8 @@ class basic_json @since version 1.0.0 */ - template::value - , int>::type = 0> + template::value>::type> ValueType get() const { return get_impl(static_cast(nullptr)); @@ -2975,10 +2954,8 @@ class basic_json @since version 1.0.0 */ - template::value - , int>::type = 0> + template::value>::type> PointerType get() noexcept { // delegate the call to get_ptr @@ -2989,10 +2966,8 @@ class basic_json @brief get a pointer value (explicit) @copydoc get() */ - template::value - , int>::type = 0> + template::value>::type> constexpr const PointerType get() const noexcept { // delegate the call to get_ptr @@ -3025,10 +3000,8 @@ class basic_json @since version 1.0.0 */ - template::value - , int>::type = 0> + template::value>::type> PointerType get_ptr() noexcept { // get the type of the PointerType (remove pointer and const) @@ -3054,11 +3027,9 @@ class basic_json @brief get a pointer value (implicit) @copydoc get_ptr() */ - template::value - and std::is_const::type>::value - , int>::type = 0> + and std::is_const::type>::value>::type> constexpr const PointerType get_ptr() const noexcept { // get the type of the PointerType (remove pointer and const) @@ -3106,10 +3077,8 @@ class basic_json @since version 1.1.0 */ - template::value - , int>::type = 0> + template::value>::type> ReferenceType get_ref() { // delegate call to get_ref_impl @@ -3120,11 +3089,9 @@ class basic_json @brief get a reference value (implicit) @copydoc get_ref() */ - template::value - and std::is_const::type>::value - , int>::type = 0> + and std::is_const::type>::value>::type> ReferenceType get_ref() const { // delegate call to get_ref_impl @@ -3159,14 +3126,13 @@ class basic_json @since version 1.0.0 */ - template < typename ValueType, typename - std::enable_if < + template < typename ValueType, typename = typename std::enable_if < not std::is_pointer::value and not std::is_same::value #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 and not std::is_same>::value #endif - , int >::type = 0 > + >::type > operator ValueType() const { // delegate the call to get<>() const @@ -3752,10 +3718,8 @@ class basic_json @since version 1.0.0 */ - template ::value - , int>::type = 0> + template::value>::type> ValueType value(const typename object_t::key_type& key, ValueType default_value) const { // at only works for objects @@ -3828,10 +3792,8 @@ class basic_json @since version 2.0.2 */ - template ::value - , int>::type = 0> + template::value>::type> ValueType value(const json_pointer& ptr, ValueType default_value) const { // at only works for objects @@ -3992,12 +3954,9 @@ class basic_json @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> + template::value or + std::is_same::value>::type> InteratorType erase(InteratorType pos) { // make sure iterator fits the current value @@ -4101,12 +4060,9 @@ class basic_json @since version 1.0.0 */ - template ::value or - std::is_same::value - , int>::type - = 0> + template::value or + std::is_same::value>::type> InteratorType erase(InteratorType first, InteratorType last) { // make sure iterator fits the current value @@ -6267,7 +6223,7 @@ class basic_json const unsigned int current_indent = 0) const { // variable to hold indentation for recursive calls - unsigned int new_indent = current_indent; + auto new_indent = current_indent; switch (m_type) { @@ -7561,7 +7517,7 @@ class basic_json const std::size_t codepoint2 = 0) { // calculate the code point from the given code points - std::size_t codepoint = codepoint1; + auto codepoint = codepoint1; // check if codepoint1 is a high surrogate if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF) @@ -8821,7 +8777,7 @@ class basic_json auto reference_token = reference_string.substr(start, slash - start); // check reference tokens are properly escaped - for (size_t pos = reference_token.find_first_of("~"); + for (auto pos = reference_token.find_first_of("~"); pos != std::string::npos; pos = reference_token.find_first_of("~", pos + 1)) { @@ -8866,7 +8822,7 @@ class basic_json assert(not f.empty()); for ( - size_t pos = s.find(f); // find first occurrence of f + auto pos = s.find(f); // find first occurrence of f pos != std::string::npos; // make sure f was found s.replace(pos, f.size(), t), // replace with t pos = s.find(f, pos + t.size()) // find next occurrence of f @@ -9266,7 +9222,7 @@ class basic_json else { // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); + auto top_pointer = ptr.top(); if (top_pointer != ptr) { basic_json& x = result.at(top_pointer); @@ -9674,7 +9630,7 @@ namespace std @since version 1.0.0 */ -template <> +template<> inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( is_nothrow_move_constructible::value and @@ -9685,7 +9641,7 @@ inline void swap(nlohmann::json& j1, } /// hash value for JSON objects -template <> +template<> struct hash { /*! diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp index 4908b5ce..b64e7e3c 100644 --- a/test/src/unit-class_const_iterator.cpp +++ b/test/src/unit-class_const_iterator.cpp @@ -64,6 +64,22 @@ TEST_CASE("const_iterator class") json::const_iterator it2(&j); it2 = it; } + + SECTION("copy constructor from non-const iterator") + { + SECTION("create from uninitialized iterator") + { + const json::iterator it {}; + json::const_iterator cit(it); + } + + SECTION("create from initialized iterator") + { + json j; + const json::iterator it = j.begin(); + json::const_iterator cit(it); + } + } } SECTION("initialization") diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index 78188574..9d4c064f 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -33,41 +33,87 @@ using nlohmann::json; TEST_CASE("deserialization") { - SECTION("stream") + SECTION("successful deserialization") { - std::stringstream ss; - ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; - json j = json::parse(ss); - CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); + SECTION("stream") + { + std::stringstream ss; + ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; + json j = json::parse(ss); + CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); + } + + SECTION("string") + { + json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}]"; + json j = json::parse(s); + CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); + } + + SECTION("operator<<") + { + std::stringstream ss; + ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; + json j; + j << ss; + CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); + } + + SECTION("operator>>") + { + std::stringstream ss; + ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; + json j; + ss >> j; + CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); + } + + SECTION("user-defined string literal") + { + CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}})); + } } - SECTION("string") + SECTION("successful deserialization") { - auto s = "[\"foo\",1,2,3,false,{\"one\":1}]"; - json j = json::parse(s); - CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); - } + SECTION("stream") + { + std::stringstream ss; + ss << "[\"foo\",1,2,3,false,{\"one\":1}"; + CHECK_THROWS_AS(json::parse(ss), std::invalid_argument); + CHECK_THROWS_WITH(json::parse(ss), "parse error - unexpected end of input"); + } - SECTION("operator<<") - { - std::stringstream ss; - ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; - json j; - j << ss; - CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); - } + SECTION("string") + { + json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}"; + CHECK_THROWS_AS(json::parse(s), std::invalid_argument); + CHECK_THROWS_WITH(json::parse(s), "parse error - unexpected end of input; expected ']'"); + } - SECTION("operator>>") - { - std::stringstream ss; - ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; - json j; - ss >> j; - CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); - } + SECTION("operator<<") + { + std::stringstream ss; + ss << "[\"foo\",1,2,3,false,{\"one\":1}"; + json j; + CHECK_THROWS_AS(j << ss, std::invalid_argument); + CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input"); + } - SECTION("user-defined string literal") - { - CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}})); + SECTION("operator>>") + { + std::stringstream ss; + ss << "[\"foo\",1,2,3,false,{\"one\":1}"; + json j; + CHECK_THROWS_AS(ss >> j, std::invalid_argument); + CHECK_THROWS_WITH(ss >> j, "parse error - unexpected end of input"); + } + + SECTION("user-defined string literal") + { + CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, std::invalid_argument); + CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json, + "parse error - unexpected end of input; expected ']'"); + } } }