From d2475f9010e880b04c19987e8211b05b6bb1e022 Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 28 Jun 2016 21:44:03 +0200 Subject: [PATCH 01/48] bumped version number --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- test/src/unit.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 7adcbb430..35bdd293c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.0 +| | |__ | | | | | | version 2.0.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 4b86afd6b..016ff0c51 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.0 +| | |__ | | | | | | version 2.0.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 1f5c6d9ff..3b8909ac7 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.0 +| | |__ | | | | | | version 2.0.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . From 7ffa07e3a3b21a2fec08da9c7d4fda8b7d043ff9 Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 28 Jun 2016 21:46:53 +0200 Subject: [PATCH 02/48] update of ChangeLog --- ChangeLog.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0565f2888..34d28e4db 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,9 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [Unreleased](https://github.com/nlohmann/json/tree/HEAD) - -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.0...HEAD) +## [v2.0.1](https://github.com/nlohmann/json/releases/tag/v2.0.1) (2016-06-28) +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.0...v2.0.1) - dump\(\) performance degradation in v2 [\#272](https://github.com/nlohmann/json/issues/272) From dc479b3f9de06dea12105c6ea21ee263dcfd8d6a Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 28 Jun 2016 22:09:22 +0200 Subject: [PATCH 03/48] check for unsupported compilers --- src/json.hpp | 14 ++++++++++++++ src/json.hpp.re2c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/json.hpp b/src/json.hpp index 35bdd293c..1673fb17a 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -53,6 +53,20 @@ SOFTWARE. #include #include +// exclude unsupported compilers +#if defined(__clang__) + #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) + #if CLANG_VERSION < 34000 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif +#endif +#if defined(__GNUC__) + #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) + #if GCC_VERSION < 48000 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif +#endif + // disable float-equal warnings on GCC/clang #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) #pragma GCC diagnostic push diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 016ff0c51..2672c1d0a 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -53,6 +53,20 @@ SOFTWARE. #include #include +// exclude unsupported compilers +#if defined(__clang__) + #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) + #if CLANG_VERSION < 34000 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif +#endif +#if defined(__GNUC__) + #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) + #if GCC_VERSION < 48000 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif +#endif + // disable float-equal warnings on GCC/clang #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) #pragma GCC diagnostic push From fc7f4b8fba1ed63f700d690ce4904ec851fc20ab Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 28 Jun 2016 22:49:05 +0200 Subject: [PATCH 04/48] replace some raw loops with algorithms --- src/json.hpp | 62 +++++++++++++++++++++-------------------------- src/json.hpp.re2c | 62 +++++++++++++++++++++-------------------------- 2 files changed, 54 insertions(+), 70 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 35bdd293c..fcb5e733d 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -46,6 +46,7 @@ SOFTWARE. #include #include #include +#include #include #include #include @@ -1554,22 +1555,13 @@ class basic_json bool type_deduction = true, value_t manual_type = value_t::array) { - // the initializer list could describe an object - bool is_an_object = true; - // check if each element is an array with two elements whose first // element is a string - for (const auto& element : init) + bool is_an_object = std::all_of(init.begin(), init.end(), + [](const basic_json & element) { - if (not element.is_array() or element.size() != 2 - or not element[0].is_string()) - { - // we found an element that makes it impossible to use the - // initializer list as object - is_an_object = false; - break; - } - } + return element.is_array() and element.size() == 2 and element[0].is_string(); + }); // adjust type if type deduction is not wanted if (not type_deduction) @@ -1595,10 +1587,10 @@ class basic_json assert(m_value.object != nullptr); - for (auto& element : init) + std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); - } + }); } else { @@ -3235,11 +3227,13 @@ class basic_json // operator[] only works for arrays if (is_array()) { - // fill up array with null values until given idx is reached + // fill up array with null values if given idx is outside range assert(m_value.array != nullptr); - for (size_t i = m_value.array->size(); i <= idx; ++i) + if (idx >= m_value.array->size()) { - m_value.array->push_back(basic_json()); + m_value.array->insert(m_value.array->end(), + idx - m_value.array->size() + 1, + basic_json()); } return m_value.array->operator[](idx); @@ -5832,9 +5826,8 @@ class basic_json */ static std::size_t extra_space(const string_t& s) noexcept { - std::size_t result = 0; - - for (const auto& c : s) + return std::accumulate(s.begin(), s.end(), size_t{}, + [](size_t res, typename string_t::value_type c) { switch (c) { @@ -5847,8 +5840,7 @@ class basic_json case '\t': { // from c (1 byte) to \x (2 bytes) - result += 1; - break; + return res + 1; } default: @@ -5856,14 +5848,15 @@ class basic_json if (c >= 0x00 and c <= 0x1f) { // from c (1 byte) to \uxxxx (6 bytes) - result += 5; + return res + 5; + } + else + { + return res; } - break; } } - } - - return result; + }); } /*! @@ -8778,14 +8771,13 @@ basic_json_parser_63: */ std::string to_string() const noexcept { - std::string result; - - for (const auto& reference_token : reference_tokens) + return std::accumulate(reference_tokens.begin(), + reference_tokens.end(), std::string{}, + [](const std::string & a, + const std::string & b) { - result += "/" + escape(reference_token); - } - - return result; + return a + "/" + escape(b); + }); } /// @copydoc to_string() diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 016ff0c51..dea0f51c5 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -46,6 +46,7 @@ SOFTWARE. #include #include #include +#include #include #include #include @@ -1554,22 +1555,13 @@ class basic_json bool type_deduction = true, value_t manual_type = value_t::array) { - // the initializer list could describe an object - bool is_an_object = true; - // check if each element is an array with two elements whose first // element is a string - for (const auto& element : init) + bool is_an_object = std::all_of(init.begin(), init.end(), + [](const basic_json & element) { - if (not element.is_array() or element.size() != 2 - or not element[0].is_string()) - { - // we found an element that makes it impossible to use the - // initializer list as object - is_an_object = false; - break; - } - } + return element.is_array() and element.size() == 2 and element[0].is_string(); + }); // adjust type if type deduction is not wanted if (not type_deduction) @@ -1595,10 +1587,10 @@ class basic_json assert(m_value.object != nullptr); - for (auto& element : init) + std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); - } + }); } else { @@ -3235,11 +3227,13 @@ class basic_json // operator[] only works for arrays if (is_array()) { - // fill up array with null values until given idx is reached + // fill up array with null values if given idx is outside range assert(m_value.array != nullptr); - for (size_t i = m_value.array->size(); i <= idx; ++i) + if (idx >= m_value.array->size()) { - m_value.array->push_back(basic_json()); + m_value.array->insert(m_value.array->end(), + idx - m_value.array->size() + 1, + basic_json()); } return m_value.array->operator[](idx); @@ -5832,9 +5826,8 @@ class basic_json */ static std::size_t extra_space(const string_t& s) noexcept { - std::size_t result = 0; - - for (const auto& c : s) + return std::accumulate(s.begin(), s.end(), size_t{}, + [](size_t res, typename string_t::value_type c) { switch (c) { @@ -5847,8 +5840,7 @@ class basic_json case '\t': { // from c (1 byte) to \x (2 bytes) - result += 1; - break; + return res + 1; } default: @@ -5856,14 +5848,15 @@ class basic_json if (c >= 0x00 and c <= 0x1f) { // from c (1 byte) to \uxxxx (6 bytes) - result += 5; + return res + 5; + } + else + { + return res; } - break; } } - } - - return result; + }); } /*! @@ -8088,14 +8081,13 @@ class basic_json */ std::string to_string() const noexcept { - std::string result; - - for (const auto& reference_token : reference_tokens) + return std::accumulate(reference_tokens.begin(), + reference_tokens.end(), std::string{}, + [](const std::string & a, + const std::string & b) { - result += "/" + escape(reference_token); - } - - return result; + return a + "/" + escape(b); + }); } /// @copydoc to_string() From d456dec320b198c1376cd10cb1697038f341de08 Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 29 Jun 2016 09:16:18 +0200 Subject: [PATCH 05/48] overlapping defines --- src/json.hpp | 3 +-- src/json.hpp.re2c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 1673fb17a..eaa3a44e1 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -59,8 +59,7 @@ SOFTWARE. #if CLANG_VERSION < 34000 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif -#endif -#if defined(__GNUC__) +#elif defined(__GNUC__) #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #if GCC_VERSION < 48000 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 2672c1d0a..9c94a2ba0 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -59,8 +59,7 @@ SOFTWARE. #if CLANG_VERSION < 34000 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif -#endif -#if defined(__GNUC__) +#elif defined(__GNUC__) #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #if GCC_VERSION < 48000 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" From 7cb8ee42d52bd773bdd55bd873c3f48565060ed0 Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 29 Jun 2016 09:22:28 +0200 Subject: [PATCH 06/48] wrong GCC version --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index eaa3a44e1..92b913a84 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -61,7 +61,7 @@ SOFTWARE. #endif #elif defined(__GNUC__) #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) - #if GCC_VERSION < 48000 + #if GCC_VERSION < 49000 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 9c94a2ba0..cc4df5de2 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -61,7 +61,7 @@ SOFTWARE. #endif #elif defined(__GNUC__) #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) - #if GCC_VERSION < 48000 + #if GCC_VERSION < 49000 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif From 924f78119b6160cd26daec2b5eeb4837483d4e43 Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 29 Jun 2016 09:34:14 +0200 Subject: [PATCH 07/48] math... --- src/json.hpp | 4 ++-- src/json.hpp.re2c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 92b913a84..d73abe0cc 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -56,12 +56,12 @@ SOFTWARE. // exclude unsupported compilers #if defined(__clang__) #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) - #if CLANG_VERSION < 34000 + #if CLANG_VERSION < 30400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif #elif defined(__GNUC__) #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) - #if GCC_VERSION < 49000 + #if GCC_VERSION < 40900 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index cc4df5de2..2d5732584 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -56,12 +56,12 @@ SOFTWARE. // exclude unsupported compilers #if defined(__clang__) #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) - #if CLANG_VERSION < 34000 + #if CLANG_VERSION < 30400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif #elif defined(__GNUC__) #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) - #if GCC_VERSION < 49000 + #if GCC_VERSION < 40900 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif From a0609b2da311ab68978e136eac770bc7aed4bd95 Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 29 Jun 2016 09:53:48 +0200 Subject: [PATCH 08/48] fixed coverage bug --- src/json.hpp | 3 +-- src/json.hpp.re2c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index fcb5e733d..78c5c54ee 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8773,8 +8773,7 @@ basic_json_parser_63: { return std::accumulate(reference_tokens.begin(), reference_tokens.end(), std::string{}, - [](const std::string & a, - const std::string & b) + [](const std::string & a, const std::string & b) { return a + "/" + escape(b); }); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index dea0f51c5..c484c5e8e 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8083,8 +8083,7 @@ class basic_json { return std::accumulate(reference_tokens.begin(), reference_tokens.end(), std::string{}, - [](const std::string & a, - const std::string & b) + [](const std::string & a, const std::string & b) { return a + "/" + escape(b); }); From 52cbda80484d112d2af352ddd608ea3cb76d73db Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 29 Jun 2016 12:47:29 +0200 Subject: [PATCH 09/48] using std::advance where possible --- src/json.hpp | 12 ++++++------ src/json.hpp.re2c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 78c5c54ee..57618dd08 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6606,13 +6606,13 @@ class basic_json { case basic_json::value_t::object: { - ++m_it.object_iterator; + std::advance(m_it.object_iterator, 1); break; } case basic_json::value_t::array: { - ++m_it.array_iterator; + std::advance(m_it.array_iterator, 1); break; } @@ -6643,13 +6643,13 @@ class basic_json { case basic_json::value_t::object: { - --m_it.object_iterator; + std::advance(m_it.object_iterator, -1); break; } case basic_json::value_t::array: { - --m_it.array_iterator; + std::advance(m_it.array_iterator, -1); break; } @@ -6761,7 +6761,7 @@ class basic_json case basic_json::value_t::array: { - m_it.array_iterator += i; + std::advance(m_it.array_iterator, i); break; } @@ -6835,7 +6835,7 @@ class basic_json case basic_json::value_t::array: { - return *(m_it.array_iterator + n); + return *std::next(m_it.array_iterator, n); } case basic_json::value_t::null: diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index c484c5e8e..cf0d4df83 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6606,13 +6606,13 @@ class basic_json { case basic_json::value_t::object: { - ++m_it.object_iterator; + std::advance(m_it.object_iterator, 1); break; } case basic_json::value_t::array: { - ++m_it.array_iterator; + std::advance(m_it.array_iterator, 1); break; } @@ -6643,13 +6643,13 @@ class basic_json { case basic_json::value_t::object: { - --m_it.object_iterator; + std::advance(m_it.object_iterator, -1); break; } case basic_json::value_t::array: { - --m_it.array_iterator; + std::advance(m_it.array_iterator, -1); break; } @@ -6761,7 +6761,7 @@ class basic_json case basic_json::value_t::array: { - m_it.array_iterator += i; + std::advance(m_it.array_iterator, i); break; } @@ -6835,7 +6835,7 @@ class basic_json case basic_json::value_t::array: { - return *(m_it.array_iterator + n); + return *std::next(m_it.array_iterator, n); } case basic_json::value_t::null: From 5c129c898158c93f751985c305296d781891d814 Mon Sep 17 00:00:00 2001 From: dtoma Date: Wed, 29 Jun 2016 19:28:56 +0800 Subject: [PATCH 10/48] Update hexify to use array lookup instead of ternary (#270) --- src/json.hpp.re2c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 016ff0c51..adc2e188c 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -5959,9 +5959,11 @@ class basic_json // (0..f) const auto hexify = [](const int v) -> char { - return (v < 10) - ? ('0' + static_cast(v)) - : ('a' + static_cast((v - 10) & 0x1f)); + static const char hex[16] = { '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f' }; + return hex[v]; }; // print character c as \uxxxx From a5262c18e23bbbd45d677226e20ea3952f52bb30 Mon Sep 17 00:00:00 2001 From: Niels Date: Thu, 30 Jun 2016 12:43:06 +0200 Subject: [PATCH 11/48] replaced a copy by a move to increase performance by 16-25% --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 35bdd293c..d9c75c4a9 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8480,7 +8480,7 @@ basic_json_parser_63: // return parser result and replace it with null in case the // top-level value was discarded by the callback function - return result.is_discarded() ? basic_json() : result; + return result.is_discarded() ? basic_json() : std::move(result); } private: diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 016ff0c51..ba045342e 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7790,7 +7790,7 @@ class basic_json // return parser result and replace it with null in case the // top-level value was discarded by the callback function - return result.is_discarded() ? basic_json() : result; + return result.is_discarded() ? basic_json() : std::move(result); } private: From 26cab42c382b2a0ff7a8f3d45b3219721ad63906 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 1 Jul 2016 16:52:05 +0200 Subject: [PATCH 12/48] some minor improvements --- doc/examples/count.cpp | 1 - doc/examples/count.link | 2 +- src/json.hpp | 91 +++++++++++++++++++++++++++++++--------- src/json.hpp.re2c | 93 +++++++++++++++++++++++++++++++---------- 4 files changed, 144 insertions(+), 43 deletions(-) diff --git a/doc/examples/count.cpp b/doc/examples/count.cpp index a805eeb6a..b97f71dab 100644 --- a/doc/examples/count.cpp +++ b/doc/examples/count.cpp @@ -12,7 +12,6 @@ int main() auto count_three = j_object.count("three"); // print values - std::cout << std::boolalpha; std::cout << "number of elements with key \"two\": " << count_two << '\n'; std::cout << "number of elements with key \"three\": " << count_three << '\n'; } diff --git a/doc/examples/count.link b/doc/examples/count.link index 62833ff46..0893d9223 100644 --- a/doc/examples/count.link +++ b/doc/examples/count.link @@ -1 +1 @@ -online \ No newline at end of file +online \ No newline at end of file diff --git a/src/json.hpp b/src/json.hpp index 35bdd293c..cef0f26df 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -76,7 +76,13 @@ namespace { /*! @brief Helper to determine whether there's a key_type for T. + +Thus helper is used to tell associative containers apart from other containers +such as sequence containers. For instance, `std::map` passes the test as it +contains a `mapped_type`, whereas `std::vector` fails the test. + @sa http://stackoverflow.com/a/7728728/266378 +@since version 1.0.0 */ template struct has_mapped_type @@ -90,11 +96,18 @@ struct has_mapped_type /*! @brief helper class to create locales with decimal point + +This struct is used a default locale during the JSON serialization. JSON +requires the decimal point to be `.`, so this function overloads the +`do_decimal_point()` function to return `.`. This function is called by +float-to-string conversions to retrieve the decimal separator between integer +and fractional parts. + @sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315 +@since version 2.0.0 */ -class DecimalSeparator : public std::numpunct +struct DecimalSeparator : std::numpunct { - protected: char do_decimal_point() const { return '.'; @@ -188,13 +201,8 @@ class basic_json { private: /// workaround type for MSVC - using basic_json_t = basic_json; public: @@ -207,6 +215,8 @@ class basic_json ///////////////////// /// @name container types + /// The canonic container types to use @ref basic_json like any other STL + /// container. /// @{ /// the type of elements in a basic_json container @@ -256,6 +266,8 @@ class basic_json /////////////////////////// /// @name JSON value data types + /// The data types to store a JSON value. These types are derived from + /// the template arguments passed to class @ref basic_json. /// @{ /*! @@ -923,6 +935,8 @@ class basic_json ////////////////// /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. /// @{ /*! @@ -2069,19 +2083,20 @@ class basic_json /////////////////////// /// @name object inspection + /// Functions to inspect the type of a JSON value. /// @{ /*! @brief serialization Serialization function for JSON values. The function tries to mimic - Python's @p json.dumps() function, and currently supports its @p indent + Python's `json.dumps()` function, and currently supports its @a indent parameter. - @param[in] indent if indent is nonnegative, then array elements and object + @param[in] indent If indent is nonnegative, then array elements and object members will be pretty-printed with that indent level. An indent level of - 0 will only insert newlines. -1 (the default) selects the most compact - representation + `0` will only insert newlines. `-1` (the default) selects the most compact + representation. @return string containing the serialization of the JSON value @@ -2767,6 +2782,7 @@ class basic_json public: /// @name value access + /// Direct access to the stored value of a JSON value. /// @{ /*! @@ -2817,7 +2833,8 @@ class basic_json Explicit pointer access to the internally stored JSON value. No copies are made. - @warning The pointer becomes invalid if the underlying JSON object changes. + @warning The pointer becomes invalid if the underlying JSON object + changes. @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, @@ -2872,7 +2889,8 @@ class basic_json @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. + @ref number_unsigned_t, or @ref number_float_t. Enforced by a static + assertion. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @@ -2892,6 +2910,21 @@ class basic_json , int>::type = 0> PointerType get_ptr() noexcept { + // get the type of the PointerType (remove pointer and const) + using pointee_t = typename std::remove_const::type>::type>::type; + // make sure the type matches the allowed types + static_assert( + std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + , "incompatible pointer type"); + // delegate the call to get_impl_ptr<>() return get_impl_ptr(static_cast(nullptr)); } @@ -2907,6 +2940,21 @@ class basic_json , int>::type = 0> constexpr const PointerType get_ptr() const noexcept { + // get the type of the PointerType (remove pointer and const) + using pointee_t = typename std::remove_const::type>::type>::type; + // make sure the type matches the allowed types + static_assert( + std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + , "incompatible pointer type"); + // delegate the call to get_impl_ptr<>() const return get_impl_ptr(static_cast(nullptr)); } @@ -2922,7 +2970,7 @@ class basic_json @tparam ReferenceType reference type; must be a reference to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or - @ref number_float_t. + @ref number_float_t. Enforced by static assertion. @return reference to the internally stored JSON value if the requested reference type @a ReferenceType fits to the JSON value; throws @@ -3012,6 +3060,7 @@ class basic_json //////////////////// /// @name element access + /// Access to the JSON value. /// @{ /*! @@ -8127,7 +8176,7 @@ basic_json_parser_63: } /// return string representation of last read token - string_t get_token() const + string_t get_token_string() const { assert(m_start != nullptr); return string_t(reinterpret_cast(m_start), @@ -8395,7 +8444,7 @@ basic_json_parser_63: if (type != value_t::number_float) { // multiply last value by ten and add the new digit - auto temp = value * 10 + *curptr - 0x30; + auto temp = value * 10 + *curptr - '0'; // test for overflow if (temp < value || temp > max) @@ -8688,7 +8737,8 @@ basic_json_parser_63: if (t != last_token) { std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + + "'") : lexer::token_type_name(last_token)); error_msg += "; expected " + lexer::token_type_name(t); throw std::invalid_argument(error_msg); @@ -8700,7 +8750,8 @@ basic_json_parser_63: if (t == last_token) { std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + + "'") : lexer::token_type_name(last_token)); throw std::invalid_argument(error_msg); } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 016ff0c51..8ac900c29 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -76,7 +76,13 @@ namespace { /*! @brief Helper to determine whether there's a key_type for T. + +Thus helper is used to tell associative containers apart from other containers +such as sequence containers. For instance, `std::map` passes the test as it +contains a `mapped_type`, whereas `std::vector` fails the test. + @sa http://stackoverflow.com/a/7728728/266378 +@since version 1.0.0 */ template struct has_mapped_type @@ -90,11 +96,18 @@ struct has_mapped_type /*! @brief helper class to create locales with decimal point + +This struct is used a default locale during the JSON serialization. JSON +requires the decimal point to be `.`, so this function overloads the +`do_decimal_point()` function to return `.`. This function is called by +float-to-string conversions to retrieve the decimal separator between integer +and fractional parts. + @sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315 +@since version 2.0.0 */ -class DecimalSeparator : public std::numpunct +struct DecimalSeparator : std::numpunct { - protected: char do_decimal_point() const { return '.'; @@ -188,13 +201,8 @@ class basic_json { private: /// workaround type for MSVC - using basic_json_t = basic_json; public: @@ -207,6 +215,8 @@ class basic_json ///////////////////// /// @name container types + /// The canonic container types to use @ref basic_json like any other STL + /// container. /// @{ /// the type of elements in a basic_json container @@ -256,6 +266,8 @@ class basic_json /////////////////////////// /// @name JSON value data types + /// The data types to store a JSON value. These types are derived from + /// the template arguments passed to class @ref basic_json. /// @{ /*! @@ -923,6 +935,8 @@ class basic_json ////////////////// /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. /// @{ /*! @@ -2069,19 +2083,20 @@ class basic_json /////////////////////// /// @name object inspection + /// Functions to inspect the type of a JSON value. /// @{ /*! @brief serialization Serialization function for JSON values. The function tries to mimic - Python's @p json.dumps() function, and currently supports its @p indent + Python's `json.dumps()` function, and currently supports its @a indent parameter. - @param[in] indent if indent is nonnegative, then array elements and object + @param[in] indent If indent is nonnegative, then array elements and object members will be pretty-printed with that indent level. An indent level of - 0 will only insert newlines. -1 (the default) selects the most compact - representation + `0` will only insert newlines. `-1` (the default) selects the most compact + representation. @return string containing the serialization of the JSON value @@ -2767,6 +2782,7 @@ class basic_json public: /// @name value access + /// Direct access to the stored value of a JSON value. /// @{ /*! @@ -2817,7 +2833,8 @@ class basic_json Explicit pointer access to the internally stored JSON value. No copies are made. - @warning The pointer becomes invalid if the underlying JSON object changes. + @warning The pointer becomes invalid if the underlying JSON object + changes. @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, @@ -2872,7 +2889,8 @@ class basic_json @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. + @ref number_unsigned_t, or @ref number_float_t. Enforced by a static + assertion. @return pointer to the internally stored JSON value if the requested pointer type @a PointerType fits to the JSON value; `nullptr` otherwise @@ -2892,6 +2910,21 @@ class basic_json , int>::type = 0> PointerType get_ptr() noexcept { + // get the type of the PointerType (remove pointer and const) + using pointee_t = typename std::remove_const::type>::type>::type; + // make sure the type matches the allowed types + static_assert( + std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + , "incompatible pointer type"); + // delegate the call to get_impl_ptr<>() return get_impl_ptr(static_cast(nullptr)); } @@ -2907,6 +2940,21 @@ class basic_json , int>::type = 0> constexpr const PointerType get_ptr() const noexcept { + // get the type of the PointerType (remove pointer and const) + using pointee_t = typename std::remove_const::type>::type>::type; + // make sure the type matches the allowed types + static_assert( + std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + or std::is_same::value + , "incompatible pointer type"); + // delegate the call to get_impl_ptr<>() const return get_impl_ptr(static_cast(nullptr)); } @@ -2922,7 +2970,7 @@ class basic_json @tparam ReferenceType reference type; must be a reference to @ref array_t, @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or - @ref number_float_t. + @ref number_float_t. Enforced by static assertion. @return reference to the internally stored JSON value if the requested reference type @a ReferenceType fits to the JSON value; throws @@ -3012,6 +3060,7 @@ class basic_json //////////////////// /// @name element access + /// Access to the JSON value. /// @{ /*! @@ -7407,7 +7456,7 @@ class basic_json // anything else is an error . { return token_type::parse_error; } - */ + */ } /// append data from the stream to the internal buffer @@ -7437,7 +7486,7 @@ class basic_json } /// return string representation of last read token - string_t get_token() const + string_t get_token_string() const { assert(m_start != nullptr); return string_t(reinterpret_cast(m_start), @@ -7705,7 +7754,7 @@ class basic_json if (type != value_t::number_float) { // multiply last value by ten and add the new digit - auto temp = value * 10 + *curptr - 0x30; + auto temp = value * 10 + *curptr - '0'; // test for overflow if (temp < value || temp > max) @@ -7998,7 +8047,8 @@ class basic_json if (t != last_token) { std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + + "'") : lexer::token_type_name(last_token)); error_msg += "; expected " + lexer::token_type_name(t); throw std::invalid_argument(error_msg); @@ -8010,7 +8060,8 @@ class basic_json if (t == last_token) { std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") : + error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + + "'") : lexer::token_type_name(last_token)); throw std::invalid_argument(error_msg); } From 6e1347e68c9d03f3b2563ed972e77c03d688a151 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 1 Jul 2016 16:58:50 +0200 Subject: [PATCH 13/48] fixes #270 --- README.md | 1 + src/json.hpp | 9 ++++----- src/json.hpp.re2c | 11 ++++------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 4ad40373b..f6b840839 100644 --- a/README.md +++ b/README.md @@ -485,6 +485,7 @@ I deeply appreciate the help of the following people. - [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal). - [Mário Feroldi](https://github.com/thelostt) fixed a small typo. - [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release. +- [Damien](https://github.com/dtoma) fixed one of the last conversion warnings. Thanks a lot for helping out! diff --git a/src/json.hpp b/src/json.hpp index 35bdd293c..a6775e53e 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -5957,16 +5957,15 @@ class basic_json { // convert a number 0..15 to its hex representation // (0..f) - const auto hexify = [](const int v) -> char + static const char hexify[16] = { - return (v < 10) - ? ('0' + static_cast(v)) - : ('a' + static_cast((v - 10) & 0x1f)); + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; // print character c as \uxxxx for (const char m : - { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f) + { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f] }) { result[++pos] = m; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index adc2e188c..1967f6a81 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -5957,18 +5957,15 @@ class basic_json { // convert a number 0..15 to its hex representation // (0..f) - const auto hexify = [](const int v) -> char + static const char hexify[16] = { - static const char hex[16] = { '0', '1', '2', '3', - '4', '5', '6', '7', - '8', '9', 'a', 'b', - 'c', 'd', 'e', 'f' }; - return hex[v]; + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; // print character c as \uxxxx for (const char m : - { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f) + { 'u', '0', '0', hexify[c >> 4], hexify[c & 0x0f] }) { result[++pos] = m; From 28644bada007985dfb3002bbd1a7f7573b144633 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 1 Jul 2016 17:25:56 +0200 Subject: [PATCH 14/48] removed std::out output from test cases --- test/src/unit.cpp | 409 +++++++++++++++++++++++----------------------- 1 file changed, 209 insertions(+), 200 deletions(-) diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 3b8909ac7..a12f0529a 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -10309,252 +10309,261 @@ TEST_CASE("parser class") TEST_CASE("README", "[hide]") { { - // create an empty structure (null) - json j; - - // add a number that is stored as double (note the implicit conversion of j to an object) - j["pi"] = 3.141; - - // add a Boolean that is stored as bool - j["happy"] = true; - - // add a string that is stored as std::string - j["name"] = "Niels"; - - // add another null object by passing nullptr - j["nothing"] = nullptr; - - // add an object inside the object - j["answer"]["everything"] = 42; - - // add an array that is stored as std::vector (using an initializer list) - j["list"] = { 1, 0, 2 }; - - // add another object (using an initializer list of pairs) - j["object"] = { {"currency", "USD"}, {"value", 42.99} }; - - // instead, you could also write (which looks very similar to the JSON above) - json j2 = + // redirect std::cout for the README file + auto old_cout_buffer = std::cout.rdbuf(); + std::ostringstream new_stream; + std::cout.rdbuf(new_stream.rdbuf()); { - {"pi", 3.141}, - {"happy", true}, - {"name", "Niels"}, - {"nothing", nullptr}, + // create an empty structure (null) + json j; + + // add a number that is stored as double (note the implicit conversion of j to an object) + j["pi"] = 3.141; + + // add a Boolean that is stored as bool + j["happy"] = true; + + // add a string that is stored as std::string + j["name"] = "Niels"; + + // add another null object by passing nullptr + j["nothing"] = nullptr; + + // add an object inside the object + j["answer"]["everything"] = 42; + + // add an array that is stored as std::vector (using an initializer list) + j["list"] = { 1, 0, 2 }; + + // add another object (using an initializer list of pairs) + j["object"] = { {"currency", "USD"}, {"value", 42.99} }; + + // instead, you could also write (which looks very similar to the JSON above) + json j2 = { - "answer", { - {"everything", 42} + {"pi", 3.141}, + {"happy", true}, + {"name", "Niels"}, + {"nothing", nullptr}, + { + "answer", { + {"everything", 42} + } + }, + {"list", {1, 0, 2}}, + { + "object", { + {"currency", "USD"}, + {"value", 42.99} + } } - }, - {"list", {1, 0, 2}}, - { - "object", { - {"currency", "USD"}, - {"value", 42.99} - } - } - }; - } + }; + } - { - // ways to express the empty array [] - json empty_array_implicit = {{}}; - json empty_array_explicit = json::array(); + { + // ways to express the empty array [] + json empty_array_implicit = {{}}; + json empty_array_explicit = json::array(); - // a way to express the empty object {} - json empty_object_explicit = json::object(); + // a way to express the empty object {} + json empty_object_explicit = json::object(); - // a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]] - json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) }; - } + // a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]] + json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) }; + } - { - // create object from string literal - json j = "{ \"happy\": true, \"pi\": 3.141 }"_json; + { + // create object from string literal + json j = "{ \"happy\": true, \"pi\": 3.141 }"_json; - // or even nicer with a raw string literal - auto j2 = R"( + // or even nicer with a raw string literal + auto j2 = R"( { "happy": true, "pi": 3.141 } )"_json; - // or explicitly - auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }"); + // or explicitly + auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }"); - // explicit conversion to string - std::string s = j.dump(); // {\"happy\":true,\"pi\":3.141} + // explicit conversion to string + std::string s = j.dump(); // {\"happy\":true,\"pi\":3.141} - // serialization with pretty printing - // pass in the amount of spaces to indent - std::cout << j.dump(4) << std::endl; - // { - // "happy": true, - // "pi": 3.141 - // } + // serialization with pretty printing + // pass in the amount of spaces to indent + std::cout << j.dump(4) << std::endl; + // { + // "happy": true, + // "pi": 3.141 + // } - std::cout << std::setw(2) << j << std::endl; - } - - { - // create an array using push_back - json j; - j.push_back("foo"); - j.push_back(1); - j.push_back(true); - - // iterate the array - for (json::iterator it = j.begin(); it != j.end(); ++it) - { - std::cout << *it << '\n'; + std::cout << std::setw(2) << j << std::endl; } - // range-based for - for (auto element : j) { - std::cout << element << '\n'; + // create an array using push_back + json j; + j.push_back("foo"); + j.push_back(1); + j.push_back(true); + + // iterate the array + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + std::cout << *it << '\n'; + } + + // range-based for + for (auto element : j) + { + std::cout << element << '\n'; + } + + // getter/setter + const std::string tmp = j[0]; + j[1] = 42; + bool foo = j.at(2); + + // other stuff + j.size(); // 3 entries + j.empty(); // false + j.type(); // json::value_t::array + j.clear(); // the array is empty again + + // comparison + j == "[\"foo\", 1, true]"_json; // true + + // create an object + json o; + o["foo"] = 23; + o["bar"] = false; + o["baz"] = 3.141; + + // find an entry + if (o.find("foo") != o.end()) + { + // there is an entry with key "foo" + } } - // getter/setter - const std::string tmp = j[0]; - j[1] = 42; - bool foo = j.at(2); - - // other stuff - j.size(); // 3 entries - j.empty(); // false - j.type(); // json::value_t::array - j.clear(); // the array is empty again - - // comparison - j == "[\"foo\", 1, true]"_json; // true - - // create an object - json o; - o["foo"] = 23; - o["bar"] = false; - o["baz"] = 3.141; - - // find an entry - if (o.find("foo") != o.end()) { - // there is an entry with key "foo" + std::vector c_vector {1, 2, 3, 4}; + json j_vec(c_vector); + // [1, 2, 3, 4] + + std::deque c_deque {1.2f, 2.3f, 3.4f, 5.6f}; + json j_deque(c_deque); + // [1.2, 2.3, 3.4, 5.6] + + std::list c_list {true, true, false, true}; + json j_list(c_list); + // [true, true, false, true] + + std::forward_list c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543}; + json j_flist(c_flist); + // [12345678909876, 23456789098765, 34567890987654, 45678909876543] + + std::array c_array {{1, 2, 3, 4}}; + json j_array(c_array); + // [1, 2, 3, 4] + + std::set c_set {"one", "two", "three", "four", "one"}; + json j_set(c_set); // only one entry for "one" is used + // ["four", "one", "three", "two"] + + std::unordered_set c_uset {"one", "two", "three", "four", "one"}; + json j_uset(c_uset); // only one entry for "one" is used + // maybe ["two", "three", "four", "one"] + + std::multiset c_mset {"one", "two", "one", "four"}; + json j_mset(c_mset); // only one entry for "one" is used + // maybe ["one", "two", "four"] + + std::unordered_multiset c_umset {"one", "two", "one", "four"}; + json j_umset(c_umset); // both entries for "one" are used + // maybe ["one", "two", "one", "four"] } - } - { - std::vector c_vector {1, 2, 3, 4}; - json j_vec(c_vector); - // [1, 2, 3, 4] + { + std::map c_map { {"one", 1}, {"two", 2}, {"three", 3} }; + json j_map(c_map); + // {"one": 1, "two": 2, "three": 3} - std::deque c_deque {1.2f, 2.3f, 3.4f, 5.6f}; - json j_deque(c_deque); - // [1.2, 2.3, 3.4, 5.6] + std::unordered_map c_umap { {"one", 1.2f}, {"two", 2.3f}, {"three", 3.4f} }; + json j_umap(c_umap); + // {"one": 1.2, "two": 2.3, "three": 3.4} - std::list c_list {true, true, false, true}; - json j_list(c_list); - // [true, true, false, true] + std::multimap c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; + json j_mmap(c_mmap); // only one entry for key "three" is used + // maybe {"one": true, "two": true, "three": true} - std::forward_list c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543}; - json j_flist(c_flist); - // [12345678909876, 23456789098765, 34567890987654, 45678909876543] + std::unordered_multimap c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; + json j_ummap(c_ummap); // only one entry for key "three" is used + // maybe {"one": true, "two": true, "three": true} + } - std::array c_array {{1, 2, 3, 4}}; - json j_array(c_array); - // [1, 2, 3, 4] + { + // strings + std::string s1 = "Hello, world!"; + json js = s1; + std::string s2 = js; - std::set c_set {"one", "two", "three", "four", "one"}; - json j_set(c_set); // only one entry for "one" is used - // ["four", "one", "three", "two"] + // Booleans + bool b1 = true; + json jb = b1; + bool b2 = jb; - std::unordered_set c_uset {"one", "two", "three", "four", "one"}; - json j_uset(c_uset); // only one entry for "one" is used - // maybe ["two", "three", "four", "one"] + // numbers + int i = 42; + json jn = i; + double f = jn; - std::multiset c_mset {"one", "two", "one", "four"}; - json j_mset(c_mset); // only one entry for "one" is used - // maybe ["one", "two", "four"] + // etc. - std::unordered_multiset c_umset {"one", "two", "one", "four"}; - json j_umset(c_umset); // both entries for "one" are used - // maybe ["one", "two", "one", "four"] - } + std::string vs = js.get(); + bool vb = jb.get(); + int vi = jn.get(); - { - std::map c_map { {"one", 1}, {"two", 2}, {"three", 3} }; - json j_map(c_map); - // {"one": 1, "two": 2, "three": 3} + // etc. + } - std::unordered_map c_umap { {"one", 1.2f}, {"two", 2.3f}, {"three", 3.4f} }; - json j_umap(c_umap); - // {"one": 1.2, "two": 2.3, "three": 3.4} - - std::multimap c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; - json j_mmap(c_mmap); // only one entry for key "three" is used - // maybe {"one": true, "two": true, "three": true} - - std::unordered_multimap c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; - json j_ummap(c_ummap); // only one entry for key "three" is used - // maybe {"one": true, "two": true, "three": true} - } - - { - // strings - std::string s1 = "Hello, world!"; - json js = s1; - std::string s2 = js; - - // Booleans - bool b1 = true; - json jb = b1; - bool b2 = jb; - - // numbers - int i = 42; - json jn = i; - double f = jn; - - // etc. - - std::string vs = js.get(); - bool vb = jb.get(); - int vi = jn.get(); - - // etc. - } - - { - // a JSON value - json j_original = R"({ + { + // a JSON value + json j_original = R"({ "baz": ["one", "two", "three"], "foo": "bar" })"_json; - // access members with a JSON pointer (RFC 6901) - j_original["/baz/1"_json_pointer]; - // "two" + // access members with a JSON pointer (RFC 6901) + j_original["/baz/1"_json_pointer]; + // "two" - // a JSON patch (RFC 6902) - json j_patch = R"([ + // a JSON patch (RFC 6902) + json j_patch = R"([ { "op": "replace", "path": "/baz", "value": "boo" }, { "op": "add", "path": "/hello", "value": ["world"] }, { "op": "remove", "path": "/foo"} ])"_json; - // apply the patch - json j_result = j_original.patch(j_patch); - // { - // "baz": "boo", - // "hello": ["world"] - // } + // apply the patch + json j_result = j_original.patch(j_patch); + // { + // "baz": "boo", + // "hello": ["world"] + // } - // calculate a JSON patch from two JSON values - json::diff(j_result, j_original); - // [ - // { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] }, - // { "op":"remove","path":"/hello" }, - // { "op":"add","path":"/foo","value":"bar" } - // ] + // calculate a JSON patch from two JSON values + json::diff(j_result, j_original); + // [ + // { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] }, + // { "op":"remove","path":"/hello" }, + // { "op":"add","path":"/foo","value":"bar" } + // ] + } + + // restore old std::cout + std::cout.rdbuf(old_cout_buffer); } } From bd7cd330cddb78fd873e10f2d46bb16a47bfe947 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 1 Jul 2016 17:26:09 +0200 Subject: [PATCH 15/48] fixed type_name() signature --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index a6775e53e..3cf3a1394 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -5801,7 +5801,7 @@ class basic_json /////////////////////////// /// return the type as string - string_t type_name() const noexcept + std::string type_name() const { switch (m_type) { diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 1967f6a81..15ab97e64 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -5801,7 +5801,7 @@ class basic_json /////////////////////////// /// return the type as string - string_t type_name() const noexcept + std::string type_name() const { switch (m_type) { From 98d48ef0c20f2c86f3344e98939f7d33a3e8ec5f Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 4 Jul 2016 00:04:22 +0200 Subject: [PATCH 16/48] fixed indentation --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f6b840839..24f6d7ab9 100644 --- a/README.md +++ b/README.md @@ -344,8 +344,8 @@ json j_result = j_original.patch(j_patch); json::diff(j_result, j_original); // [ // { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] }, -// { "op":"remove","path":"/hello" }, -// { "op":"add","path":"/foo","value":"bar" } +// { "op": "remove","path": "/hello" }, +// { "op": "add", "path": "/foo", "value": "bar" } // ] ``` From 01f9ee5fd7f9d3a52baa8984ea5b2bcbf6428b0a Mon Sep 17 00:00:00 2001 From: Muri Nicanor Date: Sat, 9 Jul 2016 20:02:41 +0200 Subject: [PATCH 17/48] let the makefile choose the correct sed --- doc/Makefile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 5e5459a00..1fb17cfc3 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,4 +1,5 @@ SRCDIR = ../src +SED:=$(shell command -v sed || gsed) all: doxygen @@ -52,10 +53,10 @@ clean: # create Doxygen documentation doxygen: create_output create_links doxygen - gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html - gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html - gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html - gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html upload: clean doxygen check_output cd html ; ../scripts/git-update-ghpages nlohmann/json @@ -70,14 +71,14 @@ upload: clean doxygen check_output # create docset for Dash docset: create_output cp Doxyfile Doxyfile_docset - gsed -i 's/DISABLE_INDEX = NO/DISABLE_INDEX = YES/' Doxyfile_docset - gsed -i 's/SEARCHENGINE = YES/SEARCHENGINE = NO/' Doxyfile_docset - gsed -i 's@HTML_EXTRA_STYLESHEET = css/mylayout.css@HTML_EXTRA_STYLESHEET = css/mylayout_docset.css@' Doxyfile_docset + $(SED) -i 's/DISABLE_INDEX = NO/DISABLE_INDEX = YES/' Doxyfile_docset + $(SED) -i 's/SEARCHENGINE = YES/SEARCHENGINE = NO/' Doxyfile_docset + $(SED) -i 's@HTML_EXTRA_STYLESHEET = css/mylayout.css@HTML_EXTRA_STYLESHEET = css/mylayout_docset.css@' Doxyfile_docset rm -fr html *.docset doxygen Doxyfile_docset - gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html - gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html make -C html mv html/*.docset . - gsed -i 's@doxygen@json@' me.nlohmann.json.docset/Contents/Info.plist + $(SED) -i 's@doxygen@json@' me.nlohmann.json.docset/Contents/Info.plist rm -fr Doxyfile_docset html From 7f4dd5d6088b7f1cb95acb31d8c4f31503193b64 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 15 Jul 2016 19:44:19 +0200 Subject: [PATCH 18/48] added header for int64_t and uint64_t (fixes #282) --- src/json.hpp | 1 + src/json.hpp.re2c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/json.hpp b/src/json.hpp index ba7d82122..44c867c08 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -37,6 +37,7 @@ SOFTWARE. #include #include #include +#include #include #include #include diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 5ee270f91..dffce54c9 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -37,6 +37,7 @@ SOFTWARE. #include #include #include +#include #include #include #include From b64367e2f76aa38f6a745e7167fc93fb1c9183fb Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 18 Jul 2016 16:22:10 +0200 Subject: [PATCH 19/48] fix for #279 --- doc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Makefile b/doc/Makefile index 1fb17cfc3..561989237 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,5 +1,5 @@ SRCDIR = ../src -SED:=$(shell command -v sed || gsed) +SED:=$(shell command -v gsed || which sed) all: doxygen From 2478be807c8b3fb28674fa2fb63a5e1263ea3c4a Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 19 Jul 2016 22:10:27 +0200 Subject: [PATCH 20/48] avoid recursion in the scanner --- src/json.hpp | 1256 +++++++++++++++++++++++---------------------- src/json.hpp.re2c | 127 ++--- 2 files changed, 705 insertions(+), 678 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 44c867c08..1311080bb 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7393,400 +7393,402 @@ class basic_json */ token_type scan() noexcept { - // pointer for backtracking information - m_marker = nullptr; - - // remember the begin of the token - m_start = m_cursor; - assert(m_start != nullptr); - - + while (true) { - lexer_char_t yych; - unsigned int yyaccept = 0; - static const unsigned char yybm[] = + // pointer for backtracking information + m_marker = nullptr; + + // remember the begin of the token + m_start = m_cursor; + assert(m_start != nullptr); + + { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 32, 0, 0, 32, 0, 0, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 160, 128, 0, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 0, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - }; - if ((m_limit - m_cursor) < 5) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_6; - } - if (yych <= '\\') - { - if (yych <= '-') + lexer_char_t yych; + unsigned int yyaccept = 0; + static const unsigned char yybm[] = { - if (yych <= '"') + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 32, 0, 0, 32, 0, 0, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 160, 128, 0, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + }; + if ((m_limit - m_cursor) < 5) + { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yybm[0 + yych] & 32) + { + goto basic_json_parser_6; + } + if (yych <= '\\') + { + if (yych <= '-') { - if (yych <= 0x00) + if (yych <= '"') { - goto basic_json_parser_2; + if (yych <= 0x00) + { + goto basic_json_parser_2; + } + if (yych <= '!') + { + goto basic_json_parser_4; + } + goto basic_json_parser_9; } - if (yych <= '!') + else { - goto basic_json_parser_4; + if (yych <= '+') + { + goto basic_json_parser_4; + } + if (yych <= ',') + { + goto basic_json_parser_10; + } + goto basic_json_parser_12; } - goto basic_json_parser_9; } else { - if (yych <= '+') + if (yych <= '9') { + if (yych <= '/') + { + goto basic_json_parser_4; + } + if (yych <= '0') + { + goto basic_json_parser_13; + } + goto basic_json_parser_15; + } + else + { + if (yych <= ':') + { + goto basic_json_parser_17; + } + if (yych == '[') + { + goto basic_json_parser_19; + } goto basic_json_parser_4; } - if (yych <= ',') - { - goto basic_json_parser_10; - } - goto basic_json_parser_12; } } else { - if (yych <= '9') + if (yych <= 't') { - if (yych <= '/') + if (yych <= 'f') { - goto basic_json_parser_4; + if (yych <= ']') + { + goto basic_json_parser_21; + } + if (yych <= 'e') + { + goto basic_json_parser_4; + } + goto basic_json_parser_23; } - if (yych <= '0') + else { - goto basic_json_parser_13; + if (yych == 'n') + { + goto basic_json_parser_24; + } + if (yych <= 's') + { + goto basic_json_parser_4; + } + goto basic_json_parser_25; } - goto basic_json_parser_15; } else { - if (yych <= ':') - { - goto basic_json_parser_17; - } - if (yych == '[') - { - goto basic_json_parser_19; - } - goto basic_json_parser_4; - } - } - } - else - { - if (yych <= 't') - { - if (yych <= 'f') - { - if (yych <= ']') - { - goto basic_json_parser_21; - } - if (yych <= 'e') + if (yych <= '|') { + if (yych == '{') + { + goto basic_json_parser_26; + } goto basic_json_parser_4; } - goto basic_json_parser_23; - } - else - { - if (yych == 'n') - { - goto basic_json_parser_24; - } - if (yych <= 's') + else { + if (yych <= '}') + { + goto basic_json_parser_28; + } + if (yych == 0xEF) + { + goto basic_json_parser_30; + } goto basic_json_parser_4; } - goto basic_json_parser_25; } } - else - { - if (yych <= '|') - { - if (yych == '{') - { - goto basic_json_parser_26; - } - goto basic_json_parser_4; - } - else - { - if (yych <= '}') - { - goto basic_json_parser_28; - } - if (yych == 0xEF) - { - goto basic_json_parser_30; - } - goto basic_json_parser_4; - } - } - } basic_json_parser_2: - ++m_cursor; - { - return token_type::end_of_input; - } + ++m_cursor; + { + last_token_type = token_type::end_of_input; + break; + } basic_json_parser_4: - ++m_cursor; + ++m_cursor; basic_json_parser_5: - { - return token_type::parse_error; - } + { + last_token_type = token_type::parse_error; + break; + } basic_json_parser_6: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_6; - } - { - return scan(); - } + ++m_cursor; + if (m_limit <= m_cursor) + { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yybm[0 + yych] & 32) + { + goto basic_json_parser_6; + } + { + continue; + } basic_json_parser_9: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych <= 0x0F) - { - goto basic_json_parser_5; - } - goto basic_json_parser_32; + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych <= 0x0F) + { + goto basic_json_parser_5; + } + goto basic_json_parser_32; basic_json_parser_10: - ++m_cursor; - { - return token_type::value_separator; - } + ++m_cursor; + { + last_token_type = token_type::value_separator; + break; + } basic_json_parser_12: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_5; - } - if (yych <= '0') - { - goto basic_json_parser_13; - } - if (yych <= '9') - { - goto basic_json_parser_15; - } - goto basic_json_parser_5; -basic_json_parser_13: - yyaccept = 1; - yych = *(m_marker = ++m_cursor); - if (yych <= 'D') - { - if (yych == '.') - { - goto basic_json_parser_37; - } - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_38; - } - if (yych == 'e') - { - goto basic_json_parser_38; - } - } -basic_json_parser_14: - { - return token_type::value_number; - } -basic_json_parser_15: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yybm[0 + yych] & 64) - { - goto basic_json_parser_15; - } - if (yych <= 'D') - { - if (yych == '.') - { - goto basic_json_parser_37; - } - goto basic_json_parser_14; - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_38; - } - if (yych == 'e') - { - goto basic_json_parser_38; - } - goto basic_json_parser_14; - } -basic_json_parser_17: - ++m_cursor; - { - return token_type::name_separator; - } -basic_json_parser_19: - ++m_cursor; - { - return token_type::begin_array; - } -basic_json_parser_21: - ++m_cursor; - { - return token_type::end_array; - } -basic_json_parser_23: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'a') - { - goto basic_json_parser_39; - } - goto basic_json_parser_5; -basic_json_parser_24: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'u') - { - goto basic_json_parser_40; - } - goto basic_json_parser_5; -basic_json_parser_25: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'r') - { - goto basic_json_parser_41; - } - goto basic_json_parser_5; -basic_json_parser_26: - ++m_cursor; - { - return token_type::begin_object; - } -basic_json_parser_28: - ++m_cursor; - { - return token_type::end_object; - } -basic_json_parser_30: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 0xBB) - { - goto basic_json_parser_42; - } - goto basic_json_parser_5; -basic_json_parser_31: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; -basic_json_parser_32: - if (yybm[0 + yych] & 128) - { - goto basic_json_parser_31; - } - if (yych <= 0x0F) - { - goto basic_json_parser_33; - } - if (yych <= '"') - { - goto basic_json_parser_34; - } - goto basic_json_parser_36; -basic_json_parser_33: - m_cursor = m_marker; - if (yyaccept == 0) - { - goto basic_json_parser_5; - } - else - { - goto basic_json_parser_14; - } -basic_json_parser_34: - ++m_cursor; - { - return token_type::value_string; - } -basic_json_parser_36: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= 'e') - { + yych = *++m_cursor; if (yych <= '/') { - if (yych == '"') + goto basic_json_parser_5; + } + if (yych <= '0') + { + goto basic_json_parser_13; + } + if (yych <= '9') + { + goto basic_json_parser_15; + } + goto basic_json_parser_5; +basic_json_parser_13: + yyaccept = 1; + yych = *(m_marker = ++m_cursor); + if (yych <= 'D') + { + if (yych == '.') { - goto basic_json_parser_31; + goto basic_json_parser_37; } - if (yych <= '.') - { - goto basic_json_parser_33; - } - goto basic_json_parser_31; } else { - if (yych <= '\\') + if (yych <= 'E') { - if (yych <= '[') + goto basic_json_parser_38; + } + if (yych == 'e') + { + goto basic_json_parser_38; + } + } +basic_json_parser_14: + { + last_token_type = token_type::value_number; + break; + } +basic_json_parser_15: + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yybm[0 + yych] & 64) + { + goto basic_json_parser_15; + } + if (yych <= 'D') + { + if (yych == '.') + { + goto basic_json_parser_37; + } + goto basic_json_parser_14; + } + else + { + if (yych <= 'E') + { + goto basic_json_parser_38; + } + if (yych == 'e') + { + goto basic_json_parser_38; + } + goto basic_json_parser_14; + } +basic_json_parser_17: + ++m_cursor; + { + last_token_type = token_type::name_separator; + break; + } +basic_json_parser_19: + ++m_cursor; + { + last_token_type = token_type::begin_array; + break; + } +basic_json_parser_21: + ++m_cursor; + { + last_token_type = token_type::end_array; + break; + } +basic_json_parser_23: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'a') + { + goto basic_json_parser_39; + } + goto basic_json_parser_5; +basic_json_parser_24: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'u') + { + goto basic_json_parser_40; + } + goto basic_json_parser_5; +basic_json_parser_25: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'r') + { + goto basic_json_parser_41; + } + goto basic_json_parser_5; +basic_json_parser_26: + ++m_cursor; + { + last_token_type = token_type::begin_object; + break; + } +basic_json_parser_28: + ++m_cursor; + { + last_token_type = token_type::end_object; + break; + } +basic_json_parser_30: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 0xBB) + { + goto basic_json_parser_42; + } + goto basic_json_parser_5; +basic_json_parser_31: + ++m_cursor; + if (m_limit <= m_cursor) + { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; +basic_json_parser_32: + if (yybm[0 + yych] & 128) + { + goto basic_json_parser_31; + } + if (yych <= 0x0F) + { + goto basic_json_parser_33; + } + if (yych <= '"') + { + goto basic_json_parser_34; + } + goto basic_json_parser_36; +basic_json_parser_33: + m_cursor = m_marker; + if (yyaccept == 0) + { + goto basic_json_parser_5; + } + else + { + goto basic_json_parser_14; + } +basic_json_parser_34: + ++m_cursor; + { + last_token_type = token_type::value_string; + break; + } +basic_json_parser_36: + ++m_cursor; + if (m_limit <= m_cursor) + { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yych <= 'e') + { + if (yych <= '/') + { + if (yych == '"') + { + goto basic_json_parser_31; + } + if (yych <= '.') { goto basic_json_parser_33; } @@ -7794,33 +7796,33 @@ basic_json_parser_36: } else { - if (yych == 'b') + if (yych <= '\\') { + if (yych <= '[') + { + goto basic_json_parser_33; + } goto basic_json_parser_31; } - goto basic_json_parser_33; + else + { + if (yych == 'b') + { + goto basic_json_parser_31; + } + goto basic_json_parser_33; + } } } - } - else - { - if (yych <= 'q') - { - if (yych <= 'f') - { - goto basic_json_parser_31; - } - if (yych == 'n') - { - goto basic_json_parser_31; - } - goto basic_json_parser_33; - } else { - if (yych <= 's') + if (yych <= 'q') { - if (yych <= 'r') + if (yych <= 'f') + { + goto basic_json_parser_31; + } + if (yych == 'n') { goto basic_json_parser_31; } @@ -7828,331 +7830,347 @@ basic_json_parser_36: } else { - if (yych <= 't') + if (yych <= 's') { - goto basic_json_parser_31; + if (yych <= 'r') + { + goto basic_json_parser_31; + } + goto basic_json_parser_33; } - if (yych <= 'u') + else { - goto basic_json_parser_43; + if (yych <= 't') + { + goto basic_json_parser_31; + } + if (yych <= 'u') + { + goto basic_json_parser_43; + } + goto basic_json_parser_33; } - goto basic_json_parser_33; } } - } basic_json_parser_37: - yych = *++m_cursor; - if (yych <= '/') - { + yych = *++m_cursor; + if (yych <= '/') + { + goto basic_json_parser_33; + } + if (yych <= '9') + { + goto basic_json_parser_44; + } goto basic_json_parser_33; - } - if (yych <= '9') - { - goto basic_json_parser_44; - } - goto basic_json_parser_33; basic_json_parser_38: - yych = *++m_cursor; - if (yych <= ',') - { - if (yych == '+') - { - goto basic_json_parser_46; - } - goto basic_json_parser_33; - } - else - { - if (yych <= '-') - { - goto basic_json_parser_46; - } - if (yych <= '/') + yych = *++m_cursor; + if (yych <= ',') { + if (yych == '+') + { + goto basic_json_parser_46; + } goto basic_json_parser_33; } - if (yych <= '9') + else { - goto basic_json_parser_47; + if (yych <= '-') + { + goto basic_json_parser_46; + } + if (yych <= '/') + { + goto basic_json_parser_33; + } + if (yych <= '9') + { + goto basic_json_parser_47; + } + goto basic_json_parser_33; } - goto basic_json_parser_33; - } basic_json_parser_39: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_49; - } - goto basic_json_parser_33; + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_49; + } + goto basic_json_parser_33; basic_json_parser_40: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_50; - } - goto basic_json_parser_33; + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_50; + } + goto basic_json_parser_33; basic_json_parser_41: - yych = *++m_cursor; - if (yych == 'u') - { - goto basic_json_parser_51; - } - goto basic_json_parser_33; + yych = *++m_cursor; + if (yych == 'u') + { + goto basic_json_parser_51; + } + goto basic_json_parser_33; basic_json_parser_42: - yych = *++m_cursor; - if (yych == 0xBF) - { - goto basic_json_parser_52; - } - goto basic_json_parser_33; + yych = *++m_cursor; + if (yych == 0xBF) + { + goto basic_json_parser_52; + } + goto basic_json_parser_33; basic_json_parser_43: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '@') - { + ++m_cursor; + if (m_limit <= m_cursor) + { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_33; + } + if (yych <= '9') + { + goto basic_json_parser_54; + } + goto basic_json_parser_33; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_54; + } + if (yych <= '`') + { + goto basic_json_parser_33; + } + if (yych <= 'f') + { + goto basic_json_parser_54; + } + goto basic_json_parser_33; + } +basic_json_parser_44: + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yych <= 'D') + { + if (yych <= '/') + { + goto basic_json_parser_14; + } + if (yych <= '9') + { + goto basic_json_parser_44; + } + goto basic_json_parser_14; + } + else + { + if (yych <= 'E') + { + goto basic_json_parser_38; + } + if (yych == 'e') + { + goto basic_json_parser_38; + } + goto basic_json_parser_14; + } +basic_json_parser_46: + yych = *++m_cursor; if (yych <= '/') { goto basic_json_parser_33; } - if (yych <= '9') - { - goto basic_json_parser_54; - } - goto basic_json_parser_33; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_54; - } - if (yych <= '`') + if (yych >= ':') { goto basic_json_parser_33; } - if (yych <= 'f') +basic_json_parser_47: + ++m_cursor; + if (m_limit <= m_cursor) { - goto basic_json_parser_54; + yyfill(); // LCOV_EXCL_LINE; } - goto basic_json_parser_33; - } -basic_json_parser_44: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= 'D') - { + yych = *m_cursor; if (yych <= '/') { goto basic_json_parser_14; } if (yych <= '9') { - goto basic_json_parser_44; + goto basic_json_parser_47; } goto basic_json_parser_14; - } - else - { - if (yych <= 'E') +basic_json_parser_49: + yych = *++m_cursor; + if (yych == 's') { - goto basic_json_parser_38; + goto basic_json_parser_55; } + goto basic_json_parser_33; +basic_json_parser_50: + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_56; + } + goto basic_json_parser_33; +basic_json_parser_51: + yych = *++m_cursor; if (yych == 'e') { - goto basic_json_parser_38; + goto basic_json_parser_58; } - goto basic_json_parser_14; - } -basic_json_parser_46: - yych = *++m_cursor; - if (yych <= '/') - { goto basic_json_parser_33; - } - if (yych >= ':') - { - goto basic_json_parser_33; - } -basic_json_parser_47: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '/') - { - goto basic_json_parser_14; - } - if (yych <= '9') - { - goto basic_json_parser_47; - } - goto basic_json_parser_14; -basic_json_parser_49: - yych = *++m_cursor; - if (yych == 's') - { - goto basic_json_parser_55; - } - goto basic_json_parser_33; -basic_json_parser_50: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_56; - } - goto basic_json_parser_33; -basic_json_parser_51: - yych = *++m_cursor; - if (yych == 'e') - { - goto basic_json_parser_58; - } - goto basic_json_parser_33; basic_json_parser_52: - ++m_cursor; - { - return scan(); - } + ++m_cursor; + { + continue; + } basic_json_parser_54: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') + ++m_cursor; + if (m_limit <= m_cursor) { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_33; + } + if (yych <= '9') + { + goto basic_json_parser_60; + } goto basic_json_parser_33; } - if (yych <= '9') - { - goto basic_json_parser_60; - } - goto basic_json_parser_33; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_60; - } - if (yych <= '`') + else { + if (yych <= 'F') + { + goto basic_json_parser_60; + } + if (yych <= '`') + { + goto basic_json_parser_33; + } + if (yych <= 'f') + { + goto basic_json_parser_60; + } goto basic_json_parser_33; } - if (yych <= 'f') - { - goto basic_json_parser_60; - } - goto basic_json_parser_33; - } basic_json_parser_55: - yych = *++m_cursor; - if (yych == 'e') - { - goto basic_json_parser_61; - } - goto basic_json_parser_33; + yych = *++m_cursor; + if (yych == 'e') + { + goto basic_json_parser_61; + } + goto basic_json_parser_33; basic_json_parser_56: - ++m_cursor; - { - return token_type::literal_null; - } + ++m_cursor; + { + last_token_type = token_type::literal_null; + break; + } basic_json_parser_58: - ++m_cursor; - { - return token_type::literal_true; - } + ++m_cursor; + { + last_token_type = token_type::literal_true; + break; + } basic_json_parser_60: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') + ++m_cursor; + if (m_limit <= m_cursor) { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_33; + } + if (yych <= '9') + { + goto basic_json_parser_63; + } goto basic_json_parser_33; } - if (yych <= '9') - { - goto basic_json_parser_63; - } - goto basic_json_parser_33; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_63; - } - if (yych <= '`') + else { + if (yych <= 'F') + { + goto basic_json_parser_63; + } + if (yych <= '`') + { + goto basic_json_parser_33; + } + if (yych <= 'f') + { + goto basic_json_parser_63; + } goto basic_json_parser_33; } - if (yych <= 'f') - { - goto basic_json_parser_63; - } - goto basic_json_parser_33; - } basic_json_parser_61: - ++m_cursor; - { - return token_type::literal_false; - } + ++m_cursor; + { + last_token_type = token_type::literal_false; + break; + } basic_json_parser_63: - ++m_cursor; - if (m_limit <= m_cursor) - { - yyfill(); // LCOV_EXCL_LINE; - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') + ++m_cursor; + if (m_limit <= m_cursor) { + yyfill(); // LCOV_EXCL_LINE; + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_33; + } + if (yych <= '9') + { + goto basic_json_parser_31; + } goto basic_json_parser_33; } - if (yych <= '9') - { - goto basic_json_parser_31; - } - goto basic_json_parser_33; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_31; - } - if (yych <= '`') + else { + if (yych <= 'F') + { + goto basic_json_parser_31; + } + if (yych <= '`') + { + goto basic_json_parser_33; + } + if (yych <= 'f') + { + goto basic_json_parser_31; + } goto basic_json_parser_33; } - if (yych <= 'f') - { - goto basic_json_parser_31; - } - goto basic_json_parser_33; } + } + return last_token_type; } /// append data from the stream to the internal buffer @@ -8500,6 +8518,8 @@ basic_json_parser_63: const lexer_char_t* m_cursor = nullptr; /// pointer to the end of the buffer const lexer_char_t* m_limit = nullptr; + /// the last token type + token_type last_token_type = token_type::end_of_input; }; /*! diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index dffce54c9..a65e41bf1 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7393,76 +7393,81 @@ class basic_json */ token_type scan() noexcept { - // pointer for backtracking information - m_marker = nullptr; + while (true) + { + // pointer for backtracking information + m_marker = nullptr; - // remember the begin of the token - m_start = m_cursor; - assert(m_start != nullptr); + // remember the begin of the token + m_start = m_cursor; + assert(m_start != nullptr); - /*!re2c - re2c:define:YYCTYPE = lexer_char_t; - re2c:define:YYCURSOR = m_cursor; - re2c:define:YYLIMIT = m_limit; - re2c:define:YYMARKER = m_marker; - re2c:define:YYFILL = "yyfill(); // LCOV_EXCL_LINE"; - re2c:yyfill:parameter = 0; - re2c:indent:string = " "; - re2c:indent:top = 1; - re2c:labelprefix = "basic_json_parser_"; + /*!re2c + re2c:define:YYCTYPE = lexer_char_t; + re2c:define:YYCURSOR = m_cursor; + re2c:define:YYLIMIT = m_limit; + re2c:define:YYMARKER = m_marker; + re2c:define:YYFILL = "yyfill(); // LCOV_EXCL_LINE"; + re2c:yyfill:parameter = 0; + re2c:indent:string = " "; + re2c:indent:top = 1; + re2c:labelprefix = "basic_json_parser_"; - // ignore whitespace - ws = [ \t\n\r]+; - ws { return scan(); } + // ignore whitespace + ws = [ \t\n\r]+; + ws { continue; } - // ignore byte-order-mark - bom = "\xEF\xBB\xBF"; - bom { return scan(); } + // ignore byte-order-mark + bom = "\xEF\xBB\xBF"; + bom { continue; } - // structural characters - "[" { return token_type::begin_array; } - "]" { return token_type::end_array; } - "{" { return token_type::begin_object; } - "}" { return token_type::end_object; } - "," { return token_type::value_separator; } - ":" { return token_type::name_separator; } + // structural characters + "[" { last_token_type = token_type::begin_array; break; } + "]" { last_token_type = token_type::end_array; break; } + "{" { last_token_type = token_type::begin_object; break; } + "}" { last_token_type = token_type::end_object; break; } + "," { last_token_type = token_type::value_separator; break; } + ":" { last_token_type = token_type::name_separator; break; } - // literal names - "null" { return token_type::literal_null; } - "true" { return token_type::literal_true; } - "false" { return token_type::literal_false; } + // literal names + "null" { last_token_type = token_type::literal_null; break; } + "true" { last_token_type = token_type::literal_true; break; } + "false" { last_token_type = token_type::literal_false; break; } - // number - decimal_point = [.]; - digit = [0-9]; - digit_1_9 = [1-9]; - e = [eE]; - minus = [-]; - plus = [+]; - zero = [0]; - exp = e (minus|plus)? digit+; - frac = decimal_point digit+; - int = (zero|digit_1_9 digit*); - number = minus? int frac? exp?; - number { return token_type::value_number; } + // number + decimal_point = [.]; + digit = [0-9]; + digit_1_9 = [1-9]; + e = [eE]; + minus = [-]; + plus = [+]; + zero = [0]; + exp = e (minus|plus)? digit+; + frac = decimal_point digit+; + int = (zero|digit_1_9 digit*); + number = minus? int frac? exp?; + number { last_token_type = token_type::value_number; break; } - // string - quotation_mark = ["]; - escape = [\\]; - unescaped = [^"\\\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F]; - single_escaped = ["\\/bfnrt]; - unicode_escaped = [u][0-9a-fA-F]{4}; - escaped = escape (single_escaped | unicode_escaped); - char = unescaped | escaped; - string = quotation_mark char* quotation_mark; - string { return token_type::value_string; } + // string + quotation_mark = ["]; + escape = [\\]; + unescaped = [^"\\\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F]; + single_escaped = ["\\/bfnrt]; + unicode_escaped = [u][0-9a-fA-F]{4}; + escaped = escape (single_escaped | unicode_escaped); + char = unescaped | escaped; + string = quotation_mark char* quotation_mark; + string { last_token_type = token_type::value_string; break; } - // end of file - '\000' { return token_type::end_of_input; } + // end of file + '\000' { last_token_type = token_type::end_of_input; break; } - // anything else is an error - . { return token_type::parse_error; } - */ + // anything else is an error + . { last_token_type = token_type::parse_error; break; } + */ + } + + return last_token_type; } /// append data from the stream to the internal buffer @@ -7810,6 +7815,8 @@ class basic_json const lexer_char_t* m_cursor = nullptr; /// pointer to the end of the buffer const lexer_char_t* m_limit = nullptr; + /// the last token type + token_type last_token_type = token_type::end_of_input; }; /*! From 0f834056bb06a4859f64d7b2457849449df6f2bc Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 19 Jul 2016 22:17:43 +0200 Subject: [PATCH 21/48] removed unused header --- src/json.hpp | 1 - src/json.hpp.re2c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 1311080bb..fa14b0e71 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -36,7 +36,6 @@ SOFTWARE. #include #include #include -#include #include #include #include diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index a65e41bf1..dd1bda1fb 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -36,7 +36,6 @@ SOFTWARE. #include #include #include -#include #include #include #include From cb145cfe714769266913a2ff623b9b643984a78f Mon Sep 17 00:00:00 2001 From: Niels Date: Tue, 19 Jul 2016 22:43:56 +0200 Subject: [PATCH 22/48] updated Changelog --- ChangeLog.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 34d28e4db..e3a7cc07f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,17 @@ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased](https://github.com/nlohmann/json/tree/HEAD) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.1...HEAD) + +- Build error for std::int64 [\#282](https://github.com/nlohmann/json/issues/282) + +- hexify\(\) function emits conversion warning [\#270](https://github.com/nlohmann/json/issues/270) + +- let the makefile choose the correct sed [\#279](https://github.com/nlohmann/json/pull/279) ([murinicanor](https://github.com/murinicanor)) +- Update hexify to use array lookup instead of ternary \(\#270\) [\#275](https://github.com/nlohmann/json/pull/275) ([dtoma](https://github.com/dtoma)) + ## [v2.0.1](https://github.com/nlohmann/json/releases/tag/v2.0.1) (2016-06-28) [Full Changelog](https://github.com/nlohmann/json/compare/v2.0.0...v2.0.1) From 1286d35767448925db9ac1d6d52855da822ce2fe Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 20 Jul 2016 20:07:45 +0200 Subject: [PATCH 23/48] make sure precision is reset on output streams during serialization --- src/json.hpp | 31 ++++++++++++++++++++++--------- src/json.hpp.re2c | 31 ++++++++++++++++++++++--------- test/src/unit.cpp | 22 ++++++++++++++++++++++ 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index fa14b0e71..291553271 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -2120,6 +2120,12 @@ class basic_json // fix locale problems ss.imbue(std::locale(std::locale(), new DecimalSeparator)); + // 6, 15 or 16 digits of precision allows round-trip IEEE 754 + // string->float->string, string->double->string or string->long + // double->string; to be safe, we read this value from + // std::numeric_limits::digits10 + ss.precision(std::numeric_limits::digits10); + if (indent >= 0) { dump(ss, true, static_cast(indent)); @@ -5693,6 +5699,10 @@ class basic_json `std::setw(4)` on @a o sets the indentation level to `4` and the serialization result is the same as calling `dump(4)`. + @note During serializaion, the locale and the precision of the output + stream @a o are changed. The original values are restored when the + function returns. + @param[in,out] o stream to serialize to @param[in] j JSON value to serialize @@ -5713,14 +5723,23 @@ class basic_json // reset width to 0 for subsequent calls to this stream o.width(0); + // fix locale problems - auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator)); + const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator)); + // set precision + + // 6, 15 or 16 digits of precision allows round-trip IEEE 754 + // string->float->string, string->double->string or string->long + // double->string; to be safe, we read this value from + // std::numeric_limits::digits10 + const auto old_preicison = o.precision(std::numeric_limits::digits10); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); - // reset locale + // reset locale and precision o.imbue(old_locale); + o.precision(old_preicison); return o; } @@ -6184,13 +6203,7 @@ class basic_json } else { - // Otherwise 6, 15 or 16 digits of precision allows - // round-trip IEEE 754 string->float->string, - // string->double->string or string->long - // double->string; to be safe, we read this value from - // std::numeric_limits::digits10 - o << std::setprecision(std::numeric_limits::digits10) - << m_value.number_float; + o << m_value.number_float; } return; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index dd1bda1fb..8eeedefee 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -2120,6 +2120,12 @@ class basic_json // fix locale problems ss.imbue(std::locale(std::locale(), new DecimalSeparator)); + // 6, 15 or 16 digits of precision allows round-trip IEEE 754 + // string->float->string, string->double->string or string->long + // double->string; to be safe, we read this value from + // std::numeric_limits::digits10 + ss.precision(std::numeric_limits::digits10); + if (indent >= 0) { dump(ss, true, static_cast(indent)); @@ -5693,6 +5699,10 @@ class basic_json `std::setw(4)` on @a o sets the indentation level to `4` and the serialization result is the same as calling `dump(4)`. + @note During serializaion, the locale and the precision of the output + stream @a o are changed. The original values are restored when the + function returns. + @param[in,out] o stream to serialize to @param[in] j JSON value to serialize @@ -5713,14 +5723,23 @@ class basic_json // reset width to 0 for subsequent calls to this stream o.width(0); + // fix locale problems - auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator)); + const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator)); + // set precision + + // 6, 15 or 16 digits of precision allows round-trip IEEE 754 + // string->float->string, string->double->string or string->long + // double->string; to be safe, we read this value from + // std::numeric_limits::digits10 + const auto old_preicison = o.precision(std::numeric_limits::digits10); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); - // reset locale + // reset locale and precision o.imbue(old_locale); + o.precision(old_preicison); return o; } @@ -6184,13 +6203,7 @@ class basic_json } else { - // Otherwise 6, 15 or 16 digits of precision allows - // round-trip IEEE 754 string->float->string, - // string->double->string or string->long - // double->string; to be safe, we read this value from - // std::numeric_limits::digits10 - o << std::setprecision(std::numeric_limits::digits10) - << m_value.number_float; + o << m_value.number_float; } return; } diff --git a/test/src/unit.cpp b/test/src/unit.cpp index a12f0529a..a7ca73947 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -1685,6 +1685,28 @@ TEST_CASE("object inspection") json j_discarded(json::value_t::discarded); CHECK(j_discarded.dump() == ""); } + + SECTION("check that precision is reset after serialization") + { + // create stringstream and set precision + std::stringstream ss; + ss.precision(3); + ss << 3.141592653589793 << std::fixed; + CHECK(ss.str() == "3.14"); + + // reset stringstream + ss.str(std::string()); + + // use stringstream for JSON serialization + json j_number = 3.141592653589793; + ss << j_number; + + // check that precision has been overridden during serialization + CHECK(ss.str() == "3.141592653589793"); + + // check that precision has been restored + CHECK(ss.precision() == 3); + } } SECTION("return the type of the object (explicit)") From 4c98c971b838645416d7bac9de4e8a4d44e9d584 Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 20 Jul 2016 23:06:45 +0200 Subject: [PATCH 24/48] added benchmarks for numbers --- .gitignore | 2 ++ Makefile | 2 ++ benchmarks/benchmarks.cpp | 30 ++++++++++++++++++++++++++++ benchmarks/files/numbers/generate.py | 25 +++++++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100755 benchmarks/files/numbers/generate.py diff --git a/.gitignore b/.gitignore index d5bd2f7c9..fd41a2e3c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ me.nlohmann.json.docset android doc/xml + +benchmarks/files/numbers/*.json diff --git a/Makefile b/Makefile index 56e46d145..98f076876 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ all: json_unit # clean up clean: rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM + rm -fr benchmarks/files/numbers/*.json $(MAKE) clean -Cdoc @@ -85,6 +86,7 @@ pretty: # benchmarks json_benchmarks: benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/cxxopts.hpp src/json.hpp + cd benchmarks/files/numbers ; python generate.py $(CXX) -std=c++11 $(CXXFLAGS) -O3 -flto -I src -I benchmarks $< $(LDFLAGS) -o $@ ./json_benchmarks diff --git a/benchmarks/benchmarks.cpp b/benchmarks/benchmarks.cpp index 1f5eb5e33..ec6b462c8 100644 --- a/benchmarks/benchmarks.cpp +++ b/benchmarks/benchmarks.cpp @@ -44,6 +44,36 @@ BENCHMARK("parse twitter.json", [](benchpress::context* ctx) } }) +BENCHMARK("parse numbers/floats.json", [](benchpress::context* ctx) +{ + for (size_t i = 0; i < ctx->num_iterations(); ++i) + { + std::ifstream input_file("benchmarks/files/numbers/floats.json"); + nlohmann::json j; + j << input_file; + } +}) + +BENCHMARK("parse numbers/signed_ints.json", [](benchpress::context* ctx) +{ + for (size_t i = 0; i < ctx->num_iterations(); ++i) + { + std::ifstream input_file("benchmarks/files/numbers/signed_ints.json"); + nlohmann::json j; + j << input_file; + } +}) + +BENCHMARK("parse numbers/unsigned_ints.json", [](benchpress::context* ctx) +{ + for (size_t i = 0; i < ctx->num_iterations(); ++i) + { + std::ifstream input_file("benchmarks/files/numbers/unsigned_ints.json"); + nlohmann::json j; + j << input_file; + } +}) + BENCHMARK("dump jeopardy.json", [](benchpress::context* ctx) { std::ifstream input_file("benchmarks/files/jeopardy/jeopardy.json"); diff --git a/benchmarks/files/numbers/generate.py b/benchmarks/files/numbers/generate.py new file mode 100755 index 000000000..714ee3a1b --- /dev/null +++ b/benchmarks/files/numbers/generate.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +import json +import random +import sys + +random.seed(0) + +# floats +result_floats = [] +for x in range(0, 1000000): + result_floats.append(random.uniform(-100000000.0, 100000000.0)) +json.dump(result_floats, open("floats.json", "w"), indent=2) + +# unsigned integers +result_uints = [] +for x in range(0, 1000000): + result_uints.append(random.randint(0, 18446744073709551615)) +json.dump(result_uints, open("unsigned_ints.json", "w"), indent=2) + +# signed integers +result_sints = [] +for x in range(0, 1000000): + result_sints.append(random.randint(-9223372036854775808, 9223372036854775807)) +json.dump(result_sints, open("signed_ints.json", "w"), indent=2) From 4e7501e59aff4c9dc27b4175bdefb49319d82ed3 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 22 Jul 2016 15:34:45 +0200 Subject: [PATCH 25/48] minor changes - fixed a bug that did not discard strings with control characters between 0x10 and 0x1f - added termination proofs for two important loops - made get_ref() constexpr --- doc/images/callback_events.png | Bin 0 -> 46039 bytes src/json.hpp | 125 +++++++++++++++++++++++----- src/json.hpp.re2c | 143 ++++++++++++++++++++++++++------- test/src/unit.cpp | 33 ++++++++ 4 files changed, 248 insertions(+), 53 deletions(-) create mode 100644 doc/images/callback_events.png diff --git a/doc/images/callback_events.png b/doc/images/callback_events.png new file mode 100644 index 0000000000000000000000000000000000000000..09aa2b38355a7227b444b5b6779f2c7ca9fa05d6 GIT binary patch literal 46039 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 UkR#h1#Q*>R07*qoM6N<$f`xGfOaK4? literal 0 HcmV?d00001 diff --git a/src/json.hpp b/src/json.hpp index 291553271..00bee9709 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -717,7 +717,19 @@ class basic_json This enumeration collects the different JSON types. It is internally used to distinguish the stored values, and the functions @ref is_null(), @ref is_object(), @ref is_array(), @ref is_string(), @ref is_boolean(), @ref - is_number(), and @ref is_discarded() rely on it. + is_number() (with @ref is_number_integer(), @ref is_number_unsigned(), and + @ref is_number_float()), @ref is_discarded(), @ref is_primitive(), and + @ref is_structured() rely on it. + + @note There are three enumeration entries (number_integer, + number_unsigned, and number_float), because the library distinguishes + these three types for numbers: @ref number_unsigned_t is used for unsigned + integers, @ref number_integer_t is used for signed integers, and @ref + number_float_t is used for floating-point numbers or to approximate + integers which do not fit in the limits of their respective type. + + @sa @ref basic_json(const value_t value_type) -- create a JSON value with + the default value for a given type @since version 1.0.0 */ @@ -728,7 +740,7 @@ class basic_json array, ///< array (ordered collection of values) string, ///< string value boolean, ///< boolean value - number_integer, ///< number value (integer) + number_integer, ///< number value (signed integer) number_unsigned, ///< number value (unsigned integer) number_float, ///< number value (floating-point) discarded ///< discarded by the the parser callback function @@ -758,7 +770,24 @@ class basic_json /*! @brief a JSON value - The actual storage for a JSON value of the @ref basic_json class. + The actual storage for a JSON value of the @ref basic_json class. This + union combines the different storage types for the JSON value types + defined in @ref value_t. + + JSON type | value_t type | used type + --------- | --------------- | ------------------------ + object | object | pointer to @ref object_t + array | array | pointer to @ref array_t + string | string | pointer to @ref string_t + boolean | boolean | @ref boolean_t + number | number_integer | @ref number_integer_t + number | number_unsigned | @ref number_unsigned_t + number | number_float | @ref number_float_t + null | null | *no value is stored* + + @note Variable-length types (objects, arrays, and strings) are stored as + pointers. The size of the union should not exceed 64 bits if the default + value types are used. @since version 1.0.0 */ @@ -874,6 +903,8 @@ class basic_json This enumeration lists the parser events that can trigger calling a callback function of type @ref parser_callback_t during parsing. + @image html callback_events.png "Example when certain parse events are triggered" + @since version 1.0.0 */ enum class parse_event_t : uint8_t @@ -916,6 +947,8 @@ class basic_json parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value + @image html callback_events.png "Example when certain parse events are triggered" + Discarding a value (i.e., returning `false`) has different effects depending on the context in which function was called: @@ -2773,21 +2806,16 @@ class basic_json type of the current JSON */ template - static ReferenceType get_ref_impl(ThisType& obj) + static constexpr ReferenceType get_ref_impl(ThisType& obj) { - // delegate the call to get_ptr<>() + // helper type using PointerType = typename std::add_pointer::type; - auto ptr = obj.template get_ptr(); - if (ptr != nullptr) - { - return *ptr; - } - else - { - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); - } + // delegate the call to get_ptr<>() + return obj.template get_ptr() != nullptr + ? *obj.template get_ptr() + : throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name()); } public: @@ -3015,7 +3043,7 @@ class basic_json std::is_reference::value and std::is_const::type>::value , int>::type = 0> - ReferenceType get_ref() const + constexpr ReferenceType get_ref() const { // delegate call to get_ref_impl return get_ref_impl(*this); @@ -7286,6 +7314,8 @@ class basic_json @throw std::invalid_argument if the low surrogate is invalid; example: `""missing or wrong low surrogate""` + @complexity Constant. + @see */ static string_t to_unicode(const std::size_t codepoint1, @@ -7402,6 +7432,17 @@ class basic_json function consists of a large block of code with `goto` jumps. @return the class of the next token read from the buffer + + @complexity Linear in the length of the input.\n + + Proposition: The loop below will always terminate for finite input.\n + + Proof (by contradiction): Assume a finite input. To loop forever, the + loop must never hit code with a `break` statement. The only code + snippets without a `break` statement are the continue statements for + whitespace and byte-order-marks. To loop forever, the input must be an + infinite sequence of whitespace or byte-order-marks. This contradicts + the assumption of finite input, q.e.d. */ token_type scan() noexcept { @@ -7422,8 +7463,8 @@ class basic_json { 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 0, 0, 32, 0, 0, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 160, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, @@ -7602,7 +7643,7 @@ basic_json_parser_6: basic_json_parser_9: yyaccept = 0; yych = *(m_marker = ++m_cursor); - if (yych <= 0x0F) + if (yych <= 0x1F) { goto basic_json_parser_5; } @@ -7760,7 +7801,7 @@ basic_json_parser_32: { goto basic_json_parser_31; } - if (yych <= 0x0F) + if (yych <= 0x1F) { goto basic_json_parser_33; } @@ -8233,16 +8274,53 @@ basic_json_parser_63: according to the nature of the escape. Some escapes create new characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape - `"\\uxxxx"` need special care. In this case, to_unicode takes care - of the construction of the values. + `"\\uxxxx"` need special care. In this case, @ref to_unicode takes + care of the construction of the values. 2. Unescaped characters are copied as is. + @pre `m_cursor - m_start >= 2`, meaning the length of the last token + is at least 2 bytes which is trivially true for any string (which + consists of at least two quotes). + + " c1 c2 c3 ... " + ^ ^ + m_start m_cursor + + @complexity Linear in the length of the string.\n + + Lemma: The loop body will always terminate.\n + + Proof (by contradiction): Assume the loop body does not terminate. As + the loop body does not contain another loop, one of the called + functions must never return. The called functions are `std::strtoul` + and @ref to_unicode. Neither function can loop forever, so the loop + body will never loop forever which contradicts the assumption that the + loop body does not terminate, q.e.d.\n + + Lemma: The loop condition for the for loop is eventually false.\n + + Proof (by contradiction): Assume the loop does not terminate. Due to + the above lemma, this can only be due to a tautological loop + condition; that is, the loop condition i < m_cursor - 1 must always be + true. Let x be the change of i for any loop iteration. Then + m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. + This can be rephrased to m_cursor - m_start - 2 > x. With the + precondition, we x <= 0, meaning that the loop condition holds + indefinitly if i is always decreased. However, observe that the + value of i is strictly increasing with each iteration, as it is + incremented by 1 in the iteration expression and never + decremented inside the loop body. Hence, the loop condition + will eventually be false which contradicts the assumption that + the loop condition is a tautology, q.e.d. + @return string value of current token without opening and closing quotes @throw std::out_of_range if to_unicode fails */ string_t get_string() const { + assert(m_cursor - m_start >= 2); + string_t result; result.reserve(static_cast(m_cursor - m_start - 2)); @@ -8915,6 +8993,8 @@ basic_json_parser_63: /*! @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. */ reference get_and_create(reference j) const { @@ -9352,6 +9432,7 @@ basic_json_parser_63: basic_json result; // iterate the JSON object values + assert(value.m_value.object != nullptr); for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 8eeedefee..05c49ec58 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -717,7 +717,19 @@ class basic_json This enumeration collects the different JSON types. It is internally used to distinguish the stored values, and the functions @ref is_null(), @ref is_object(), @ref is_array(), @ref is_string(), @ref is_boolean(), @ref - is_number(), and @ref is_discarded() rely on it. + is_number() (with @ref is_number_integer(), @ref is_number_unsigned(), and + @ref is_number_float()), @ref is_discarded(), @ref is_primitive(), and + @ref is_structured() rely on it. + + @note There are three enumeration entries (number_integer, + number_unsigned, and number_float), because the library distinguishes + these three types for numbers: @ref number_unsigned_t is used for unsigned + integers, @ref number_integer_t is used for signed integers, and @ref + number_float_t is used for floating-point numbers or to approximate + integers which do not fit in the limits of their respective type. + + @sa @ref basic_json(const value_t value_type) -- create a JSON value with + the default value for a given type @since version 1.0.0 */ @@ -728,7 +740,7 @@ class basic_json array, ///< array (ordered collection of values) string, ///< string value boolean, ///< boolean value - number_integer, ///< number value (integer) + number_integer, ///< number value (signed integer) number_unsigned, ///< number value (unsigned integer) number_float, ///< number value (floating-point) discarded ///< discarded by the the parser callback function @@ -758,7 +770,24 @@ class basic_json /*! @brief a JSON value - The actual storage for a JSON value of the @ref basic_json class. + The actual storage for a JSON value of the @ref basic_json class. This + union combines the different storage types for the JSON value types + defined in @ref value_t. + + JSON type | value_t type | used type + --------- | --------------- | ------------------------ + object | object | pointer to @ref object_t + array | array | pointer to @ref array_t + string | string | pointer to @ref string_t + boolean | boolean | @ref boolean_t + number | number_integer | @ref number_integer_t + number | number_unsigned | @ref number_unsigned_t + number | number_float | @ref number_float_t + null | null | *no value is stored* + + @note Variable-length types (objects, arrays, and strings) are stored as + pointers. The size of the union should not exceed 64 bits if the default + value types are used. @since version 1.0.0 */ @@ -874,6 +903,8 @@ class basic_json This enumeration lists the parser events that can trigger calling a callback function of type @ref parser_callback_t during parsing. + @image html callback_events.png "Example when certain parse events are triggered" + @since version 1.0.0 */ enum class parse_event_t : uint8_t @@ -916,6 +947,8 @@ class basic_json parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value + @image html callback_events.png "Example when certain parse events are triggered" + Discarding a value (i.e., returning `false`) has different effects depending on the context in which function was called: @@ -2773,21 +2806,16 @@ class basic_json type of the current JSON */ template - static ReferenceType get_ref_impl(ThisType& obj) + static constexpr ReferenceType get_ref_impl(ThisType& obj) { - // delegate the call to get_ptr<>() + // helper type using PointerType = typename std::add_pointer::type; - auto ptr = obj.template get_ptr(); - if (ptr != nullptr) - { - return *ptr; - } - else - { - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); - } + // delegate the call to get_ptr<>() + return obj.template get_ptr() != nullptr + ? *obj.template get_ptr() + : throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name()); } public: @@ -3015,7 +3043,7 @@ class basic_json std::is_reference::value and std::is_const::type>::value , int>::type = 0> - ReferenceType get_ref() const + constexpr ReferenceType get_ref() const { // delegate call to get_ref_impl return get_ref_impl(*this); @@ -7286,6 +7314,8 @@ class basic_json @throw std::invalid_argument if the low surrogate is invalid; example: `""missing or wrong low surrogate""` + @complexity Constant. + @see */ static string_t to_unicode(const std::size_t codepoint1, @@ -7402,6 +7432,17 @@ class basic_json function consists of a large block of code with `goto` jumps. @return the class of the next token read from the buffer + + @complexity Linear in the length of the input.\n + + Proposition: The loop below will always terminate for finite input.\n + + Proof (by contradiction): Assume a finite input. To loop forever, the + loop must never hit code with a `break` statement. The only code + snippets without a `break` statement are the continue statements for + whitespace and byte-order-marks. To loop forever, the input must be an + infinite sequence of whitespace or byte-order-marks. This contradicts + the assumption of finite input, q.e.d. */ token_type scan() noexcept { @@ -7447,32 +7488,32 @@ class basic_json "false" { last_token_type = token_type::literal_false; break; } // number - decimal_point = [.]; + decimal_point = "."; digit = [0-9]; digit_1_9 = [1-9]; - e = [eE]; - minus = [-]; - plus = [+]; - zero = [0]; - exp = e (minus|plus)? digit+; + e = "e" | "E"; + minus = "-"; + plus = "+"; + zero = "0"; + exp = e (minus | plus)? digit+; frac = decimal_point digit+; - int = (zero|digit_1_9 digit*); + int = (zero | digit_1_9 digit*); number = minus? int frac? exp?; number { last_token_type = token_type::value_number; break; } // string - quotation_mark = ["]; - escape = [\\]; - unescaped = [^"\\\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F]; - single_escaped = ["\\/bfnrt]; - unicode_escaped = [u][0-9a-fA-F]{4}; + quotation_mark = "\""; + escape = "\\"; + unescaped = [^"\\\x00-\x1f]; + single_escaped = "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t"; + unicode_escaped = "u" [0-9a-fA-F]{4}; escaped = escape (single_escaped | unicode_escaped); char = unescaped | escaped; string = quotation_mark char* quotation_mark; string { last_token_type = token_type::value_string; break; } // end of file - '\000' { last_token_type = token_type::end_of_input; break; } + "\000" { last_token_type = token_type::end_of_input; break; } // anything else is an error . { last_token_type = token_type::parse_error; break; } @@ -7530,16 +7571,53 @@ class basic_json according to the nature of the escape. Some escapes create new characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape - `"\\uxxxx"` need special care. In this case, to_unicode takes care - of the construction of the values. + `"\\uxxxx"` need special care. In this case, @ref to_unicode takes + care of the construction of the values. 2. Unescaped characters are copied as is. + @pre `m_cursor - m_start >= 2`, meaning the length of the last token + is at least 2 bytes which is trivially true for any string (which + consists of at least two quotes). + + " c1 c2 c3 ... " + ^ ^ + m_start m_cursor + + @complexity Linear in the length of the string.\n + + Lemma: The loop body will always terminate.\n + + Proof (by contradiction): Assume the loop body does not terminate. As + the loop body does not contain another loop, one of the called + functions must never return. The called functions are `std::strtoul` + and @ref to_unicode. Neither function can loop forever, so the loop + body will never loop forever which contradicts the assumption that the + loop body does not terminate, q.e.d.\n + + Lemma: The loop condition for the for loop is eventually false.\n + + Proof (by contradiction): Assume the loop does not terminate. Due to + the above lemma, this can only be due to a tautological loop + condition; that is, the loop condition i < m_cursor - 1 must always be + true. Let x be the change of i for any loop iteration. Then + m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. + This can be rephrased to m_cursor - m_start - 2 > x. With the + precondition, we x <= 0, meaning that the loop condition holds + indefinitly if i is always decreased. However, observe that the + value of i is strictly increasing with each iteration, as it is + incremented by 1 in the iteration expression and never + decremented inside the loop body. Hence, the loop condition + will eventually be false which contradicts the assumption that + the loop condition is a tautology, q.e.d. + @return string value of current token without opening and closing quotes @throw std::out_of_range if to_unicode fails */ string_t get_string() const { + assert(m_cursor - m_start >= 2); + string_t result; result.reserve(static_cast(m_cursor - m_start - 2)); @@ -8212,6 +8290,8 @@ class basic_json /*! @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. */ reference get_and_create(reference j) const { @@ -8649,6 +8729,7 @@ class basic_json basic_json result; // iterate the JSON object values + assert(value.m_value.object != nullptr); for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) diff --git a/test/src/unit.cpp b/test/src/unit.cpp index a7ca73947..8ca9b01fa 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -9716,6 +9716,39 @@ TEST_CASE("parser class") CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), "parse error - unexpected '\"'"); // improve code coverage CHECK_THROWS_AS(json::parser("\uFF01").parse(), std::invalid_argument); + // unescaped control characters + CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x02\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x03\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x04\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x05\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x06\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x07\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x08\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x09\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x0a\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x0b\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x0c\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x0d\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x0e\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x0f\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x10\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x11\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x12\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x13\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x14\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x15\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x16\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x17\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x18\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x19\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x1a\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x1b\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x1c\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x1d\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x1e\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x1f\"").parse(), std::invalid_argument); } SECTION("escaped") From 51a3829680dd5f5a67fe5c0390151c3157294639 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 22 Jul 2016 15:53:38 +0200 Subject: [PATCH 26/48] reverted change to constexpr get_ref (does not work with GCC and MSVC) --- src/json.hpp | 19 +++++++++++++------ src/json.hpp.re2c | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 00bee9709..b581fea19 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -2806,16 +2806,23 @@ class basic_json type of the current JSON */ template - static constexpr ReferenceType get_ref_impl(ThisType& obj) + static ReferenceType get_ref_impl(ThisType& obj) { // helper type using PointerType = typename std::add_pointer::type; // delegate the call to get_ptr<>() - return obj.template get_ptr() != nullptr - ? *obj.template get_ptr() - : throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); + auto ptr = obj.template get_ptr(); + + if (ptr != nullptr) + { + return *ptr; + } + else + { + throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name()); + } } public: @@ -3043,7 +3050,7 @@ class basic_json std::is_reference::value and std::is_const::type>::value , int>::type = 0> - constexpr ReferenceType get_ref() const + ReferenceType get_ref() const { // delegate call to get_ref_impl return get_ref_impl(*this); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 05c49ec58..73185c6b1 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -2806,16 +2806,23 @@ class basic_json type of the current JSON */ template - static constexpr ReferenceType get_ref_impl(ThisType& obj) + static ReferenceType get_ref_impl(ThisType& obj) { // helper type using PointerType = typename std::add_pointer::type; // delegate the call to get_ptr<>() - return obj.template get_ptr() != nullptr - ? *obj.template get_ptr() - : throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); + auto ptr = obj.template get_ptr(); + + if (ptr != nullptr) + { + return *ptr; + } + else + { + throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name()); + } } public: @@ -3043,7 +3050,7 @@ class basic_json std::is_reference::value and std::is_const::type>::value , int>::type = 0> - constexpr ReferenceType get_ref() const + ReferenceType get_ref() const { // delegate call to get_ref_impl return get_ref_impl(*this); From ddfe86cc49f3c97b70efef77da505a05569a250f Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 22 Jul 2016 21:40:58 +0200 Subject: [PATCH 27/48] fixed a bug that was found in the discussion of #274 --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- test/src/unit.cpp | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index b581fea19..614a700f2 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7283,7 +7283,7 @@ class basic_json explicit lexer(const string_t& s) noexcept : m_stream(nullptr), m_buffer(s) { - m_content = reinterpret_cast(s.c_str()); + m_content = reinterpret_cast(m_buffer.c_str()); assert(m_content != nullptr); m_start = m_cursor = m_content; m_limit = m_content + s.size(); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 73185c6b1..a7c6f7e77 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7283,7 +7283,7 @@ class basic_json explicit lexer(const string_t& s) noexcept : m_stream(nullptr), m_buffer(s) { - m_content = reinterpret_cast(s.c_str()); + m_content = reinterpret_cast(m_buffer.c_str()); assert(m_content != nullptr); m_start = m_cursor = m_content; m_limit = m_content + s.size(); diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 8ca9b01fa..2a92b3277 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -10359,6 +10359,14 @@ TEST_CASE("parser class") CHECK(j_empty_array == json()); } } + + SECTION("copy constructor") + { + json::string_t* s = new json::string_t("[1,2,3,4]"); + json::parser p(*s); + delete s; + CHECK(p.parse() == json({1, 2, 3, 4})); + } } TEST_CASE("README", "[hide]") From 75dbbc55cf239fe225aa13b302622d4e015eca06 Mon Sep 17 00:00:00 2001 From: Niels Date: Sat, 23 Jul 2016 09:59:09 +0200 Subject: [PATCH 28/48] started to implement #283 --- src/json.hpp | 53 ++++++++- src/json.hpp.re2c | 53 ++++++++- test/src/unit.cpp | 267 +++++++++++++++++++++++++++------------------- 3 files changed, 260 insertions(+), 113 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 614a700f2..a5bc864e7 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -3633,8 +3633,8 @@ class basic_json /*! @brief access specified object element with default value - Returns either a copy of an object's element at the specified key @a key or - a given default value if no element with key @a key exists. + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. The function is basically equivalent to executing @code {.cpp} @@ -3706,13 +3706,60 @@ class basic_json /*! @brief overload for a default value of type const char* - @copydoc basic_json::value() + @copydoc basic_json::value(const typename object_t::key_type&, ValueType) */ string_t value(const typename object_t::key_type& key, const char* default_value) const { return value(key, string_t(default_value)); } + /*! + @brief access specified object element via JSON Pointer with default value + + @param[in] ptr a JSON pointer to the element to access + @param[in] default_value the value to return if @a ptr found no value + + @tparam ValueType type compatible to JSON values, for instance `int` for + JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for + JSON arrays. Note the type of the expected value at @a key and the default + value @a default_value must be compatible. + + @since version 2.0.2 + */ + template ::value + , int>::type = 0> + ValueType value(const json_pointer& ptr, ValueType default_value) const + { + // at only works for objects + if (is_object()) + { + // if pointer resolves a value, return it or use default value + try + { + return ptr.get_checked(this); + } + catch (std::out_of_range&) + { + return default_value; + } + } + else + { + throw std::domain_error("cannot use value() with " + type_name()); + } + } + + /*! + @brief overload for a default value of type const char* + @copydoc basic_json::value(const json_pointer&, ValueType) + */ + string_t value(const json_pointer& ptr, const char* default_value) const + { + return value(ptr, string_t(default_value)); + } + /*! @brief access the first element diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index a7c6f7e77..2f5ecd2cf 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -3633,8 +3633,8 @@ class basic_json /*! @brief access specified object element with default value - Returns either a copy of an object's element at the specified key @a key or - a given default value if no element with key @a key exists. + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. The function is basically equivalent to executing @code {.cpp} @@ -3706,13 +3706,60 @@ class basic_json /*! @brief overload for a default value of type const char* - @copydoc basic_json::value() + @copydoc basic_json::value(const typename object_t::key_type&, ValueType) */ string_t value(const typename object_t::key_type& key, const char* default_value) const { return value(key, string_t(default_value)); } + /*! + @brief access specified object element via JSON Pointer with default value + + @param[in] ptr a JSON pointer to the element to access + @param[in] default_value the value to return if @a ptr found no value + + @tparam ValueType type compatible to JSON values, for instance `int` for + JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for + JSON arrays. Note the type of the expected value at @a key and the default + value @a default_value must be compatible. + + @since version 2.0.2 + */ + template ::value + , int>::type = 0> + ValueType value(const json_pointer& ptr, ValueType default_value) const + { + // at only works for objects + if (is_object()) + { + // if pointer resolves a value, return it or use default value + try + { + return ptr.get_checked(this); + } + catch (std::out_of_range&) + { + return default_value; + } + } + else + { + throw std::domain_error("cannot use value() with " + type_name()); + } + } + + /*! + @brief overload for a default value of type const char* + @copydoc basic_json::value(const json_pointer&, ValueType) + */ + string_t value(const json_pointer& ptr, const char* default_value) const + { + return value(ptr, string_t(default_value)); + } + /*! @brief access the first element diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 2a92b3277..2952708cd 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -3768,123 +3768,176 @@ TEST_CASE("element access") SECTION("access specified element with default value") { - SECTION("access existing value") + SECTION("given a key") { - CHECK(j.value("integer", 2) == 1); - CHECK(j.value("integer", 1.0) == Approx(1)); - CHECK(j.value("unsigned", 2) == 1u); - CHECK(j.value("unsigned", 1.0) == Approx(1u)); - CHECK(j.value("null", json(1)) == json()); - CHECK(j.value("boolean", false) == true); - CHECK(j.value("string", "bar") == "hello world"); - CHECK(j.value("string", std::string("bar")) == "hello world"); - CHECK(j.value("floating", 12.34) == Approx(42.23)); - CHECK(j.value("floating", 12) == 42); - CHECK(j.value("object", json({{"foo", "bar"}})) == json(json::object())); - CHECK(j.value("array", json({10, 100})) == json({1, 2, 3})); + SECTION("access existing value") + { + CHECK(j.value("integer", 2) == 1); + CHECK(j.value("integer", 1.0) == Approx(1)); + CHECK(j.value("unsigned", 2) == 1u); + CHECK(j.value("unsigned", 1.0) == Approx(1u)); + CHECK(j.value("null", json(1)) == json()); + CHECK(j.value("boolean", false) == true); + CHECK(j.value("string", "bar") == "hello world"); + CHECK(j.value("string", std::string("bar")) == "hello world"); + CHECK(j.value("floating", 12.34) == Approx(42.23)); + CHECK(j.value("floating", 12) == 42); + CHECK(j.value("object", json({{"foo", "bar"}})) == json(json::object())); + CHECK(j.value("array", json({10, 100})) == json({1, 2, 3})); - CHECK(j_const.value("integer", 2) == 1); - CHECK(j_const.value("integer", 1.0) == Approx(1)); - CHECK(j_const.value("unsigned", 2) == 1u); - CHECK(j_const.value("unsigned", 1.0) == Approx(1u)); - CHECK(j_const.value("boolean", false) == true); - CHECK(j_const.value("string", "bar") == "hello world"); - CHECK(j_const.value("string", std::string("bar")) == "hello world"); - CHECK(j_const.value("floating", 12.34) == Approx(42.23)); - CHECK(j_const.value("floating", 12) == 42); - CHECK(j_const.value("object", json({{"foo", "bar"}})) == json(json::object())); - CHECK(j_const.value("array", json({10, 100})) == json({1, 2, 3})); + CHECK(j_const.value("integer", 2) == 1); + CHECK(j_const.value("integer", 1.0) == Approx(1)); + CHECK(j_const.value("unsigned", 2) == 1u); + CHECK(j_const.value("unsigned", 1.0) == Approx(1u)); + CHECK(j_const.value("boolean", false) == true); + CHECK(j_const.value("string", "bar") == "hello world"); + CHECK(j_const.value("string", std::string("bar")) == "hello world"); + CHECK(j_const.value("floating", 12.34) == Approx(42.23)); + CHECK(j_const.value("floating", 12) == 42); + CHECK(j_const.value("object", json({{"foo", "bar"}})) == json(json::object())); + CHECK(j_const.value("array", json({10, 100})) == json({1, 2, 3})); + } + + SECTION("access non-existing value") + { + CHECK(j.value("_", 2) == 2); + CHECK(j.value("_", 2u) == 2u); + CHECK(j.value("_", false) == false); + CHECK(j.value("_", "bar") == "bar"); + CHECK(j.value("_", 12.34) == Approx(12.34)); + CHECK(j.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); + CHECK(j.value("_", json({10, 100})) == json({10, 100})); + + CHECK(j_const.value("_", 2) == 2); + CHECK(j_const.value("_", 2u) == 2u); + CHECK(j_const.value("_", false) == false); + CHECK(j_const.value("_", "bar") == "bar"); + CHECK(j_const.value("_", 12.34) == Approx(12.34)); + CHECK(j_const.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); + CHECK(j_const.value("_", json({10, 100})) == json({10, 100})); + } + + SECTION("access on non-object type") + { + SECTION("null") + { + json j_nonobject(json::value_t::null); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with null"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with null"); + } + + SECTION("boolean") + { + json j_nonobject(json::value_t::boolean); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with boolean"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with boolean"); + } + + SECTION("string") + { + json j_nonobject(json::value_t::string); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with string"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with string"); + } + + SECTION("array") + { + json j_nonobject(json::value_t::array); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with array"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with array"); + } + + SECTION("number (integer)") + { + json j_nonobject(json::value_t::number_integer); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); + } + + SECTION("number (unsigned)") + { + json j_nonobject(json::value_t::number_unsigned); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); + } + + SECTION("number (floating-point)") + { + json j_nonobject(json::value_t::number_float); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); + } + } } - SECTION("access non-existing value") + SECTION("given a JSON pointer") { - CHECK(j.value("_", 2) == 2); - CHECK(j.value("_", 2u) == 2u); - CHECK(j.value("_", false) == false); - CHECK(j.value("_", "bar") == "bar"); - CHECK(j.value("_", 12.34) == Approx(12.34)); - CHECK(j.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); - CHECK(j.value("_", json({10, 100})) == json({10, 100})); - - CHECK(j_const.value("_", 2) == 2); - CHECK(j_const.value("_", 2u) == 2u); - CHECK(j_const.value("_", false) == false); - CHECK(j_const.value("_", "bar") == "bar"); - CHECK(j_const.value("_", 12.34) == Approx(12.34)); - CHECK(j_const.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); - CHECK(j_const.value("_", json({10, 100})) == json({10, 100})); - } - - SECTION("access on non-object type") - { - SECTION("null") + SECTION("access existing value") { - json j_nonobject(json::value_t::null); - const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with null"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with null"); + CHECK(j.value("/integer"_json_pointer, 2) == 1); + CHECK(j.value("/integer"_json_pointer, 1.0) == Approx(1)); + CHECK(j.value("/unsigned"_json_pointer, 2) == 1u); + CHECK(j.value("/unsigned"_json_pointer, 1.0) == Approx(1u)); + CHECK(j.value("/null"_json_pointer, json(1)) == json()); + CHECK(j.value("/boolean"_json_pointer, false) == true); + CHECK(j.value("/string"_json_pointer, "bar") == "hello world"); + CHECK(j.value("/string"_json_pointer, std::string("bar")) == "hello world"); + CHECK(j.value("/floating"_json_pointer, 12.34) == Approx(42.23)); + CHECK(j.value("/floating"_json_pointer, 12) == 42); + CHECK(j.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object())); + CHECK(j.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3})); + + CHECK(j_const.value("/integer"_json_pointer, 2) == 1); + CHECK(j_const.value("/integer"_json_pointer, 1.0) == Approx(1)); + CHECK(j_const.value("/unsigned"_json_pointer, 2) == 1u); + CHECK(j_const.value("/unsigned"_json_pointer, 1.0) == Approx(1u)); + CHECK(j_const.value("/boolean"_json_pointer, false) == true); + CHECK(j_const.value("/string"_json_pointer, "bar") == "hello world"); + CHECK(j_const.value("/string"_json_pointer, std::string("bar")) == "hello world"); + CHECK(j_const.value("/floating"_json_pointer, 12.34) == Approx(42.23)); + CHECK(j_const.value("/floating"_json_pointer, 12) == 42); + CHECK(j_const.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object())); + CHECK(j_const.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3})); } - SECTION("boolean") + SECTION("access non-existing value") { - json j_nonobject(json::value_t::boolean); - const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with boolean"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with boolean"); - } + CHECK(j.value("/not/existing", 2) == 2); + CHECK(j.value("/not/existing", 2u) == 2u); + CHECK(j.value("/not/existing", false) == false); + CHECK(j.value("/not/existing", "bar") == "bar"); + CHECK(j.value("/not/existing", 12.34) == Approx(12.34)); + CHECK(j.value("/not/existing", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); + CHECK(j.value("/not/existing", json({10, 100})) == json({10, 100})); - SECTION("string") - { - json j_nonobject(json::value_t::string); - const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with string"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with string"); - } - - SECTION("array") - { - json j_nonobject(json::value_t::array); - const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with array"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with array"); - } - - SECTION("number (integer)") - { - json j_nonobject(json::value_t::number_integer); - const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); - } - - SECTION("number (unsigned)") - { - json j_nonobject(json::value_t::number_unsigned); - const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); - } - - SECTION("number (floating-point)") - { - json j_nonobject(json::value_t::number_float); - const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); + CHECK(j_const.value("/not/existing", 2) == 2); + CHECK(j_const.value("/not/existing", 2u) == 2u); + CHECK(j_const.value("/not/existing", false) == false); + CHECK(j_const.value("/not/existing", "bar") == "bar"); + CHECK(j_const.value("/not/existing", 12.34) == Approx(12.34)); + CHECK(j_const.value("/not/existing", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); + CHECK(j_const.value("/not/existing", json({10, 100})) == json({10, 100})); } } } From e2aa2d21899536db3724cacd207c70d233696345 Mon Sep 17 00:00:00 2001 From: Niels Date: Sun, 24 Jul 2016 11:01:47 +0200 Subject: [PATCH 29/48] improved test coverage --- test/src/unit.cpp | 106 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 14 deletions(-) diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 2952708cd..92ba97b04 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -3923,21 +3923,99 @@ TEST_CASE("element access") SECTION("access non-existing value") { - CHECK(j.value("/not/existing", 2) == 2); - CHECK(j.value("/not/existing", 2u) == 2u); - CHECK(j.value("/not/existing", false) == false); - CHECK(j.value("/not/existing", "bar") == "bar"); - CHECK(j.value("/not/existing", 12.34) == Approx(12.34)); - CHECK(j.value("/not/existing", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); - CHECK(j.value("/not/existing", json({10, 100})) == json({10, 100})); + CHECK(j.value("/not/existing"_json_pointer, 2) == 2); + CHECK(j.value("/not/existing"_json_pointer, 2u) == 2u); + CHECK(j.value("/not/existing"_json_pointer, false) == false); + CHECK(j.value("/not/existing"_json_pointer, "bar") == "bar"); + CHECK(j.value("/not/existing"_json_pointer, 12.34) == Approx(12.34)); + CHECK(j.value("/not/existing"_json_pointer, json({{"foo", "bar"}})) == json({{"foo", "bar"}})); + CHECK(j.value("/not/existing"_json_pointer, json({10, 100})) == json({10, 100})); - CHECK(j_const.value("/not/existing", 2) == 2); - CHECK(j_const.value("/not/existing", 2u) == 2u); - CHECK(j_const.value("/not/existing", false) == false); - CHECK(j_const.value("/not/existing", "bar") == "bar"); - CHECK(j_const.value("/not/existing", 12.34) == Approx(12.34)); - CHECK(j_const.value("/not/existing", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); - CHECK(j_const.value("/not/existing", json({10, 100})) == json({10, 100})); + CHECK(j_const.value("/not/existing"_json_pointer, 2) == 2); + CHECK(j_const.value("/not/existing"_json_pointer, 2u) == 2u); + CHECK(j_const.value("/not/existing"_json_pointer, false) == false); + CHECK(j_const.value("/not/existing"_json_pointer, "bar") == "bar"); + CHECK(j_const.value("/not/existing"_json_pointer, 12.34) == Approx(12.34)); + CHECK(j_const.value("/not/existing"_json_pointer, json({{"foo", "bar"}})) == json({{"foo", "bar"}})); + CHECK(j_const.value("/not/existing"_json_pointer, json({10, 100})) == json({10, 100})); + } + + SECTION("access on non-object type") + { + SECTION("null") + { + json j_nonobject(json::value_t::null); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with null"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), "cannot use value() with null"); + } + + SECTION("boolean") + { + json j_nonobject(json::value_t::boolean); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with boolean"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), + "cannot use value() with boolean"); + } + + SECTION("string") + { + json j_nonobject(json::value_t::string); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with string"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), + "cannot use value() with string"); + } + + SECTION("array") + { + json j_nonobject(json::value_t::array); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with array"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), "cannot use value() with array"); + } + + SECTION("number (integer)") + { + json j_nonobject(json::value_t::number_integer); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), + "cannot use value() with number"); + } + + SECTION("number (unsigned)") + { + json j_nonobject(json::value_t::number_unsigned); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), + "cannot use value() with number"); + } + + SECTION("number (floating-point)") + { + json j_nonobject(json::value_t::number_float); + const json j_nonobject_const(j_nonobject); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), + "cannot use value() with number"); + } } } } From 84673b7de38df50d4cdb32a5e78e3e5857291d58 Mon Sep 17 00:00:00 2001 From: Niels Date: Sun, 24 Jul 2016 11:08:39 +0200 Subject: [PATCH 30/48] added test case from issue #283 --- test/src/unit.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 92ba97b04..a1589949a 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -14331,6 +14331,19 @@ TEST_CASE("regression tests") // check roundtrip CHECK(doc.patch(json::diff(doc, expected)) == expected); } + + SECTION("issue #283 - value() does not work with _json_pointer types") + { + json j = + { + {"object", {{"key1", 1}, {"key2", 2}}}, + }; + + int at_integer = j.at("/object/key2"_json_pointer); + int val_integer = j.value("/object/key2"_json_pointer, 0); + + CHECK(at_integer == val_integer); + } } // special test case to check if memory is leaked if constructor throws From 369671f028739178d22c53546d30d0ba87746985 Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 25 Jul 2016 16:05:58 +0200 Subject: [PATCH 31/48] added more Unicode tests --- README.md | 2 +- test/src/unit.cpp | 81 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 24f6d7ab9..5adcf15ca 100644 --- a/README.md +++ b/README.md @@ -505,7 +505,7 @@ $ make $ ./json_unit "*" =============================================================================== -All tests passed (5568718 assertions in 32 test cases) +All tests passed (8905012 assertions in 32 test cases) ``` For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml). diff --git a/test/src/unit.cpp b/test/src/unit.cpp index a1589949a..c2738faef 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -12285,19 +12285,23 @@ TEST_CASE("RFC 7159 examples") TEST_CASE("Unicode", "[hide]") { - SECTION("full enumeration of Unicode codepoints") + SECTION("full enumeration of Unicode code points") { - // create a string from a codepoint - auto codepoint_to_unicode = [](std::size_t cp) + // create an escaped string from a code point + const auto codepoint_to_unicode = [](std::size_t cp) { - char* buffer = new char[10]; - sprintf(buffer, "\\u%04lx", cp); - std::string result(buffer); - delete[] buffer; - return result; + // copd points are represented as a six-character sequence: a + // reverse solidus, followed by the lowercase letter u, followed + // by four hexadecimal digits that encode the character's code + // point + std::stringstream ss; + ss << "\\u" << std::setw(4) << std::setfill('0') << std::hex << cp; + return ss.str(); }; - // generate all codepoints + // generate all UTF8 code points; in total, 1112064 code points are + // generated: 0x1FFFFF code points - 2047 invalid values between + // 0xD800 and 0xDFFF. for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp) { // The Unicode standard permanently reserves these code point @@ -12307,34 +12311,57 @@ TEST_CASE("Unicode", "[hide]") // no UTF forms, including UTF-16, can encode these code points. if (cp >= 0xD800u and cp <= 0xDFFFu) { + // if we would not skip these code points, we would get a + // "missing low surrogate" exception continue; } - std::string res; + // string to store the code point as in \uxxxx format + std::string escaped_string; + // string to store the code point as unescaped character sequence + std::string unescaped_string; if (cp < 0x10000u) { - // codepoint can be represented with 16 bit - res += codepoint_to_unicode(cp); + // code points in the Basic Multilingual Plane can be + // represented with one \\uxxxx sequence + escaped_string = codepoint_to_unicode(cp); + + // All Unicode characters may be placed within the quotation + // marks, except for the characters that must be escaped: + // quotation mark, reverse solidus, and the control characters + // (U+0000 through U+001F); we ignore these code points as + // they are checked with codepoint_to_unicode. + if (cp > 0x1f and cp != 0x22 and cp != 0x5c) + { + unescaped_string = json::lexer::to_unicode(cp); + } } else { - // codepoint can be represented with a pair - res += codepoint_to_unicode(0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu)); - res += codepoint_to_unicode(0xdc00u + ((cp - 0x10000u) & 0x3ffu)); + // To escape an extended character that is not in the Basic + // Multilingual Plane, the character is represented as a + // 12-character sequence, encoding the UTF-16 surrogate pair + const auto codepoint1 = 0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu); + const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu); + escaped_string = codepoint_to_unicode(codepoint1); + escaped_string += codepoint_to_unicode(codepoint2); + unescaped_string += json::lexer::to_unicode(codepoint1, codepoint2); } - try - { - json j1, j2; - CHECK_NOTHROW(j1 = json::parse("\"" + res + "\"")); - CHECK_NOTHROW(j2 = json::parse(j1.dump())); - CHECK(j1 == j2); - } - catch (std::invalid_argument) - { - // we ignore parsing errors - } + // all other code points are valid and must not yield parse errors + CAPTURE(cp); + CAPTURE(escaped_string); + CAPTURE(unescaped_string); + + json j1, j2, j3, j4; + CHECK_NOTHROW(j1 = json::parse("\"" + escaped_string + "\"")); + CHECK_NOTHROW(j2 = json::parse(j1.dump())); + CHECK(j1 == j2); + + CHECK_NOTHROW(j3 = json::parse("\"" + unescaped_string + "\"")); + CHECK_NOTHROW(j4 = json::parse(j3.dump())); + CHECK(j3 == j4); } } @@ -12347,6 +12374,8 @@ TEST_CASE("Unicode", "[hide]") CHECK_NOTHROW(j << f); // the array has 1112064 + 1 elemnts (a terminating "null" value) + // Note: 1112064 = 0x1FFFFF code points - 2047 invalid values between + // 0xD800 and 0xDFFF. CHECK(j.size() == 1112065); SECTION("check JSON Pointers") From d08e013dd01cc00e2d3e5097ca603310ff4722d0 Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 25 Jul 2016 16:06:13 +0200 Subject: [PATCH 32/48] improved documentation --- doc/examples/basic_json__value_ptr.cpp | 29 ++++++++++++++++++++ doc/examples/basic_json__value_ptr.link | 1 + doc/examples/basic_json__value_ptr.output | 1 + src/json.hpp | 32 ++++++++++++++++++++++- src/json.hpp.re2c | 32 ++++++++++++++++++++++- 5 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 doc/examples/basic_json__value_ptr.cpp create mode 100644 doc/examples/basic_json__value_ptr.link create mode 100644 doc/examples/basic_json__value_ptr.output diff --git a/doc/examples/basic_json__value_ptr.cpp b/doc/examples/basic_json__value_ptr.cpp new file mode 100644 index 000000000..f45fb8b0f --- /dev/null +++ b/doc/examples/basic_json__value_ptr.cpp @@ -0,0 +1,29 @@ +#include + +using json = nlohmann::json; + +int main() +{ + // create a JSON object with different entry types + json j = + { + {"integer", 1}, + {"floating", 42.23}, + {"string", "hello world"}, + {"boolean", true}, + {"object", {{"key1", 1}, {"key2", 2}}}, + {"array", {1, 2, 3}} + }; + + // access existing values + int v_integer = j.value("/integer"_json_pointer, 0); + double v_floating = j.value("/floating"_json_pointer, 47.11); + + // access nonexisting values and rely on default value + std::string v_string = j.value("/nonexisting"_json_pointer, "oops"); + bool v_boolean = j.value("/nonexisting"_json_pointer, false); + + // output values + std::cout << std::boolalpha << v_integer << " " << v_floating + << " " << v_string << " " << v_boolean << "\n"; +} diff --git a/doc/examples/basic_json__value_ptr.link b/doc/examples/basic_json__value_ptr.link new file mode 100644 index 000000000..2f8fc83ca --- /dev/null +++ b/doc/examples/basic_json__value_ptr.link @@ -0,0 +1 @@ +online \ No newline at end of file diff --git a/doc/examples/basic_json__value_ptr.output b/doc/examples/basic_json__value_ptr.output new file mode 100644 index 000000000..dfc40e58c --- /dev/null +++ b/doc/examples/basic_json__value_ptr.output @@ -0,0 +1 @@ +1 42.23 oops false diff --git a/src/json.hpp b/src/json.hpp index a5bc864e7..fc99374bb 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -974,7 +974,9 @@ class basic_json @since version 1.0.0 */ - using parser_callback_t = std::function; + using parser_callback_t = std::function; ////////////////// @@ -3716,6 +3718,21 @@ class basic_json /*! @brief access specified object element via JSON Pointer with default value + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. + + The function is basically equivalent to executing + @code {.cpp} + try { + return at(ptr); + } catch(std::out_of_range) { + return default_value; + } + @endcode + + @note Unlike @ref at(const json_pointer&), this function does not throw + if the given key @a key was not found. + @param[in] ptr a JSON pointer to the element to access @param[in] default_value the value to return if @a ptr found no value @@ -3724,6 +3741,19 @@ class basic_json JSON arrays. Note the type of the expected value at @a key and the default value @a default_value must be compatible. + @return copy of the element at key @a key or @a default_value if @a key + is not found + + @throw std::domain_error if JSON is not an object; example: `"cannot use + value() with null"` + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be queried + with a default value.,basic_json__value_ptr} + + @sa @ref operator[](const json_ptr&) for unchecked access by reference + @since version 2.0.2 */ template ; + using parser_callback_t = std::function; ////////////////// @@ -3716,6 +3718,21 @@ class basic_json /*! @brief access specified object element via JSON Pointer with default value + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. + + The function is basically equivalent to executing + @code {.cpp} + try { + return at(ptr); + } catch(std::out_of_range) { + return default_value; + } + @endcode + + @note Unlike @ref at(const json_pointer&), this function does not throw + if the given key @a key was not found. + @param[in] ptr a JSON pointer to the element to access @param[in] default_value the value to return if @a ptr found no value @@ -3724,6 +3741,19 @@ class basic_json JSON arrays. Note the type of the expected value at @a key and the default value @a default_value must be compatible. + @return copy of the element at key @a key or @a default_value if @a key + is not found + + @throw std::domain_error if JSON is not an object; example: `"cannot use + value() with null"` + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be queried + with a default value.,basic_json__value_ptr} + + @sa @ref operator[](const json_ptr&) for unchecked access by reference + @since version 2.0.2 */ template Date: Mon, 25 Jul 2016 16:21:15 +0200 Subject: [PATCH 33/48] minor changes --- src/json.hpp | 12 +++++++++--- src/json.hpp.re2c | 12 +++++++++--- test/src/unit.cpp | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index fc99374bb..15221b8be 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7386,12 +7386,18 @@ class basic_json lexer operator=(const lexer&) = delete; /*! - @brief create a string from a Unicode code point + @brief create a string from one or two Unicode code points + + There are two cases: (1) @a codepoint1 is in the Basic Multilingual + Plane (U+0000 through U+FFFF) and @a codepoint2 is 0, or (2) + @a codepoint1 and @a codepoint2 are a UTF-16 surrogate pair to + represent a code point above U+FFFF. @param[in] codepoint1 the code point (can be high surrogate) @param[in] codepoint2 the code point (can be low surrogate or 0) - @return string representation of the code point + @return string representation of the code point; the length of the + result string is between 1 and 4 characters. @throw std::out_of_range if code point is > 0x10ffff; example: `"code points above 0x10FFFF are invalid"` @@ -7405,7 +7411,7 @@ class basic_json static string_t to_unicode(const std::size_t codepoint1, const std::size_t codepoint2 = 0) { - // calculate the codepoint from the given code points + // calculate the code point from the given code points std::size_t codepoint = codepoint1; // check if codepoint1 is a high surrogate diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 1227f36d7..74db214eb 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7386,12 +7386,18 @@ class basic_json lexer operator=(const lexer&) = delete; /*! - @brief create a string from a Unicode code point + @brief create a string from one or two Unicode code points + + There are two cases: (1) @a codepoint1 is in the Basic Multilingual + Plane (U+0000 through U+FFFF) and @a codepoint2 is 0, or (2) + @a codepoint1 and @a codepoint2 are a UTF-16 surrogate pair to + represent a code point above U+FFFF. @param[in] codepoint1 the code point (can be high surrogate) @param[in] codepoint2 the code point (can be low surrogate or 0) - @return string representation of the code point + @return string representation of the code point; the length of the + result string is between 1 and 4 characters. @throw std::out_of_range if code point is > 0x10ffff; example: `"code points above 0x10FFFF are invalid"` @@ -7405,7 +7411,7 @@ class basic_json static string_t to_unicode(const std::size_t codepoint1, const std::size_t codepoint2 = 0) { - // calculate the codepoint from the given code points + // calculate the code point from the given code points std::size_t codepoint = codepoint1; // check if codepoint1 is a high surrogate diff --git a/test/src/unit.cpp b/test/src/unit.cpp index c2738faef..cdeb11273 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -12299,7 +12299,7 @@ TEST_CASE("Unicode", "[hide]") return ss.str(); }; - // generate all UTF8 code points; in total, 1112064 code points are + // generate all UTF-8 code points; in total, 1112064 code points are // generated: 0x1FFFFF code points - 2047 invalid values between // 0xD800 and 0xDFFF. for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp) From 02fc3cddee97a476752775cb54cc50ff67b4cc0d Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 25 Jul 2016 16:48:26 +0200 Subject: [PATCH 34/48] test homebrew on OSX --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index b459f5d5a..64deb2fe7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -168,3 +168,8 @@ script: - if [ `which valgrind` ]; then valgrind --error-exitcode=1 --leak-check=full ./json_unit ; fi + - if [ $os = "osx" ]; then + brew tap nlohmann/json ; + brew install nlohmann_json --HEAD ; + brew test nlohmann_json + fi From 148fed1e635b552ef47ee31a3bd79f3926a661f0 Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 25 Jul 2016 18:06:59 +0200 Subject: [PATCH 35/48] minor change --- test/src/unit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/src/unit.cpp b/test/src/unit.cpp index cdeb11273..edbafacf2 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -12300,7 +12300,7 @@ TEST_CASE("Unicode", "[hide]") }; // generate all UTF-8 code points; in total, 1112064 code points are - // generated: 0x1FFFFF code points - 2047 invalid values between + // generated: 0x1FFFFF code points - 2048 invalid values between // 0xD800 and 0xDFFF. for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp) { @@ -12374,7 +12374,7 @@ TEST_CASE("Unicode", "[hide]") CHECK_NOTHROW(j << f); // the array has 1112064 + 1 elemnts (a terminating "null" value) - // Note: 1112064 = 0x1FFFFF code points - 2047 invalid values between + // Note: 1112064 = 0x1FFFFF code points - 2048 invalid values between // 0xD800 and 0xDFFF. CHECK(j.size() == 1112065); From fd7c7be851a7a3cc8f2eb0f782a81cd709bcda67 Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 25 Jul 2016 19:38:51 +0200 Subject: [PATCH 36/48] fixed bash errors --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 64deb2fe7..0373ca3fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -168,8 +168,8 @@ script: - if [ `which valgrind` ]; then valgrind --error-exitcode=1 --leak-check=full ./json_unit ; fi - - if [ $os = "osx" ]; then + - if [ $os="osx" ]; then brew tap nlohmann/json ; brew install nlohmann_json --HEAD ; - brew test nlohmann_json + brew test nlohmann_json ; fi From cc8102f0c4e3ccc60d1fe8e2d37c0f4827cc36a3 Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 25 Jul 2016 22:19:49 +0200 Subject: [PATCH 37/48] used the wrong variable --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0373ca3fe..424465ebf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -168,7 +168,7 @@ script: - if [ `which valgrind` ]; then valgrind --error-exitcode=1 --leak-check=full ./json_unit ; fi - - if [ $os="osx" ]; then + - if [ $TRAVIS_OS_NAME="osx" ]; then brew tap nlohmann/json ; brew install nlohmann_json --HEAD ; brew test nlohmann_json ; From 5e88c6f2547cf1300940dbe3cadf4202dd5cd96f Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 25 Jul 2016 23:41:16 +0200 Subject: [PATCH 38/48] more on travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 424465ebf..ffe05ec6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -168,7 +168,8 @@ script: - if [ `which valgrind` ]; then valgrind --error-exitcode=1 --leak-check=full ./json_unit ; fi - - if [ $TRAVIS_OS_NAME="osx" ]; then + - if [ `which brew` ]; then + brew update ; brew tap nlohmann/json ; brew install nlohmann_json --HEAD ; brew test nlohmann_json ; From bdaade91f5705fd2b4c47f574d8d00328d5adb28 Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 27 Jul 2016 17:07:00 +0200 Subject: [PATCH 39/48] fixed some errors in the README gif --- doc/json.gif | Bin 451520 -> 450319 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/json.gif b/doc/json.gif index 7edafe018c464d59c673ee3913805c83a370ae35..46f005dd0da32ad9a2723e34edf4a8219699d118 100644 GIT binary patch delta 124209 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
~_H}DoB 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 B>zM!m delta 125410 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 Date: Wed, 27 Jul 2016 21:29:55 +0200 Subject: [PATCH 40/48] cleaned up code - removed unnecessary assertions - simplified simple if/return patterns --- ChangeLog.md | 3 + src/json.hpp | 234 ++++++++++++---------------------------------- src/json.hpp.re2c | 234 ++++++++++++---------------------------------- 3 files changed, 121 insertions(+), 350 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index e3a7cc07f..901e37c10 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file. This projec [Full Changelog](https://github.com/nlohmann/json/compare/v2.0.1...HEAD) +- value\(\) does not work with \_json\_pointer types [\#283](https://github.com/nlohmann/json/issues/283) +- Easy serialization of classes [\#280](https://github.com/nlohmann/json/issues/280) + - Build error for std::int64 [\#282](https://github.com/nlohmann/json/issues/282) - hexify\(\) function emits conversion warning [\#270](https://github.com/nlohmann/json/issues/270) diff --git a/src/json.hpp b/src/json.hpp index 15221b8be..9c80cee0b 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -621,8 +621,8 @@ class basic_json > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], this - class's integer type is interoperable. + number_integer_t type) of the exactly supported range [0, UINT64_MAX], + this class's integer type is interoperable. #### Storage @@ -760,6 +760,7 @@ class basic_json }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward(args)...); + assert(object.get() != nullptr); return object.release(); } @@ -1415,8 +1416,8 @@ class basic_json Create an unsigned integer number JSON value with a given content. - @tparam T helper type to compare number_unsigned_t and unsigned int - (not visible in) the interface. + @tparam T helper type to compare number_unsigned_t and unsigned int (not + visible in) the interface. @param[in] val an integer to create a JSON number from @@ -1521,8 +1522,8 @@ class basic_json disallows NaN values: > Numeric values that cannot be represented in the grammar below (such as > Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is - created instead. + In case the parameter @a val is not a number, a JSON null value is created + instead. @complexity Constant. @@ -1647,8 +1648,6 @@ class basic_json m_type = value_t::object; m_value = value_t::object; - assert(m_value.object != nullptr); - std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); @@ -1806,7 +1805,8 @@ class basic_json std::is_same::value , int>::type = 0> - basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type) + basic_json(InputIT first, InputIT last) + : m_type(first.m_object->m_type) { // make sure iterator fits the current value if (first.m_object != last.m_object) @@ -1840,35 +1840,30 @@ class basic_json { case value_t::number_integer: { - assert(first.m_object != nullptr); m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { - assert(first.m_object != nullptr); m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { - assert(first.m_object != nullptr); m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { - assert(first.m_object != nullptr); m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { - assert(first.m_object != nullptr); m_value = *first.m_object->m_value.string; break; } @@ -1887,7 +1882,6 @@ class basic_json default: { - assert(first.m_object != nullptr); throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); } } @@ -1951,21 +1945,18 @@ class basic_json { case value_t::object: { - assert(other.m_value.object != nullptr); m_value = *other.m_value.object; break; } case value_t::array: { - assert(other.m_value.array != nullptr); m_value = *other.m_value.array; break; } case value_t::string: { - assert(other.m_value.string != nullptr); m_value = *other.m_value.string; break; } @@ -2020,8 +2011,7 @@ class basic_json @since version 1.0.0 */ basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) + : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) { // invalidate payload other.m_type = value_t::null; @@ -2543,29 +2533,17 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - if (is_object()) - { - assert(m_value.object != nullptr); - return T(m_value.object->begin(), m_value.object->end()); - } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } + return is_object() + ? T(m_value.object->begin(), m_value.object->end()) + : throw std::domain_error("type must be object, but is " + type_name()); } /// get an object (explicit) object_t get_impl(object_t*) const { - if (is_object()) - { - assert(m_value.object != nullptr); - return *(m_value.object); - } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } + return is_object() + ? *(m_value.object) + : throw std::domain_error("type must be object, but is " + type_name()); } /// get an array (explicit) @@ -2582,7 +2560,6 @@ class basic_json if (is_array()) { T to_vector; - assert(m_value.array != nullptr); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) { @@ -2607,7 +2584,6 @@ class basic_json if (is_array()) { std::vector to_vector; - assert(m_value.array != nullptr); to_vector.reserve(m_value.array->size()); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) @@ -2630,29 +2606,17 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - if (is_array()) - { - assert(m_value.array != nullptr); - return T(m_value.array->begin(), m_value.array->end()); - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + return is_array() + ? T(m_value.array->begin(), m_value.array->end()) + : throw std::domain_error("type must be array, but is " + type_name()); } /// get an array (explicit) array_t get_impl(array_t*) const { - if (is_array()) - { - assert(m_value.array != nullptr); - return *(m_value.array); - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + return is_array() + ? *(m_value.array) + : throw std::domain_error("type must be array, but is " + type_name()); } /// get a string (explicit) @@ -2662,15 +2626,9 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - if (is_string()) - { - assert(m_value.string != nullptr); - return *m_value.string; - } - else - { - throw std::domain_error("type must be string, but is " + type_name()); - } + return is_string() + ? *m_value.string + : throw std::domain_error("type must be string, but is " + type_name()); } /// get a number (explicit) @@ -3140,7 +3098,6 @@ class basic_json { try { - assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3184,7 +3141,6 @@ class basic_json { try { - assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3232,7 +3188,6 @@ class basic_json { try { - assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3280,7 +3235,6 @@ class basic_json { try { - assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3333,7 +3287,6 @@ class basic_json if (is_array()) { // fill up array with null values if given idx is outside range - assert(m_value.array != nullptr); if (idx >= m_value.array->size()) { m_value.array->insert(m_value.array->end(), @@ -3371,15 +3324,9 @@ class basic_json const_reference operator[](size_type idx) const { // const operator[] only works for arrays - if (is_array()) - { - assert(m_value.array != nullptr); - return m_value.array->operator[](idx); - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_array() + ? m_value.array->operator[](idx) + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3419,15 +3366,9 @@ class basic_json } // operator[] only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - return m_value.object->operator[](key); - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_object() + ? m_value.object->operator[](key) + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3460,16 +3401,9 @@ class basic_json const_reference operator[](const typename object_t::key_type& key) const { // const operator[] only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - assert(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_object() + ? m_value.object->find(key)->second + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3578,15 +3512,9 @@ class basic_json } // at only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - return m_value.object->operator[](key); - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_object() + ? m_value.object->operator[](key) + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3620,16 +3548,9 @@ class basic_json const_reference operator[](T* key) const { // at only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - assert(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_object() + ? m_value.object->find(key)->second + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3959,14 +3880,12 @@ class basic_json case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } @@ -4067,7 +3986,6 @@ class basic_json case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; @@ -4075,7 +3993,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; @@ -4122,15 +4039,9 @@ class basic_json size_type erase(const typename object_t::key_type& key) { // this erase only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - return m_value.object->erase(key); - } - else - { - throw std::domain_error("cannot use erase() with " + type_name()); - } + return is_object() + ? m_value.object->erase(key) + : throw std::domain_error("cannot use erase() with " + type_name()); } /*! @@ -4167,7 +4078,6 @@ class basic_json throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); } - assert(m_value.array != nullptr); m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else @@ -4210,7 +4120,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4227,7 +4136,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4255,7 +4163,6 @@ class basic_json size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types - assert(not is_object() or m_value.object != nullptr); return is_object() ? m_value.object->count(key) : 0; } @@ -4597,6 +4504,10 @@ class basic_json object | result of function `object_t::empty()` array | result of function `array_t::empty()` + @note This function does not return whether a string stored as JSON value + is empty - it returns whether the JSON container itself is empty which is + false in the case of a string. + @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their `empty()` functions have constant complexity. @@ -4626,13 +4537,13 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::empty() return m_value.array->empty(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::empty() return m_value.object->empty(); } @@ -4660,6 +4571,10 @@ class basic_json object | result of function object_t::size() array | result of function array_t::size() + @note This function does not return the length of a string stored as JSON + value - it returns the number of elements in the JSON value which is 1 in + the case of a string. + @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their size() functions have constant complexity. @@ -4690,13 +4605,13 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::size() return m_value.array->size(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::size() return m_value.object->size(); } @@ -4750,13 +4665,13 @@ class basic_json { case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::max_size() return m_value.array->max_size(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::max_size() return m_value.object->max_size(); } @@ -4833,21 +4748,18 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); m_value.string->clear(); break; } case value_t::array: { - assert(m_value.array != nullptr); m_value.array->clear(); break; } case value_t::object: { - assert(m_value.object != nullptr); m_value.object->clear(); break; } @@ -4895,7 +4807,6 @@ class basic_json } // add element to array (move semantics) - assert(m_value.array != nullptr); m_value.array->push_back(std::move(val)); // invalidate object val.m_type = value_t::null; @@ -4931,7 +4842,6 @@ class basic_json } // add element to array - assert(m_value.array != nullptr); m_value.array->push_back(val); } @@ -4981,7 +4891,6 @@ class basic_json } // add element to array - assert(m_value.object != nullptr); m_value.object->insert(val); } @@ -5078,7 +4987,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } @@ -5134,7 +5042,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } @@ -5201,7 +5108,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert( pos.m_it.array_iterator, first.m_it.array_iterator, @@ -5249,7 +5155,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); return result; } @@ -5307,7 +5212,6 @@ class basic_json // swap only works for arrays if (is_array()) { - assert(m_value.array != nullptr); std::swap(*(m_value.array), other); } else @@ -5341,7 +5245,6 @@ class basic_json // swap only works for objects if (is_object()) { - assert(m_value.object != nullptr); std::swap(*(m_value.object), other); } else @@ -5375,7 +5278,6 @@ class basic_json // swap only works for strings if (is_string()) { - assert(m_value.string != nullptr); std::swap(*(m_value.string), other); } else @@ -5462,14 +5364,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array == *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object == *rhs.m_value.object; } case value_t::null: @@ -5478,8 +5376,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string == *rhs.m_value.string; } case value_t::boolean: @@ -5652,14 +5548,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: @@ -5668,8 +5560,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: @@ -5844,14 +5734,14 @@ class basic_json // string->float->string, string->double->string or string->long // double->string; to be safe, we read this value from // std::numeric_limits::digits10 - const auto old_preicison = o.precision(std::numeric_limits::digits10); + const auto old_precision = o.precision(std::numeric_limits::digits10); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); // reset locale and precision o.imbue(old_locale); - o.precision(old_preicison); + o.precision(old_precision); return o; } @@ -6201,8 +6091,6 @@ class basic_json { case value_t::object: { - assert(m_value.object != nullptr); - if (m_value.object->empty()) { o << "{}"; @@ -6243,8 +6131,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); - if (m_value.array->empty()) { o << "[]"; @@ -6283,7 +6169,6 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); o << string_t("\"") << escape_string(*m_value.string) << "\""; return; } @@ -9522,7 +9407,6 @@ basic_json_parser_63: basic_json result; // iterate the JSON object values - assert(value.m_value.object != nullptr); for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 74db214eb..73e6d8e57 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -621,8 +621,8 @@ class basic_json > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], this - class's integer type is interoperable. + number_integer_t type) of the exactly supported range [0, UINT64_MAX], + this class's integer type is interoperable. #### Storage @@ -760,6 +760,7 @@ class basic_json }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward(args)...); + assert(object.get() != nullptr); return object.release(); } @@ -1415,8 +1416,8 @@ class basic_json Create an unsigned integer number JSON value with a given content. - @tparam T helper type to compare number_unsigned_t and unsigned int - (not visible in) the interface. + @tparam T helper type to compare number_unsigned_t and unsigned int (not + visible in) the interface. @param[in] val an integer to create a JSON number from @@ -1521,8 +1522,8 @@ class basic_json disallows NaN values: > Numeric values that cannot be represented in the grammar below (such as > Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is - created instead. + In case the parameter @a val is not a number, a JSON null value is created + instead. @complexity Constant. @@ -1647,8 +1648,6 @@ class basic_json m_type = value_t::object; m_value = value_t::object; - assert(m_value.object != nullptr); - std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); @@ -1806,7 +1805,8 @@ class basic_json std::is_same::value , int>::type = 0> - basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type) + basic_json(InputIT first, InputIT last) + : m_type(first.m_object->m_type) { // make sure iterator fits the current value if (first.m_object != last.m_object) @@ -1840,35 +1840,30 @@ class basic_json { case value_t::number_integer: { - assert(first.m_object != nullptr); m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { - assert(first.m_object != nullptr); m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { - assert(first.m_object != nullptr); m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { - assert(first.m_object != nullptr); m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { - assert(first.m_object != nullptr); m_value = *first.m_object->m_value.string; break; } @@ -1887,7 +1882,6 @@ class basic_json default: { - assert(first.m_object != nullptr); throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); } } @@ -1951,21 +1945,18 @@ class basic_json { case value_t::object: { - assert(other.m_value.object != nullptr); m_value = *other.m_value.object; break; } case value_t::array: { - assert(other.m_value.array != nullptr); m_value = *other.m_value.array; break; } case value_t::string: { - assert(other.m_value.string != nullptr); m_value = *other.m_value.string; break; } @@ -2020,8 +2011,7 @@ class basic_json @since version 1.0.0 */ basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) + : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) { // invalidate payload other.m_type = value_t::null; @@ -2543,29 +2533,17 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - if (is_object()) - { - assert(m_value.object != nullptr); - return T(m_value.object->begin(), m_value.object->end()); - } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } + return is_object() + ? T(m_value.object->begin(), m_value.object->end()) + : throw std::domain_error("type must be object, but is " + type_name()); } /// get an object (explicit) object_t get_impl(object_t*) const { - if (is_object()) - { - assert(m_value.object != nullptr); - return *(m_value.object); - } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } + return is_object() + ? *(m_value.object) + : throw std::domain_error("type must be object, but is " + type_name()); } /// get an array (explicit) @@ -2582,7 +2560,6 @@ class basic_json if (is_array()) { T to_vector; - assert(m_value.array != nullptr); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) { @@ -2607,7 +2584,6 @@ class basic_json if (is_array()) { std::vector to_vector; - assert(m_value.array != nullptr); to_vector.reserve(m_value.array->size()); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) @@ -2630,29 +2606,17 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - if (is_array()) - { - assert(m_value.array != nullptr); - return T(m_value.array->begin(), m_value.array->end()); - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + return is_array() + ? T(m_value.array->begin(), m_value.array->end()) + : throw std::domain_error("type must be array, but is " + type_name()); } /// get an array (explicit) array_t get_impl(array_t*) const { - if (is_array()) - { - assert(m_value.array != nullptr); - return *(m_value.array); - } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + return is_array() + ? *(m_value.array) + : throw std::domain_error("type must be array, but is " + type_name()); } /// get a string (explicit) @@ -2662,15 +2626,9 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - if (is_string()) - { - assert(m_value.string != nullptr); - return *m_value.string; - } - else - { - throw std::domain_error("type must be string, but is " + type_name()); - } + return is_string() + ? *m_value.string + : throw std::domain_error("type must be string, but is " + type_name()); } /// get a number (explicit) @@ -3140,7 +3098,6 @@ class basic_json { try { - assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3184,7 +3141,6 @@ class basic_json { try { - assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3232,7 +3188,6 @@ class basic_json { try { - assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3280,7 +3235,6 @@ class basic_json { try { - assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3333,7 +3287,6 @@ class basic_json if (is_array()) { // fill up array with null values if given idx is outside range - assert(m_value.array != nullptr); if (idx >= m_value.array->size()) { m_value.array->insert(m_value.array->end(), @@ -3371,15 +3324,9 @@ class basic_json const_reference operator[](size_type idx) const { // const operator[] only works for arrays - if (is_array()) - { - assert(m_value.array != nullptr); - return m_value.array->operator[](idx); - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_array() + ? m_value.array->operator[](idx) + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3419,15 +3366,9 @@ class basic_json } // operator[] only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - return m_value.object->operator[](key); - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_object() + ? m_value.object->operator[](key) + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3460,16 +3401,9 @@ class basic_json const_reference operator[](const typename object_t::key_type& key) const { // const operator[] only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - assert(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_object() + ? m_value.object->find(key)->second + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3578,15 +3512,9 @@ class basic_json } // at only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - return m_value.object->operator[](key); - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_object() + ? m_value.object->operator[](key) + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3620,16 +3548,9 @@ class basic_json const_reference operator[](T* key) const { // at only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - assert(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + return is_object() + ? m_value.object->find(key)->second + : throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3959,14 +3880,12 @@ class basic_json case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } @@ -4067,7 +3986,6 @@ class basic_json case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; @@ -4075,7 +3993,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; @@ -4122,15 +4039,9 @@ class basic_json size_type erase(const typename object_t::key_type& key) { // this erase only works for objects - if (is_object()) - { - assert(m_value.object != nullptr); - return m_value.object->erase(key); - } - else - { - throw std::domain_error("cannot use erase() with " + type_name()); - } + return is_object() + ? m_value.object->erase(key) + : throw std::domain_error("cannot use erase() with " + type_name()); } /*! @@ -4167,7 +4078,6 @@ class basic_json throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); } - assert(m_value.array != nullptr); m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else @@ -4210,7 +4120,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4227,7 +4136,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4255,7 +4163,6 @@ class basic_json size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types - assert(not is_object() or m_value.object != nullptr); return is_object() ? m_value.object->count(key) : 0; } @@ -4597,6 +4504,10 @@ class basic_json object | result of function `object_t::empty()` array | result of function `array_t::empty()` + @note This function does not return whether a string stored as JSON value + is empty - it returns whether the JSON container itself is empty which is + false in the case of a string. + @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their `empty()` functions have constant complexity. @@ -4626,13 +4537,13 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::empty() return m_value.array->empty(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::empty() return m_value.object->empty(); } @@ -4660,6 +4571,10 @@ class basic_json object | result of function object_t::size() array | result of function array_t::size() + @note This function does not return the length of a string stored as JSON + value - it returns the number of elements in the JSON value which is 1 in + the case of a string. + @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their size() functions have constant complexity. @@ -4690,13 +4605,13 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::size() return m_value.array->size(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::size() return m_value.object->size(); } @@ -4750,13 +4665,13 @@ class basic_json { case value_t::array: { - assert(m_value.array != nullptr); + // delegate call to array_t::max_size() return m_value.array->max_size(); } case value_t::object: { - assert(m_value.object != nullptr); + // delegate call to object_t::max_size() return m_value.object->max_size(); } @@ -4833,21 +4748,18 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); m_value.string->clear(); break; } case value_t::array: { - assert(m_value.array != nullptr); m_value.array->clear(); break; } case value_t::object: { - assert(m_value.object != nullptr); m_value.object->clear(); break; } @@ -4895,7 +4807,6 @@ class basic_json } // add element to array (move semantics) - assert(m_value.array != nullptr); m_value.array->push_back(std::move(val)); // invalidate object val.m_type = value_t::null; @@ -4931,7 +4842,6 @@ class basic_json } // add element to array - assert(m_value.array != nullptr); m_value.array->push_back(val); } @@ -4981,7 +4891,6 @@ class basic_json } // add element to array - assert(m_value.object != nullptr); m_value.object->insert(val); } @@ -5078,7 +4987,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } @@ -5134,7 +5042,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } @@ -5201,7 +5108,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert( pos.m_it.array_iterator, first.m_it.array_iterator, @@ -5249,7 +5155,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); return result; } @@ -5307,7 +5212,6 @@ class basic_json // swap only works for arrays if (is_array()) { - assert(m_value.array != nullptr); std::swap(*(m_value.array), other); } else @@ -5341,7 +5245,6 @@ class basic_json // swap only works for objects if (is_object()) { - assert(m_value.object != nullptr); std::swap(*(m_value.object), other); } else @@ -5375,7 +5278,6 @@ class basic_json // swap only works for strings if (is_string()) { - assert(m_value.string != nullptr); std::swap(*(m_value.string), other); } else @@ -5462,14 +5364,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array == *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object == *rhs.m_value.object; } case value_t::null: @@ -5478,8 +5376,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string == *rhs.m_value.string; } case value_t::boolean: @@ -5652,14 +5548,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: @@ -5668,8 +5560,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: @@ -5844,14 +5734,14 @@ class basic_json // string->float->string, string->double->string or string->long // double->string; to be safe, we read this value from // std::numeric_limits::digits10 - const auto old_preicison = o.precision(std::numeric_limits::digits10); + const auto old_precision = o.precision(std::numeric_limits::digits10); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); // reset locale and precision o.imbue(old_locale); - o.precision(old_preicison); + o.precision(old_precision); return o; } @@ -6201,8 +6091,6 @@ class basic_json { case value_t::object: { - assert(m_value.object != nullptr); - if (m_value.object->empty()) { o << "{}"; @@ -6243,8 +6131,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); - if (m_value.array->empty()) { o << "[]"; @@ -6283,7 +6169,6 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); o << string_t("\"") << escape_string(*m_value.string) << "\""; return; } @@ -8819,7 +8704,6 @@ class basic_json basic_json result; // iterate the JSON object values - assert(value.m_value.object != nullptr); for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) From 6297631e22f28e8691add1a65898f33ca7b13e59 Mon Sep 17 00:00:00 2001 From: Niels Date: Wed, 27 Jul 2016 21:40:15 +0200 Subject: [PATCH 41/48] reverted breaking changes --- src/json.hpp | 234 ++++++++++++++++++++++++++++++++++------------ src/json.hpp.re2c | 234 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 350 insertions(+), 118 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 9c80cee0b..15221b8be 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -621,8 +621,8 @@ class basic_json > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], - this class's integer type is interoperable. + number_integer_t type) of the exactly supported range [0, UINT64_MAX], this + class's integer type is interoperable. #### Storage @@ -760,7 +760,6 @@ class basic_json }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward(args)...); - assert(object.get() != nullptr); return object.release(); } @@ -1416,8 +1415,8 @@ class basic_json Create an unsigned integer number JSON value with a given content. - @tparam T helper type to compare number_unsigned_t and unsigned int (not - visible in) the interface. + @tparam T helper type to compare number_unsigned_t and unsigned int + (not visible in) the interface. @param[in] val an integer to create a JSON number from @@ -1522,8 +1521,8 @@ class basic_json disallows NaN values: > Numeric values that cannot be represented in the grammar below (such as > Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is created - instead. + In case the parameter @a val is not a number, a JSON null value is + created instead. @complexity Constant. @@ -1648,6 +1647,8 @@ class basic_json m_type = value_t::object; m_value = value_t::object; + assert(m_value.object != nullptr); + std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); @@ -1805,8 +1806,7 @@ class basic_json std::is_same::value , int>::type = 0> - basic_json(InputIT first, InputIT last) - : m_type(first.m_object->m_type) + basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type) { // make sure iterator fits the current value if (first.m_object != last.m_object) @@ -1840,30 +1840,35 @@ class basic_json { case value_t::number_integer: { + assert(first.m_object != nullptr); m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { + assert(first.m_object != nullptr); m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { + assert(first.m_object != nullptr); m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { + assert(first.m_object != nullptr); m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { + assert(first.m_object != nullptr); m_value = *first.m_object->m_value.string; break; } @@ -1882,6 +1887,7 @@ class basic_json default: { + assert(first.m_object != nullptr); throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); } } @@ -1945,18 +1951,21 @@ class basic_json { case value_t::object: { + assert(other.m_value.object != nullptr); m_value = *other.m_value.object; break; } case value_t::array: { + assert(other.m_value.array != nullptr); m_value = *other.m_value.array; break; } case value_t::string: { + assert(other.m_value.string != nullptr); m_value = *other.m_value.string; break; } @@ -2011,7 +2020,8 @@ class basic_json @since version 1.0.0 */ basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) { // invalidate payload other.m_type = value_t::null; @@ -2533,17 +2543,29 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - return is_object() - ? T(m_value.object->begin(), m_value.object->end()) - : throw std::domain_error("type must be object, but is " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return T(m_value.object->begin(), m_value.object->end()); + } + else + { + throw std::domain_error("type must be object, but is " + type_name()); + } } /// get an object (explicit) object_t get_impl(object_t*) const { - return is_object() - ? *(m_value.object) - : throw std::domain_error("type must be object, but is " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return *(m_value.object); + } + else + { + throw std::domain_error("type must be object, but is " + type_name()); + } } /// get an array (explicit) @@ -2560,6 +2582,7 @@ class basic_json if (is_array()) { T to_vector; + assert(m_value.array != nullptr); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) { @@ -2584,6 +2607,7 @@ class basic_json if (is_array()) { std::vector to_vector; + assert(m_value.array != nullptr); to_vector.reserve(m_value.array->size()); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) @@ -2606,17 +2630,29 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - return is_array() - ? T(m_value.array->begin(), m_value.array->end()) - : throw std::domain_error("type must be array, but is " + type_name()); + if (is_array()) + { + assert(m_value.array != nullptr); + return T(m_value.array->begin(), m_value.array->end()); + } + else + { + throw std::domain_error("type must be array, but is " + type_name()); + } } /// get an array (explicit) array_t get_impl(array_t*) const { - return is_array() - ? *(m_value.array) - : throw std::domain_error("type must be array, but is " + type_name()); + if (is_array()) + { + assert(m_value.array != nullptr); + return *(m_value.array); + } + else + { + throw std::domain_error("type must be array, but is " + type_name()); + } } /// get a string (explicit) @@ -2626,9 +2662,15 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - return is_string() - ? *m_value.string - : throw std::domain_error("type must be string, but is " + type_name()); + if (is_string()) + { + assert(m_value.string != nullptr); + return *m_value.string; + } + else + { + throw std::domain_error("type must be string, but is " + type_name()); + } } /// get a number (explicit) @@ -3098,6 +3140,7 @@ class basic_json { try { + assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3141,6 +3184,7 @@ class basic_json { try { + assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3188,6 +3232,7 @@ class basic_json { try { + assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3235,6 +3280,7 @@ class basic_json { try { + assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3287,6 +3333,7 @@ class basic_json if (is_array()) { // fill up array with null values if given idx is outside range + assert(m_value.array != nullptr); if (idx >= m_value.array->size()) { m_value.array->insert(m_value.array->end(), @@ -3324,9 +3371,15 @@ class basic_json const_reference operator[](size_type idx) const { // const operator[] only works for arrays - return is_array() - ? m_value.array->operator[](idx) - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_array()) + { + assert(m_value.array != nullptr); + return m_value.array->operator[](idx); + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3366,9 +3419,15 @@ class basic_json } // operator[] only works for objects - return is_object() - ? m_value.object->operator[](key) - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return m_value.object->operator[](key); + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3401,9 +3460,16 @@ class basic_json const_reference operator[](const typename object_t::key_type& key) const { // const operator[] only works for objects - return is_object() - ? m_value.object->find(key)->second - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + assert(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3512,9 +3578,15 @@ class basic_json } // at only works for objects - return is_object() - ? m_value.object->operator[](key) - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return m_value.object->operator[](key); + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3548,9 +3620,16 @@ class basic_json const_reference operator[](T* key) const { // at only works for objects - return is_object() - ? m_value.object->find(key)->second - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + assert(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3880,12 +3959,14 @@ class basic_json case value_t::object: { + assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } @@ -3986,6 +4067,7 @@ class basic_json case value_t::object: { + assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; @@ -3993,6 +4075,7 @@ class basic_json case value_t::array: { + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; @@ -4039,9 +4122,15 @@ class basic_json size_type erase(const typename object_t::key_type& key) { // this erase only works for objects - return is_object() - ? m_value.object->erase(key) - : throw std::domain_error("cannot use erase() with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return m_value.object->erase(key); + } + else + { + throw std::domain_error("cannot use erase() with " + type_name()); + } } /*! @@ -4078,6 +4167,7 @@ class basic_json throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); } + assert(m_value.array != nullptr); m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else @@ -4120,6 +4210,7 @@ class basic_json if (is_object()) { + assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4136,6 +4227,7 @@ class basic_json if (is_object()) { + assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4163,6 +4255,7 @@ class basic_json size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types + assert(not is_object() or m_value.object != nullptr); return is_object() ? m_value.object->count(key) : 0; } @@ -4504,10 +4597,6 @@ class basic_json object | result of function `object_t::empty()` array | result of function `array_t::empty()` - @note This function does not return whether a string stored as JSON value - is empty - it returns whether the JSON container itself is empty which is - false in the case of a string. - @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their `empty()` functions have constant complexity. @@ -4537,13 +4626,13 @@ class basic_json case value_t::array: { - // delegate call to array_t::empty() + assert(m_value.array != nullptr); return m_value.array->empty(); } case value_t::object: { - // delegate call to object_t::empty() + assert(m_value.object != nullptr); return m_value.object->empty(); } @@ -4571,10 +4660,6 @@ class basic_json object | result of function object_t::size() array | result of function array_t::size() - @note This function does not return the length of a string stored as JSON - value - it returns the number of elements in the JSON value which is 1 in - the case of a string. - @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their size() functions have constant complexity. @@ -4605,13 +4690,13 @@ class basic_json case value_t::array: { - // delegate call to array_t::size() + assert(m_value.array != nullptr); return m_value.array->size(); } case value_t::object: { - // delegate call to object_t::size() + assert(m_value.object != nullptr); return m_value.object->size(); } @@ -4665,13 +4750,13 @@ class basic_json { case value_t::array: { - // delegate call to array_t::max_size() + assert(m_value.array != nullptr); return m_value.array->max_size(); } case value_t::object: { - // delegate call to object_t::max_size() + assert(m_value.object != nullptr); return m_value.object->max_size(); } @@ -4748,18 +4833,21 @@ class basic_json case value_t::string: { + assert(m_value.string != nullptr); m_value.string->clear(); break; } case value_t::array: { + assert(m_value.array != nullptr); m_value.array->clear(); break; } case value_t::object: { + assert(m_value.object != nullptr); m_value.object->clear(); break; } @@ -4807,6 +4895,7 @@ class basic_json } // add element to array (move semantics) + assert(m_value.array != nullptr); m_value.array->push_back(std::move(val)); // invalidate object val.m_type = value_t::null; @@ -4842,6 +4931,7 @@ class basic_json } // add element to array + assert(m_value.array != nullptr); m_value.array->push_back(val); } @@ -4891,6 +4981,7 @@ class basic_json } // add element to array + assert(m_value.object != nullptr); m_value.object->insert(val); } @@ -4987,6 +5078,7 @@ class basic_json // insert to array and return iterator iterator result(this); + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } @@ -5042,6 +5134,7 @@ class basic_json // insert to array and return iterator iterator result(this); + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } @@ -5108,6 +5201,7 @@ class basic_json // insert to array and return iterator iterator result(this); + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert( pos.m_it.array_iterator, first.m_it.array_iterator, @@ -5155,6 +5249,7 @@ class basic_json // insert to array and return iterator iterator result(this); + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); return result; } @@ -5212,6 +5307,7 @@ class basic_json // swap only works for arrays if (is_array()) { + assert(m_value.array != nullptr); std::swap(*(m_value.array), other); } else @@ -5245,6 +5341,7 @@ class basic_json // swap only works for objects if (is_object()) { + assert(m_value.object != nullptr); std::swap(*(m_value.object), other); } else @@ -5278,6 +5375,7 @@ class basic_json // swap only works for strings if (is_string()) { + assert(m_value.string != nullptr); std::swap(*(m_value.string), other); } else @@ -5364,10 +5462,14 @@ class basic_json { case value_t::array: { + assert(lhs.m_value.array != nullptr); + assert(rhs.m_value.array != nullptr); return *lhs.m_value.array == *rhs.m_value.array; } case value_t::object: { + assert(lhs.m_value.object != nullptr); + assert(rhs.m_value.object != nullptr); return *lhs.m_value.object == *rhs.m_value.object; } case value_t::null: @@ -5376,6 +5478,8 @@ class basic_json } case value_t::string: { + assert(lhs.m_value.string != nullptr); + assert(rhs.m_value.string != nullptr); return *lhs.m_value.string == *rhs.m_value.string; } case value_t::boolean: @@ -5548,10 +5652,14 @@ class basic_json { case value_t::array: { + assert(lhs.m_value.array != nullptr); + assert(rhs.m_value.array != nullptr); return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { + assert(lhs.m_value.object != nullptr); + assert(rhs.m_value.object != nullptr); return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: @@ -5560,6 +5668,8 @@ class basic_json } case value_t::string: { + assert(lhs.m_value.string != nullptr); + assert(rhs.m_value.string != nullptr); return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: @@ -5734,14 +5844,14 @@ class basic_json // string->float->string, string->double->string or string->long // double->string; to be safe, we read this value from // std::numeric_limits::digits10 - const auto old_precision = o.precision(std::numeric_limits::digits10); + const auto old_preicison = o.precision(std::numeric_limits::digits10); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); // reset locale and precision o.imbue(old_locale); - o.precision(old_precision); + o.precision(old_preicison); return o; } @@ -6091,6 +6201,8 @@ class basic_json { case value_t::object: { + assert(m_value.object != nullptr); + if (m_value.object->empty()) { o << "{}"; @@ -6131,6 +6243,8 @@ class basic_json case value_t::array: { + assert(m_value.array != nullptr); + if (m_value.array->empty()) { o << "[]"; @@ -6169,6 +6283,7 @@ class basic_json case value_t::string: { + assert(m_value.string != nullptr); o << string_t("\"") << escape_string(*m_value.string) << "\""; return; } @@ -9407,6 +9522,7 @@ basic_json_parser_63: basic_json result; // iterate the JSON object values + assert(value.m_value.object != nullptr); for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 73e6d8e57..74db214eb 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -621,8 +621,8 @@ class basic_json > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], - this class's integer type is interoperable. + number_integer_t type) of the exactly supported range [0, UINT64_MAX], this + class's integer type is interoperable. #### Storage @@ -760,7 +760,6 @@ class basic_json }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward(args)...); - assert(object.get() != nullptr); return object.release(); } @@ -1416,8 +1415,8 @@ class basic_json Create an unsigned integer number JSON value with a given content. - @tparam T helper type to compare number_unsigned_t and unsigned int (not - visible in) the interface. + @tparam T helper type to compare number_unsigned_t and unsigned int + (not visible in) the interface. @param[in] val an integer to create a JSON number from @@ -1522,8 +1521,8 @@ class basic_json disallows NaN values: > Numeric values that cannot be represented in the grammar below (such as > Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is created - instead. + In case the parameter @a val is not a number, a JSON null value is + created instead. @complexity Constant. @@ -1648,6 +1647,8 @@ class basic_json m_type = value_t::object; m_value = value_t::object; + assert(m_value.object != nullptr); + std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); @@ -1805,8 +1806,7 @@ class basic_json std::is_same::value , int>::type = 0> - basic_json(InputIT first, InputIT last) - : m_type(first.m_object->m_type) + basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type) { // make sure iterator fits the current value if (first.m_object != last.m_object) @@ -1840,30 +1840,35 @@ class basic_json { case value_t::number_integer: { + assert(first.m_object != nullptr); m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { + assert(first.m_object != nullptr); m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { + assert(first.m_object != nullptr); m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { + assert(first.m_object != nullptr); m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { + assert(first.m_object != nullptr); m_value = *first.m_object->m_value.string; break; } @@ -1882,6 +1887,7 @@ class basic_json default: { + assert(first.m_object != nullptr); throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); } } @@ -1945,18 +1951,21 @@ class basic_json { case value_t::object: { + assert(other.m_value.object != nullptr); m_value = *other.m_value.object; break; } case value_t::array: { + assert(other.m_value.array != nullptr); m_value = *other.m_value.array; break; } case value_t::string: { + assert(other.m_value.string != nullptr); m_value = *other.m_value.string; break; } @@ -2011,7 +2020,8 @@ class basic_json @since version 1.0.0 */ basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) { // invalidate payload other.m_type = value_t::null; @@ -2533,17 +2543,29 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - return is_object() - ? T(m_value.object->begin(), m_value.object->end()) - : throw std::domain_error("type must be object, but is " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return T(m_value.object->begin(), m_value.object->end()); + } + else + { + throw std::domain_error("type must be object, but is " + type_name()); + } } /// get an object (explicit) object_t get_impl(object_t*) const { - return is_object() - ? *(m_value.object) - : throw std::domain_error("type must be object, but is " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return *(m_value.object); + } + else + { + throw std::domain_error("type must be object, but is " + type_name()); + } } /// get an array (explicit) @@ -2560,6 +2582,7 @@ class basic_json if (is_array()) { T to_vector; + assert(m_value.array != nullptr); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) { @@ -2584,6 +2607,7 @@ class basic_json if (is_array()) { std::vector to_vector; + assert(m_value.array != nullptr); to_vector.reserve(m_value.array->size()); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) @@ -2606,17 +2630,29 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - return is_array() - ? T(m_value.array->begin(), m_value.array->end()) - : throw std::domain_error("type must be array, but is " + type_name()); + if (is_array()) + { + assert(m_value.array != nullptr); + return T(m_value.array->begin(), m_value.array->end()); + } + else + { + throw std::domain_error("type must be array, but is " + type_name()); + } } /// get an array (explicit) array_t get_impl(array_t*) const { - return is_array() - ? *(m_value.array) - : throw std::domain_error("type must be array, but is " + type_name()); + if (is_array()) + { + assert(m_value.array != nullptr); + return *(m_value.array); + } + else + { + throw std::domain_error("type must be array, but is " + type_name()); + } } /// get a string (explicit) @@ -2626,9 +2662,15 @@ class basic_json , int>::type = 0> T get_impl(T*) const { - return is_string() - ? *m_value.string - : throw std::domain_error("type must be string, but is " + type_name()); + if (is_string()) + { + assert(m_value.string != nullptr); + return *m_value.string; + } + else + { + throw std::domain_error("type must be string, but is " + type_name()); + } } /// get a number (explicit) @@ -3098,6 +3140,7 @@ class basic_json { try { + assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3141,6 +3184,7 @@ class basic_json { try { + assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3188,6 +3232,7 @@ class basic_json { try { + assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3235,6 +3280,7 @@ class basic_json { try { + assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3287,6 +3333,7 @@ class basic_json if (is_array()) { // fill up array with null values if given idx is outside range + assert(m_value.array != nullptr); if (idx >= m_value.array->size()) { m_value.array->insert(m_value.array->end(), @@ -3324,9 +3371,15 @@ class basic_json const_reference operator[](size_type idx) const { // const operator[] only works for arrays - return is_array() - ? m_value.array->operator[](idx) - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_array()) + { + assert(m_value.array != nullptr); + return m_value.array->operator[](idx); + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3366,9 +3419,15 @@ class basic_json } // operator[] only works for objects - return is_object() - ? m_value.object->operator[](key) - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return m_value.object->operator[](key); + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3401,9 +3460,16 @@ class basic_json const_reference operator[](const typename object_t::key_type& key) const { // const operator[] only works for objects - return is_object() - ? m_value.object->find(key)->second - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + assert(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3512,9 +3578,15 @@ class basic_json } // at only works for objects - return is_object() - ? m_value.object->operator[](key) - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return m_value.object->operator[](key); + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3548,9 +3620,16 @@ class basic_json const_reference operator[](T* key) const { // at only works for objects - return is_object() - ? m_value.object->find(key)->second - : throw std::domain_error("cannot use operator[] with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + assert(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + else + { + throw std::domain_error("cannot use operator[] with " + type_name()); + } } /*! @@ -3880,12 +3959,14 @@ class basic_json case value_t::object: { + assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } @@ -3986,6 +4067,7 @@ class basic_json case value_t::object: { + assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; @@ -3993,6 +4075,7 @@ class basic_json case value_t::array: { + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; @@ -4039,9 +4122,15 @@ class basic_json size_type erase(const typename object_t::key_type& key) { // this erase only works for objects - return is_object() - ? m_value.object->erase(key) - : throw std::domain_error("cannot use erase() with " + type_name()); + if (is_object()) + { + assert(m_value.object != nullptr); + return m_value.object->erase(key); + } + else + { + throw std::domain_error("cannot use erase() with " + type_name()); + } } /*! @@ -4078,6 +4167,7 @@ class basic_json throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); } + assert(m_value.array != nullptr); m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else @@ -4120,6 +4210,7 @@ class basic_json if (is_object()) { + assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4136,6 +4227,7 @@ class basic_json if (is_object()) { + assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4163,6 +4255,7 @@ class basic_json size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types + assert(not is_object() or m_value.object != nullptr); return is_object() ? m_value.object->count(key) : 0; } @@ -4504,10 +4597,6 @@ class basic_json object | result of function `object_t::empty()` array | result of function `array_t::empty()` - @note This function does not return whether a string stored as JSON value - is empty - it returns whether the JSON container itself is empty which is - false in the case of a string. - @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their `empty()` functions have constant complexity. @@ -4537,13 +4626,13 @@ class basic_json case value_t::array: { - // delegate call to array_t::empty() + assert(m_value.array != nullptr); return m_value.array->empty(); } case value_t::object: { - // delegate call to object_t::empty() + assert(m_value.object != nullptr); return m_value.object->empty(); } @@ -4571,10 +4660,6 @@ class basic_json object | result of function object_t::size() array | result of function array_t::size() - @note This function does not return the length of a string stored as JSON - value - it returns the number of elements in the JSON value which is 1 in - the case of a string. - @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their size() functions have constant complexity. @@ -4605,13 +4690,13 @@ class basic_json case value_t::array: { - // delegate call to array_t::size() + assert(m_value.array != nullptr); return m_value.array->size(); } case value_t::object: { - // delegate call to object_t::size() + assert(m_value.object != nullptr); return m_value.object->size(); } @@ -4665,13 +4750,13 @@ class basic_json { case value_t::array: { - // delegate call to array_t::max_size() + assert(m_value.array != nullptr); return m_value.array->max_size(); } case value_t::object: { - // delegate call to object_t::max_size() + assert(m_value.object != nullptr); return m_value.object->max_size(); } @@ -4748,18 +4833,21 @@ class basic_json case value_t::string: { + assert(m_value.string != nullptr); m_value.string->clear(); break; } case value_t::array: { + assert(m_value.array != nullptr); m_value.array->clear(); break; } case value_t::object: { + assert(m_value.object != nullptr); m_value.object->clear(); break; } @@ -4807,6 +4895,7 @@ class basic_json } // add element to array (move semantics) + assert(m_value.array != nullptr); m_value.array->push_back(std::move(val)); // invalidate object val.m_type = value_t::null; @@ -4842,6 +4931,7 @@ class basic_json } // add element to array + assert(m_value.array != nullptr); m_value.array->push_back(val); } @@ -4891,6 +4981,7 @@ class basic_json } // add element to array + assert(m_value.object != nullptr); m_value.object->insert(val); } @@ -4987,6 +5078,7 @@ class basic_json // insert to array and return iterator iterator result(this); + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } @@ -5042,6 +5134,7 @@ class basic_json // insert to array and return iterator iterator result(this); + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } @@ -5108,6 +5201,7 @@ class basic_json // insert to array and return iterator iterator result(this); + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert( pos.m_it.array_iterator, first.m_it.array_iterator, @@ -5155,6 +5249,7 @@ class basic_json // insert to array and return iterator iterator result(this); + assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); return result; } @@ -5212,6 +5307,7 @@ class basic_json // swap only works for arrays if (is_array()) { + assert(m_value.array != nullptr); std::swap(*(m_value.array), other); } else @@ -5245,6 +5341,7 @@ class basic_json // swap only works for objects if (is_object()) { + assert(m_value.object != nullptr); std::swap(*(m_value.object), other); } else @@ -5278,6 +5375,7 @@ class basic_json // swap only works for strings if (is_string()) { + assert(m_value.string != nullptr); std::swap(*(m_value.string), other); } else @@ -5364,10 +5462,14 @@ class basic_json { case value_t::array: { + assert(lhs.m_value.array != nullptr); + assert(rhs.m_value.array != nullptr); return *lhs.m_value.array == *rhs.m_value.array; } case value_t::object: { + assert(lhs.m_value.object != nullptr); + assert(rhs.m_value.object != nullptr); return *lhs.m_value.object == *rhs.m_value.object; } case value_t::null: @@ -5376,6 +5478,8 @@ class basic_json } case value_t::string: { + assert(lhs.m_value.string != nullptr); + assert(rhs.m_value.string != nullptr); return *lhs.m_value.string == *rhs.m_value.string; } case value_t::boolean: @@ -5548,10 +5652,14 @@ class basic_json { case value_t::array: { + assert(lhs.m_value.array != nullptr); + assert(rhs.m_value.array != nullptr); return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { + assert(lhs.m_value.object != nullptr); + assert(rhs.m_value.object != nullptr); return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: @@ -5560,6 +5668,8 @@ class basic_json } case value_t::string: { + assert(lhs.m_value.string != nullptr); + assert(rhs.m_value.string != nullptr); return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: @@ -5734,14 +5844,14 @@ class basic_json // string->float->string, string->double->string or string->long // double->string; to be safe, we read this value from // std::numeric_limits::digits10 - const auto old_precision = o.precision(std::numeric_limits::digits10); + const auto old_preicison = o.precision(std::numeric_limits::digits10); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); // reset locale and precision o.imbue(old_locale); - o.precision(old_precision); + o.precision(old_preicison); return o; } @@ -6091,6 +6201,8 @@ class basic_json { case value_t::object: { + assert(m_value.object != nullptr); + if (m_value.object->empty()) { o << "{}"; @@ -6131,6 +6243,8 @@ class basic_json case value_t::array: { + assert(m_value.array != nullptr); + if (m_value.array->empty()) { o << "[]"; @@ -6169,6 +6283,7 @@ class basic_json case value_t::string: { + assert(m_value.string != nullptr); o << string_t("\"") << escape_string(*m_value.string) << "\""; return; } @@ -8704,6 +8819,7 @@ class basic_json basic_json result; // iterate the JSON object values + assert(value.m_value.object != nullptr); for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) From 161c74a92ed97f163a3842ba6ed08a1b6d2d3995 Mon Sep 17 00:00:00 2001 From: Niels Date: Thu, 28 Jul 2016 21:19:56 +0200 Subject: [PATCH 42/48] some cleanup --- src/json.hpp | 19 +++++++++++++++++-- src/json.hpp.re2c | 28 +++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 15221b8be..f4c1b0f5e 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -760,6 +760,7 @@ class basic_json }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward(args)...); + assert(object.get() != nullptr); return object.release(); } @@ -4597,6 +4598,10 @@ class basic_json object | result of function `object_t::empty()` array | result of function `array_t::empty()` + @note This function does not return whether a string stored as JSON value + is empty - it returns whether the JSON container itself is empty which is + false in the case of a string. + @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their `empty()` functions have constant complexity. @@ -4626,12 +4631,14 @@ class basic_json case value_t::array: { + // delegate call to array_t::empty() assert(m_value.array != nullptr); return m_value.array->empty(); } case value_t::object: { + // delegate call to object_t::empty() assert(m_value.object != nullptr); return m_value.object->empty(); } @@ -4660,6 +4667,10 @@ class basic_json object | result of function object_t::size() array | result of function array_t::size() + @note This function does not return the length of a string stored as JSON + value - it returns the number of elements in the JSON value which is 1 in + the case of a string. + @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their size() functions have constant complexity. @@ -4690,12 +4701,14 @@ class basic_json case value_t::array: { + // delegate call to array_t::size() assert(m_value.array != nullptr); return m_value.array->size(); } case value_t::object: { + // delegate call to object_t::size() assert(m_value.object != nullptr); return m_value.object->size(); } @@ -4750,12 +4763,14 @@ class basic_json { case value_t::array: { + // delegate call to array_t::max_size() assert(m_value.array != nullptr); return m_value.array->max_size(); } case value_t::object: { + // delegate call to object_t::max_size() assert(m_value.object != nullptr); return m_value.object->max_size(); } @@ -5844,14 +5859,14 @@ class basic_json // string->float->string, string->double->string or string->long // double->string; to be safe, we read this value from // std::numeric_limits::digits10 - const auto old_preicison = o.precision(std::numeric_limits::digits10); + const auto old_precision = o.precision(std::numeric_limits::digits10); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); // reset locale and precision o.imbue(old_locale); - o.precision(old_preicison); + o.precision(old_precision); return o; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 74db214eb..d7b197937 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -760,6 +760,7 @@ class basic_json }; std::unique_ptr object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward(args)...); + assert(object.get() != nullptr); return object.release(); } @@ -4597,6 +4598,10 @@ class basic_json object | result of function `object_t::empty()` array | result of function `array_t::empty()` + @note This function does not return whether a string stored as JSON value + is empty - it returns whether the JSON container itself is empty which is + false in the case of a string. + @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their `empty()` functions have constant complexity. @@ -4626,12 +4631,14 @@ class basic_json case value_t::array: { + // delegate call to array_t::empty() assert(m_value.array != nullptr); return m_value.array->empty(); } case value_t::object: { + // delegate call to object_t::empty() assert(m_value.object != nullptr); return m_value.object->empty(); } @@ -4660,6 +4667,10 @@ class basic_json object | result of function object_t::size() array | result of function array_t::size() + @note This function does not return the length of a string stored as JSON + value - it returns the number of elements in the JSON value which is 1 in + the case of a string. + @complexity Constant, as long as @ref array_t and @ref object_t satisfy the Container concept; that is, their size() functions have constant complexity. @@ -4690,12 +4701,14 @@ class basic_json case value_t::array: { + // delegate call to array_t::size() assert(m_value.array != nullptr); return m_value.array->size(); } case value_t::object: { + // delegate call to object_t::size() assert(m_value.object != nullptr); return m_value.object->size(); } @@ -4750,12 +4763,14 @@ class basic_json { case value_t::array: { + // delegate call to array_t::max_size() assert(m_value.array != nullptr); return m_value.array->max_size(); } case value_t::object: { + // delegate call to object_t::max_size() assert(m_value.object != nullptr); return m_value.object->max_size(); } @@ -5844,14 +5859,14 @@ class basic_json // string->float->string, string->double->string or string->long // double->string; to be safe, we read this value from // std::numeric_limits::digits10 - const auto old_preicison = o.precision(std::numeric_limits::digits10); + const auto old_precision = o.precision(std::numeric_limits::digits10); // do the actual serialization j.dump(o, pretty_print, static_cast(indentation)); // reset locale and precision o.imbue(old_locale); - o.precision(old_preicison); + o.precision(old_precision); return o; } @@ -9560,7 +9575,7 @@ struct hash @brief user-defined string literal for JSON values This operator implements a user-defined string literal for JSON objects. It -can be used by adding \p "_json" to a string literal and returns a JSON object +can be used by adding `"_json"` to a string literal and returns a JSON object if no parse error occurred. @param[in] s a string representation of a JSON object @@ -9576,6 +9591,13 @@ inline nlohmann::json operator "" _json(const char* s, std::size_t) /*! @brief user-defined string literal for JSON pointer +This operator implements a user-defined string literal for JSON Pointers. It +can be used by adding `"_json"` to a string literal and returns a JSON pointer +object if no parse error occurred. + +@param[in] s a string representation of a JSON Pointer +@return a JSON pointer object + @since version 2.0.0 */ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t) From b2b68a0fa1f3e41933548b4e5684def7d96f3306 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 29 Jul 2016 22:24:47 +0200 Subject: [PATCH 43/48] header + cleanup --- src/json.hpp | 74 +++++++++++++++++++++++++---------------------- src/json.hpp.re2c | 65 ++++++++++++++++++++--------------------- 2 files changed, 72 insertions(+), 67 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index f4c1b0f5e..646e260db 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -32,7 +32,6 @@ SOFTWARE. #include #include #include -#include #include #include #include @@ -44,6 +43,7 @@ SOFTWARE. #include #include #include +#include #include #include #include @@ -384,7 +384,7 @@ class basic_json @tparam ArrayType container type to store arrays (e.g., `std::vector` or `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) + @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) #### Default type @@ -621,15 +621,14 @@ class basic_json > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], this - class's integer type is interoperable. + number_integer_t type) of the exactly supported range [0, UINT64_MAX], + this class's integer type is interoperable. #### Storage Integer number values are stored directly inside a @ref basic_json type. @sa @ref number_float_t -- type for number values (floating-point) - @sa @ref number_integer_t -- type for number values (integer) @since version 2.0.0 @@ -1416,8 +1415,8 @@ class basic_json Create an unsigned integer number JSON value with a given content. - @tparam T helper type to compare number_unsigned_t and unsigned int - (not visible in) the interface. + @tparam T helper type to compare number_unsigned_t and unsigned int (not + visible in) the interface. @param[in] val an integer to create a JSON number from @@ -1481,8 +1480,8 @@ class basic_json disallows NaN values: > Numeric values that cannot be represented in the grammar below (such as > Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is - created instead. + In case the parameter @a val is not a number, a JSON null value is created + instead. @complexity Constant. @@ -1555,21 +1554,21 @@ class basic_json 1. If the list is empty, an empty JSON object value `{}` is created. 2. If the list consists of pairs whose first element is a string, a JSON - object value is created where the first elements of the pairs are treated - as keys and the second elements are as values. + object value is created where the first elements of the pairs are + treated as keys and the second elements are as values. 3. In all other cases, an array is created. The rules aim to create the best fit between a C++ initializer list and JSON values. The rationale is as follows: 1. The empty initializer list is written as `{}` which is exactly an empty - JSON object. + JSON object. 2. C++ has now way of describing mapped types other than to list a list of - pairs. As JSON requires that keys must be of type string, rule 2 is the - weakest constraint one can pose on initializer lists to interpret them as - an object. + pairs. As JSON requires that keys must be of type string, rule 2 is the + weakest constraint one can pose on initializer lists to interpret them + as an object. 3. In all other cases, the initializer list could not be interpreted as - JSON object type, so interpreting it as JSON array type is safe. + JSON object type, so interpreting it as JSON array type is safe. With the rules described above, the following JSON values cannot be expressed by an initializer list: @@ -3709,7 +3708,7 @@ class basic_json /*! @brief overload for a default value of type const char* - @copydoc basic_json::value(const typename object_t::key_type&, ValueType) + @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const */ string_t value(const typename object_t::key_type& key, const char* default_value) const { @@ -3753,7 +3752,7 @@ class basic_json @liveexample{The example below shows how object elements can be queried with a default value.,basic_json__value_ptr} - @sa @ref operator[](const json_ptr&) for unchecked access by reference + @sa @ref operator[](const json_pointer&) for unchecked access by reference @since version 2.0.2 */ @@ -3784,7 +3783,7 @@ class basic_json /*! @brief overload for a default value of type const char* - @copydoc basic_json::value(const json_pointer&, ValueType) + @copydoc basic_json::value(const json_pointer&, ValueType) const */ string_t value(const json_pointer& ptr, const char* default_value) const { @@ -7386,7 +7385,7 @@ class basic_json : m_stream(s), m_buffer() { assert(m_stream != nullptr); - getline(*m_stream, m_buffer); + std::getline(*m_stream, m_buffer); m_content = reinterpret_cast(m_buffer.c_str()); assert(m_content != nullptr); m_start = m_cursor = m_content; @@ -8379,8 +8378,8 @@ basic_json_parser_63: according to the nature of the escape. Some escapes create new characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape - `"\\uxxxx"` need special care. In this case, @ref to_unicode takes - care of the construction of the values. + `"\\uxxxx"` need special care. In this case, to_unicode takes care + of the construction of the values. 2. Unescaped characters are copied as is. @pre `m_cursor - m_start >= 2`, meaning the length of the last token @@ -8398,9 +8397,9 @@ basic_json_parser_63: Proof (by contradiction): Assume the loop body does not terminate. As the loop body does not contain another loop, one of the called functions must never return. The called functions are `std::strtoul` - and @ref to_unicode. Neither function can loop forever, so the loop - body will never loop forever which contradicts the assumption that the - loop body does not terminate, q.e.d.\n + and to_unicode. Neither function can loop forever, so the loop body + will never loop forever which contradicts the assumption that the loop + body does not terminate, q.e.d.\n Lemma: The loop condition for the for loop is eventually false.\n @@ -8408,15 +8407,15 @@ basic_json_parser_63: the above lemma, this can only be due to a tautological loop condition; that is, the loop condition i < m_cursor - 1 must always be true. Let x be the change of i for any loop iteration. Then - m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. - This can be rephrased to m_cursor - m_start - 2 > x. With the + m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This + can be rephrased to m_cursor - m_start - 2 > x. With the precondition, we x <= 0, meaning that the loop condition holds - indefinitly if i is always decreased. However, observe that the - value of i is strictly increasing with each iteration, as it is - incremented by 1 in the iteration expression and never - decremented inside the loop body. Hence, the loop condition - will eventually be false which contradicts the assumption that - the loop condition is a tautology, q.e.d. + indefinitly if i is always decreased. However, observe that the value + of i is strictly increasing with each iteration, as it is incremented + by 1 in the iteration expression and never decremented inside the loop + body. Hence, the loop condition will eventually be false which + contradicts the assumption that the loop condition is a tautology, + q.e.d. @return string value of current token without opening and closing quotes @@ -10278,7 +10277,7 @@ struct hash @brief user-defined string literal for JSON values This operator implements a user-defined string literal for JSON objects. It -can be used by adding \p "_json" to a string literal and returns a JSON object +can be used by adding `"_json"` to a string literal and returns a JSON object if no parse error occurred. @param[in] s a string representation of a JSON object @@ -10294,6 +10293,13 @@ inline nlohmann::json operator "" _json(const char* s, std::size_t) /*! @brief user-defined string literal for JSON pointer +This operator implements a user-defined string literal for JSON Pointers. It +can be used by adding `"_json"` to a string literal and returns a JSON pointer +object if no parse error occurred. + +@param[in] s a string representation of a JSON Pointer +@return a JSON pointer object + @since version 2.0.0 */ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index d7b197937..18e7f48de 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -32,7 +32,6 @@ SOFTWARE. #include #include #include -#include #include #include #include @@ -44,6 +43,7 @@ SOFTWARE. #include #include #include +#include #include #include #include @@ -384,7 +384,7 @@ class basic_json @tparam ArrayType container type to store arrays (e.g., `std::vector` or `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) + @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) #### Default type @@ -621,15 +621,14 @@ class basic_json > that implementations will agree exactly on their numeric values. As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], this - class's integer type is interoperable. + number_integer_t type) of the exactly supported range [0, UINT64_MAX], + this class's integer type is interoperable. #### Storage Integer number values are stored directly inside a @ref basic_json type. @sa @ref number_float_t -- type for number values (floating-point) - @sa @ref number_integer_t -- type for number values (integer) @since version 2.0.0 @@ -1416,8 +1415,8 @@ class basic_json Create an unsigned integer number JSON value with a given content. - @tparam T helper type to compare number_unsigned_t and unsigned int - (not visible in) the interface. + @tparam T helper type to compare number_unsigned_t and unsigned int (not + visible in) the interface. @param[in] val an integer to create a JSON number from @@ -1481,8 +1480,8 @@ class basic_json disallows NaN values: > Numeric values that cannot be represented in the grammar below (such as > Infinity and NaN) are not permitted. - In case the parameter @a val is not a number, a JSON null value is - created instead. + In case the parameter @a val is not a number, a JSON null value is created + instead. @complexity Constant. @@ -1555,21 +1554,21 @@ class basic_json 1. If the list is empty, an empty JSON object value `{}` is created. 2. If the list consists of pairs whose first element is a string, a JSON - object value is created where the first elements of the pairs are treated - as keys and the second elements are as values. + object value is created where the first elements of the pairs are + treated as keys and the second elements are as values. 3. In all other cases, an array is created. The rules aim to create the best fit between a C++ initializer list and JSON values. The rationale is as follows: 1. The empty initializer list is written as `{}` which is exactly an empty - JSON object. + JSON object. 2. C++ has now way of describing mapped types other than to list a list of - pairs. As JSON requires that keys must be of type string, rule 2 is the - weakest constraint one can pose on initializer lists to interpret them as - an object. + pairs. As JSON requires that keys must be of type string, rule 2 is the + weakest constraint one can pose on initializer lists to interpret them + as an object. 3. In all other cases, the initializer list could not be interpreted as - JSON object type, so interpreting it as JSON array type is safe. + JSON object type, so interpreting it as JSON array type is safe. With the rules described above, the following JSON values cannot be expressed by an initializer list: @@ -3709,7 +3708,7 @@ class basic_json /*! @brief overload for a default value of type const char* - @copydoc basic_json::value(const typename object_t::key_type&, ValueType) + @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const */ string_t value(const typename object_t::key_type& key, const char* default_value) const { @@ -3753,7 +3752,7 @@ class basic_json @liveexample{The example below shows how object elements can be queried with a default value.,basic_json__value_ptr} - @sa @ref operator[](const json_ptr&) for unchecked access by reference + @sa @ref operator[](const json_pointer&) for unchecked access by reference @since version 2.0.2 */ @@ -3784,7 +3783,7 @@ class basic_json /*! @brief overload for a default value of type const char* - @copydoc basic_json::value(const json_pointer&, ValueType) + @copydoc basic_json::value(const json_pointer&, ValueType) const */ string_t value(const json_pointer& ptr, const char* default_value) const { @@ -7386,7 +7385,7 @@ class basic_json : m_stream(s), m_buffer() { assert(m_stream != nullptr); - getline(*m_stream, m_buffer); + std::getline(*m_stream, m_buffer); m_content = reinterpret_cast(m_buffer.c_str()); assert(m_content != nullptr); m_start = m_cursor = m_content; @@ -7676,8 +7675,8 @@ class basic_json according to the nature of the escape. Some escapes create new characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape - `"\\uxxxx"` need special care. In this case, @ref to_unicode takes - care of the construction of the values. + `"\\uxxxx"` need special care. In this case, to_unicode takes care + of the construction of the values. 2. Unescaped characters are copied as is. @pre `m_cursor - m_start >= 2`, meaning the length of the last token @@ -7695,9 +7694,9 @@ class basic_json Proof (by contradiction): Assume the loop body does not terminate. As the loop body does not contain another loop, one of the called functions must never return. The called functions are `std::strtoul` - and @ref to_unicode. Neither function can loop forever, so the loop - body will never loop forever which contradicts the assumption that the - loop body does not terminate, q.e.d.\n + and to_unicode. Neither function can loop forever, so the loop body + will never loop forever which contradicts the assumption that the loop + body does not terminate, q.e.d.\n Lemma: The loop condition for the for loop is eventually false.\n @@ -7705,15 +7704,15 @@ class basic_json the above lemma, this can only be due to a tautological loop condition; that is, the loop condition i < m_cursor - 1 must always be true. Let x be the change of i for any loop iteration. Then - m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. - This can be rephrased to m_cursor - m_start - 2 > x. With the + m_start + 1 + x < m_cursor - 1 must hold to loop indefinitely. This + can be rephrased to m_cursor - m_start - 2 > x. With the precondition, we x <= 0, meaning that the loop condition holds - indefinitly if i is always decreased. However, observe that the - value of i is strictly increasing with each iteration, as it is - incremented by 1 in the iteration expression and never - decremented inside the loop body. Hence, the loop condition - will eventually be false which contradicts the assumption that - the loop condition is a tautology, q.e.d. + indefinitly if i is always decreased. However, observe that the value + of i is strictly increasing with each iteration, as it is incremented + by 1 in the iteration expression and never decremented inside the loop + body. Hence, the loop condition will eventually be false which + contradicts the assumption that the loop condition is a tautology, + q.e.d. @return string value of current token without opening and closing quotes From b145e0c404e72e17f711735a7cf1ddcd29176ac9 Mon Sep 17 00:00:00 2001 From: Niels Date: Fri, 29 Jul 2016 23:47:16 +0200 Subject: [PATCH 44/48] more cleanup --- README.md | 2 +- src/json.hpp | 66 +++++++++++++++++++++++++++-------------------- src/json.hpp.re2c | 66 +++++++++++++++++++++++++++-------------------- 3 files changed, 77 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 5adcf15ca..584906799 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Other aspects were not so important to us: - **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs. -- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) with a decent regular expression processor should be even faster (but would consist of more files which makes the integration harder). +- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) may be even faster (but would consist of more files which makes the integration harder). See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information. diff --git a/src/json.hpp b/src/json.hpp index 646e260db..565c0415f 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -927,12 +927,13 @@ class basic_json @brief per-element parser callback type With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse(std::istream&, parser_callback_t) or - @ref parse(const string_t&, parser_callback_t), it is called on certain - events (passed as @ref parse_event_t via parameter @a event) with a set - recursion depth @a depth and context JSON value @a parsed. The return - value of the callback function is a boolean indicating whether the element - that emitted the callback shall be kept or not. + influenced. When passed to @ref parse(std::istream&, const + parser_callback_t) or @ref parse(const string_t&, const parser_callback_t), + it is called on certain events (passed as @ref parse_event_t via parameter + @a event) with a set recursion depth @a depth and context JSON value + @a parsed. The return value of the callback function is a boolean + indicating whether the element that emitted the callback shall be kept or + not. We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values @@ -1913,7 +1914,7 @@ class basic_json @since version 2.0.0 */ - explicit basic_json(std::istream& i, parser_callback_t cb = nullptr) + explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) { *this = parser(i, cb).parse(); } @@ -5907,12 +5908,13 @@ class basic_json @liveexample{The example below demonstrates the `parse()` function with and without callback function.,parse__string__parser_callback_t} - @sa @ref parse(std::istream&, parser_callback_t) for a version that reads - from an input stream + @sa @ref parse(std::istream&, const parser_callback_t) for a version that + reads from an input stream @since version 1.0.0 */ - static basic_json parse(const string_t& s, parser_callback_t cb = nullptr) + static basic_json parse(const string_t& s, + const parser_callback_t cb = nullptr) { return parser(s, cb).parse(); } @@ -5936,20 +5938,22 @@ class basic_json @liveexample{The example below demonstrates the `parse()` function with and without callback function.,parse__istream__parser_callback_t} - @sa @ref parse(const string_t&, parser_callback_t) for a version that - reads from a string + @sa @ref parse(const string_t&, const parser_callback_t) for a version + that reads from a string @since version 1.0.0 */ - static basic_json parse(std::istream& i, parser_callback_t cb = nullptr) + static basic_json parse(std::istream& i, + const parser_callback_t cb = nullptr) { return parser(i, cb).parse(); } /*! - @copydoc parse(std::istream&, parser_callback_t) + @copydoc parse(std::istream&, const parser_callback_t) */ - static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr) + static basic_json parse(std::istream&& i, + const parser_callback_t cb = nullptr) { return parser(i, cb).parse(); } @@ -5972,8 +5976,8 @@ class basic_json @liveexample{The example below shows how a JSON value is constructed by reading a serialization from a stream.,operator_deserialize} - @sa parse(std::istream&, parser_callback_t) for a variant with a parser - callback function to filter values while parsing + @sa parse(std::istream&, const parser_callback_t) for a variant with a + parser callback function to filter values while parsing @since version 1.0.0 */ @@ -6001,7 +6005,18 @@ class basic_json // convenience functions // /////////////////////////// - /// return the type as string + /*! + @brief return the type as string + + Returns the type name as string to be used in error messages - usually to + indicate that a function was called on a wrong JSON type. + + @return basically a string representation of a the @ref m_type member + + @complexity Constant. + + @since version 1.0.0 + */ std::string type_name() const { switch (m_type) @@ -7487,7 +7502,7 @@ class basic_json } /// return name of values of type token_type (only used for errors) - static std::string token_type_name(token_type t) + static std::string token_type_name(const token_type t) { switch (t) { @@ -8540,11 +8555,6 @@ basic_json_parser_63: the number @return the floating point number - - @bug This function uses `std::strtof`, `std::strtod`, or `std::strtold` - which use the current C locale to determine which character is used as - decimal point character. This may yield to parse errors if the locale - does not used `.`. */ long double str_to_float_t(long double* /* type */, char** endptr) const { @@ -8725,7 +8735,7 @@ basic_json_parser_63: { public: /// constructor for strings - parser(const string_t& s, parser_callback_t cb = nullptr) noexcept + parser(const string_t& s, const parser_callback_t cb = nullptr) noexcept : callback(cb), m_lexer(s) { // read first token @@ -8733,7 +8743,7 @@ basic_json_parser_63: } /// a parser reading from an input stream - parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept + parser(std::istream& _is, const parser_callback_t cb = nullptr) noexcept : callback(cb), m_lexer(&_is) { // read first token @@ -8981,7 +8991,7 @@ basic_json_parser_63: /// current level of recursion int depth = 0; /// callback function - parser_callback_t callback; + const parser_callback_t callback; /// the type of the last read token typename lexer::token_type last_token = lexer::token_type::uninitialized; /// the lexer @@ -9420,7 +9430,7 @@ basic_json_parser_63: @param[in,out] s the string to manipulate @param[in] f the substring to replace with @a t - @param[out] t the string to replace @a f + @param[in] t the string to replace @a f @return The string @a s where all occurrences of @a f are replaced with @a t. diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 18e7f48de..26fafa543 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -927,12 +927,13 @@ class basic_json @brief per-element parser callback type With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse(std::istream&, parser_callback_t) or - @ref parse(const string_t&, parser_callback_t), it is called on certain - events (passed as @ref parse_event_t via parameter @a event) with a set - recursion depth @a depth and context JSON value @a parsed. The return - value of the callback function is a boolean indicating whether the element - that emitted the callback shall be kept or not. + influenced. When passed to @ref parse(std::istream&, const + parser_callback_t) or @ref parse(const string_t&, const parser_callback_t), + it is called on certain events (passed as @ref parse_event_t via parameter + @a event) with a set recursion depth @a depth and context JSON value + @a parsed. The return value of the callback function is a boolean + indicating whether the element that emitted the callback shall be kept or + not. We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values @@ -1913,7 +1914,7 @@ class basic_json @since version 2.0.0 */ - explicit basic_json(std::istream& i, parser_callback_t cb = nullptr) + explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) { *this = parser(i, cb).parse(); } @@ -5907,12 +5908,13 @@ class basic_json @liveexample{The example below demonstrates the `parse()` function with and without callback function.,parse__string__parser_callback_t} - @sa @ref parse(std::istream&, parser_callback_t) for a version that reads - from an input stream + @sa @ref parse(std::istream&, const parser_callback_t) for a version that + reads from an input stream @since version 1.0.0 */ - static basic_json parse(const string_t& s, parser_callback_t cb = nullptr) + static basic_json parse(const string_t& s, + const parser_callback_t cb = nullptr) { return parser(s, cb).parse(); } @@ -5936,20 +5938,22 @@ class basic_json @liveexample{The example below demonstrates the `parse()` function with and without callback function.,parse__istream__parser_callback_t} - @sa @ref parse(const string_t&, parser_callback_t) for a version that - reads from a string + @sa @ref parse(const string_t&, const parser_callback_t) for a version + that reads from a string @since version 1.0.0 */ - static basic_json parse(std::istream& i, parser_callback_t cb = nullptr) + static basic_json parse(std::istream& i, + const parser_callback_t cb = nullptr) { return parser(i, cb).parse(); } /*! - @copydoc parse(std::istream&, parser_callback_t) + @copydoc parse(std::istream&, const parser_callback_t) */ - static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr) + static basic_json parse(std::istream&& i, + const parser_callback_t cb = nullptr) { return parser(i, cb).parse(); } @@ -5972,8 +5976,8 @@ class basic_json @liveexample{The example below shows how a JSON value is constructed by reading a serialization from a stream.,operator_deserialize} - @sa parse(std::istream&, parser_callback_t) for a variant with a parser - callback function to filter values while parsing + @sa parse(std::istream&, const parser_callback_t) for a variant with a + parser callback function to filter values while parsing @since version 1.0.0 */ @@ -6001,7 +6005,18 @@ class basic_json // convenience functions // /////////////////////////// - /// return the type as string + /*! + @brief return the type as string + + Returns the type name as string to be used in error messages - usually to + indicate that a function was called on a wrong JSON type. + + @return basically a string representation of a the @ref m_type member + + @complexity Constant. + + @since version 1.0.0 + */ std::string type_name() const { switch (m_type) @@ -7487,7 +7502,7 @@ class basic_json } /// return name of values of type token_type (only used for errors) - static std::string token_type_name(token_type t) + static std::string token_type_name(const token_type t) { switch (t) { @@ -7837,11 +7852,6 @@ class basic_json the number @return the floating point number - - @bug This function uses `std::strtof`, `std::strtod`, or `std::strtold` - which use the current C locale to determine which character is used as - decimal point character. This may yield to parse errors if the locale - does not used `.`. */ long double str_to_float_t(long double* /* type */, char** endptr) const { @@ -8022,7 +8032,7 @@ class basic_json { public: /// constructor for strings - parser(const string_t& s, parser_callback_t cb = nullptr) noexcept + parser(const string_t& s, const parser_callback_t cb = nullptr) noexcept : callback(cb), m_lexer(s) { // read first token @@ -8030,7 +8040,7 @@ class basic_json } /// a parser reading from an input stream - parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept + parser(std::istream& _is, const parser_callback_t cb = nullptr) noexcept : callback(cb), m_lexer(&_is) { // read first token @@ -8278,7 +8288,7 @@ class basic_json /// current level of recursion int depth = 0; /// callback function - parser_callback_t callback; + const parser_callback_t callback; /// the type of the last read token typename lexer::token_type last_token = lexer::token_type::uninitialized; /// the lexer @@ -8717,7 +8727,7 @@ class basic_json @param[in,out] s the string to manipulate @param[in] f the substring to replace with @a t - @param[out] t the string to replace @a f + @param[in] t the string to replace @a f @return The string @a s where all occurrences of @a f are replaced with @a t. From 5405ae860117f55f9b5af287a7006dd64cef9eaa Mon Sep 17 00:00:00 2001 From: Niels Date: Sat, 30 Jul 2016 10:50:53 +0200 Subject: [PATCH 45/48] added default value --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 565c0415f..9d2305d85 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8991,7 +8991,7 @@ basic_json_parser_63: /// current level of recursion int depth = 0; /// callback function - const parser_callback_t callback; + const parser_callback_t callback = nullptr; /// the type of the last read token typename lexer::token_type last_token = lexer::token_type::uninitialized; /// the lexer diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 26fafa543..537d4f4da 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8288,7 +8288,7 @@ class basic_json /// current level of recursion int depth = 0; /// callback function - const parser_callback_t callback; + const parser_callback_t callback = nullptr; /// the type of the last read token typename lexer::token_type last_token = lexer::token_type::uninitialized; /// the lexer From 891918a30f16a515ed0c499dcab5526c266ccb70 Mon Sep 17 00:00:00 2001 From: Niels Date: Sat, 30 Jul 2016 16:12:10 +0200 Subject: [PATCH 46/48] cleanup and documentation --- src/json.hpp | 190 ++++++++++++++++++++++++++++++++++------------ src/json.hpp.re2c | 190 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 282 insertions(+), 98 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 9d2305d85..46edec62d 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1785,6 +1785,8 @@ class basic_json @param[in] first begin of the range to copy from (included) @param[in] last end of the range to copy from (excluded) + @pre Iterators @a first and @a last must be initialized. + @throw std::domain_error if iterators are not compatible; that is, do not belong to the same JSON value; example: `"iterators are not compatible"` @throw std::out_of_range if iterators are for a primitive type (number, @@ -1807,14 +1809,20 @@ class basic_json std::is_same::value , int>::type = 0> - basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type) + basic_json(InputIT first, InputIT last) { + assert(first.m_object != nullptr); + assert(last.m_object != nullptr); + // make sure iterator fits the current value if (first.m_object != last.m_object) { throw std::domain_error("iterators are not compatible"); } + // copy type from first iterator + m_type = first.m_object->m_type; + // check if iterator range is complete for primitive values switch (m_type) { @@ -1841,35 +1849,30 @@ class basic_json { case value_t::number_integer: { - assert(first.m_object != nullptr); m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { - assert(first.m_object != nullptr); m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { - assert(first.m_object != nullptr); m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { - assert(first.m_object != nullptr); m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { - assert(first.m_object != nullptr); m_value = *first.m_object->m_value.string; break; } @@ -1888,7 +1891,6 @@ class basic_json default: { - assert(first.m_object != nullptr); throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); } } @@ -6561,6 +6563,12 @@ class basic_json This class implements a const iterator for the @ref basic_json class. From this class, the @ref iterator class is derived. + @note An iterator is called *initialized* when a pointer to a JSON value + has been set (e.g., by a constructor or a copy assignment). If the + iterator is default-constructed, it is *uninitialized* and most + methods are undefined. The library uses assertions to detect calls + on uninitialized iterators. + @requirement The class satisfies the following concept requirements: - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): The iterator that can be moved to point (forward and backward) to any @@ -6588,7 +6596,12 @@ class basic_json /// default constructor const_iterator() = default; - /// constructor for a given JSON instance + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ explicit const_iterator(pointer object) noexcept : m_object(object) { @@ -6616,40 +6629,53 @@ class basic_json } } - /// copy constructor given a nonconst iterator + /*! + @brief copy constructor given a non-const iterator + @param[in] other iterator to copy from + @note It is not checked whether @a other is initialized. + */ explicit const_iterator(const iterator& other) noexcept : m_object(other.m_object) { - assert(m_object != nullptr); - - switch (m_object->m_type) + if (m_object != nullptr) { - case basic_json::value_t::object: + switch (m_object->m_type) { - m_it.object_iterator = other.m_it.object_iterator; - break; - } + case basic_json::value_t::object: + { + m_it.object_iterator = other.m_it.object_iterator; + break; + } - case basic_json::value_t::array: - { - m_it.array_iterator = other.m_it.array_iterator; - break; - } + case basic_json::value_t::array: + { + m_it.array_iterator = other.m_it.array_iterator; + break; + } - default: - { - m_it.primitive_iterator = other.m_it.primitive_iterator; - break; + default: + { + m_it.primitive_iterator = other.m_it.primitive_iterator; + break; + } } } } - /// copy constructor + /*! + @brief copy constructor + @param[in] other iterator to copy from + @note It is not checked whether @a other is initialized. + */ const_iterator(const const_iterator& other) noexcept : m_object(other.m_object), m_it(other.m_it) {} - /// copy assignment + /*! + @brief copy assignment + @param[in,out] other iterator to copy from + @note It is not checked whether @a other is initialized. + */ const_iterator& operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value and @@ -6663,7 +6689,10 @@ class basic_json } private: - /// set the iterator to the first value + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ void set_begin() noexcept { assert(m_object != nullptr); @@ -6699,7 +6728,10 @@ class basic_json } } - /// set the iterator past the last value + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ void set_end() noexcept { assert(m_object != nullptr); @@ -6729,7 +6761,10 @@ class basic_json } public: - /// return a reference to the value pointed to by the iterator + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ reference operator*() const { assert(m_object != nullptr); @@ -6769,7 +6804,10 @@ class basic_json } } - /// dereference the iterator + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ pointer operator->() const { assert(m_object != nullptr); @@ -6804,7 +6842,10 @@ class basic_json } } - /// post-increment (it++) + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator operator++(int) { auto result = *this; @@ -6812,7 +6853,10 @@ class basic_json return result; } - /// pre-increment (++it) + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator& operator++() { assert(m_object != nullptr); @@ -6841,7 +6885,10 @@ class basic_json return *this; } - /// post-decrement (it--) + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator operator--(int) { auto result = *this; @@ -6849,7 +6896,10 @@ class basic_json return result; } - /// pre-decrement (--it) + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator& operator--() { assert(m_object != nullptr); @@ -6878,7 +6928,10 @@ class basic_json return *this; } - /// comparison: equal + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator==(const const_iterator& other) const { // if objects are not the same, the comparison is undefined @@ -6908,13 +6961,19 @@ class basic_json } } - /// comparison: not equal + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator!=(const const_iterator& other) const { return not operator==(other); } - /// comparison: smaller + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator<(const const_iterator& other) const { // if objects are not the same, the comparison is undefined @@ -6944,25 +7003,37 @@ class basic_json } } - /// comparison: less than or equal + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator<=(const const_iterator& other) const { return not other.operator < (*this); } - /// comparison: greater than + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator>(const const_iterator& other) const { return not operator<=(other); } - /// comparison: greater than or equal + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator>=(const const_iterator& other) const { return not operator<(other); } - /// add to iterator + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator& operator+=(difference_type i) { assert(m_object != nullptr); @@ -6990,13 +7061,19 @@ class basic_json return *this; } - /// subtract from iterator + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator& operator-=(difference_type i) { return operator+=(-i); } - /// add to iterator + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator operator+(difference_type i) { auto result = *this; @@ -7004,7 +7081,10 @@ class basic_json return result; } - /// subtract from iterator + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator operator-(difference_type i) { auto result = *this; @@ -7012,7 +7092,10 @@ class basic_json return result; } - /// return difference + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ difference_type operator-(const const_iterator& other) const { assert(m_object != nullptr); @@ -7036,7 +7119,10 @@ class basic_json } } - /// access to successor + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ reference operator[](difference_type n) const { assert(m_object != nullptr); @@ -7072,7 +7158,10 @@ class basic_json } } - /// return the key of an object iterator + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ typename object_t::key_type key() const { assert(m_object != nullptr); @@ -7087,7 +7176,10 @@ class basic_json } } - /// return the value of an iterator + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ reference value() const { return operator*(); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 537d4f4da..7bc0f360e 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1785,6 +1785,8 @@ class basic_json @param[in] first begin of the range to copy from (included) @param[in] last end of the range to copy from (excluded) + @pre Iterators @a first and @a last must be initialized. + @throw std::domain_error if iterators are not compatible; that is, do not belong to the same JSON value; example: `"iterators are not compatible"` @throw std::out_of_range if iterators are for a primitive type (number, @@ -1807,14 +1809,20 @@ class basic_json std::is_same::value , int>::type = 0> - basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type) + basic_json(InputIT first, InputIT last) { + assert(first.m_object != nullptr); + assert(last.m_object != nullptr); + // make sure iterator fits the current value if (first.m_object != last.m_object) { throw std::domain_error("iterators are not compatible"); } + // copy type from first iterator + m_type = first.m_object->m_type; + // check if iterator range is complete for primitive values switch (m_type) { @@ -1841,35 +1849,30 @@ class basic_json { case value_t::number_integer: { - assert(first.m_object != nullptr); m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { - assert(first.m_object != nullptr); m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { - assert(first.m_object != nullptr); m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { - assert(first.m_object != nullptr); m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { - assert(first.m_object != nullptr); m_value = *first.m_object->m_value.string; break; } @@ -1888,7 +1891,6 @@ class basic_json default: { - assert(first.m_object != nullptr); throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); } } @@ -6561,6 +6563,12 @@ class basic_json This class implements a const iterator for the @ref basic_json class. From this class, the @ref iterator class is derived. + @note An iterator is called *initialized* when a pointer to a JSON value + has been set (e.g., by a constructor or a copy assignment). If the + iterator is default-constructed, it is *uninitialized* and most + methods are undefined. The library uses assertions to detect calls + on uninitialized iterators. + @requirement The class satisfies the following concept requirements: - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): The iterator that can be moved to point (forward and backward) to any @@ -6588,7 +6596,12 @@ class basic_json /// default constructor const_iterator() = default; - /// constructor for a given JSON instance + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ explicit const_iterator(pointer object) noexcept : m_object(object) { @@ -6616,40 +6629,53 @@ class basic_json } } - /// copy constructor given a nonconst iterator + /*! + @brief copy constructor given a non-const iterator + @param[in] other iterator to copy from + @note It is not checked whether @a other is initialized. + */ explicit const_iterator(const iterator& other) noexcept : m_object(other.m_object) { - assert(m_object != nullptr); - - switch (m_object->m_type) + if (m_object != nullptr) { - case basic_json::value_t::object: + switch (m_object->m_type) { - m_it.object_iterator = other.m_it.object_iterator; - break; - } + case basic_json::value_t::object: + { + m_it.object_iterator = other.m_it.object_iterator; + break; + } - case basic_json::value_t::array: - { - m_it.array_iterator = other.m_it.array_iterator; - break; - } + case basic_json::value_t::array: + { + m_it.array_iterator = other.m_it.array_iterator; + break; + } - default: - { - m_it.primitive_iterator = other.m_it.primitive_iterator; - break; + default: + { + m_it.primitive_iterator = other.m_it.primitive_iterator; + break; + } } } } - /// copy constructor + /*! + @brief copy constructor + @param[in] other iterator to copy from + @note It is not checked whether @a other is initialized. + */ const_iterator(const const_iterator& other) noexcept : m_object(other.m_object), m_it(other.m_it) {} - /// copy assignment + /*! + @brief copy assignment + @param[in,out] other iterator to copy from + @note It is not checked whether @a other is initialized. + */ const_iterator& operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible::value and std::is_nothrow_move_assignable::value and @@ -6663,7 +6689,10 @@ class basic_json } private: - /// set the iterator to the first value + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ void set_begin() noexcept { assert(m_object != nullptr); @@ -6699,7 +6728,10 @@ class basic_json } } - /// set the iterator past the last value + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ void set_end() noexcept { assert(m_object != nullptr); @@ -6729,7 +6761,10 @@ class basic_json } public: - /// return a reference to the value pointed to by the iterator + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ reference operator*() const { assert(m_object != nullptr); @@ -6769,7 +6804,10 @@ class basic_json } } - /// dereference the iterator + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ pointer operator->() const { assert(m_object != nullptr); @@ -6804,7 +6842,10 @@ class basic_json } } - /// post-increment (it++) + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator operator++(int) { auto result = *this; @@ -6812,7 +6853,10 @@ class basic_json return result; } - /// pre-increment (++it) + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator& operator++() { assert(m_object != nullptr); @@ -6841,7 +6885,10 @@ class basic_json return *this; } - /// post-decrement (it--) + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator operator--(int) { auto result = *this; @@ -6849,7 +6896,10 @@ class basic_json return result; } - /// pre-decrement (--it) + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator& operator--() { assert(m_object != nullptr); @@ -6878,7 +6928,10 @@ class basic_json return *this; } - /// comparison: equal + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator==(const const_iterator& other) const { // if objects are not the same, the comparison is undefined @@ -6908,13 +6961,19 @@ class basic_json } } - /// comparison: not equal + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator!=(const const_iterator& other) const { return not operator==(other); } - /// comparison: smaller + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator<(const const_iterator& other) const { // if objects are not the same, the comparison is undefined @@ -6944,25 +7003,37 @@ class basic_json } } - /// comparison: less than or equal + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator<=(const const_iterator& other) const { return not other.operator < (*this); } - /// comparison: greater than + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator>(const const_iterator& other) const { return not operator<=(other); } - /// comparison: greater than or equal + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ bool operator>=(const const_iterator& other) const { return not operator<(other); } - /// add to iterator + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator& operator+=(difference_type i) { assert(m_object != nullptr); @@ -6990,13 +7061,19 @@ class basic_json return *this; } - /// subtract from iterator + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator& operator-=(difference_type i) { return operator+=(-i); } - /// add to iterator + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator operator+(difference_type i) { auto result = *this; @@ -7004,7 +7081,10 @@ class basic_json return result; } - /// subtract from iterator + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ const_iterator operator-(difference_type i) { auto result = *this; @@ -7012,7 +7092,10 @@ class basic_json return result; } - /// return difference + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ difference_type operator-(const const_iterator& other) const { assert(m_object != nullptr); @@ -7036,7 +7119,10 @@ class basic_json } } - /// access to successor + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ reference operator[](difference_type n) const { assert(m_object != nullptr); @@ -7072,7 +7158,10 @@ class basic_json } } - /// return the key of an object iterator + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ typename object_t::key_type key() const { assert(m_object != nullptr); @@ -7087,7 +7176,10 @@ class basic_json } } - /// return the value of an iterator + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ reference value() const { return operator*(); From 9e51c9041eb4f1adde343e2998a3d77c807d67ed Mon Sep 17 00:00:00 2001 From: Niels Date: Sat, 30 Jul 2016 18:02:41 +0200 Subject: [PATCH 47/48] replaced individual assertions by a class invariant function --- src/json.hpp | 206 +++++++++++++++++++++++++--------------------- src/json.hpp.re2c | 206 +++++++++++++++++++++++++--------------------- 2 files changed, 224 insertions(+), 188 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 46edec62d..7120ad80e 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -190,6 +190,13 @@ default) JSON values can be used like STL containers and provide reverse iterator access. +@invariant The member variables @a m_value and @a m_type have the following +relationship: +- If `m_type == value_t::object`, then `m_value.object != nullptr`. +- If `m_type == value_t::array`, then `m_value.array != nullptr`. +- If `m_type == value_t::string`, then `m_value.string != nullptr`. +The invariants are checked by member function assert_invariant(). + @internal @note ObjectType trick from http://stackoverflow.com/a/9860911 @endinternal @@ -891,6 +898,21 @@ class basic_json } }; + /*! + @brief checks the class invariants + + This function asserts the class invariants. It needs to be called at the + end of every constructor to make sure that created objects respect the + invariant. Furthermore, it has to be called each time the type of a JSON + value is changed, because the invariant expresses a relationship between + @a m_type and @a m_value. + */ + void assert_invariant() const + { + assert(m_type != value_t::object or m_value.object != nullptr); + assert(m_type != value_t::array or m_value.array != nullptr); + assert(m_type != value_t::string or m_value.string != nullptr); + } public: ////////////////////////// @@ -1030,7 +1052,9 @@ class basic_json */ basic_json(const value_t value_type) : m_type(value_type), m_value(value_type) - {} + { + assert_invariant(); + } /*! @brief create a null object (implicitly) @@ -1038,6 +1062,9 @@ class basic_json Create a `null` JSON value. This is the implicit version of the `null` value constructor as it takes no parameters. + @note The class invariant is satisfied, because it poses no requirements + for null values. + @complexity Constant. @exceptionsafety No-throw guarantee: this constructor never throws @@ -1082,7 +1109,9 @@ class basic_json */ basic_json(std::nullptr_t) noexcept : basic_json(value_t::null) - {} + { + assert_invariant(); + } /*! @brief create an object (explicit) @@ -1105,7 +1134,9 @@ class basic_json */ basic_json(const object_t& val) : m_type(value_t::object), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an object (implicit) @@ -1144,6 +1175,7 @@ class basic_json using std::begin; using std::end; m_value.object = create(begin(val), end(val)); + assert_invariant(); } /*! @@ -1167,7 +1199,9 @@ class basic_json */ basic_json(const array_t& val) : m_type(value_t::array), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an array (implicit) @@ -1211,6 +1245,7 @@ class basic_json using std::begin; using std::end; m_value.array = create(begin(val), end(val)); + assert_invariant(); } /*! @@ -1236,7 +1271,9 @@ class basic_json */ basic_json(const string_t& val) : m_type(value_t::string), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create a string (explicit) @@ -1260,7 +1297,9 @@ class basic_json */ basic_json(const typename string_t::value_type* val) : basic_json(string_t(val)) - {} + { + assert_invariant(); + } /*! @brief create a string (implicit) @@ -1291,7 +1330,9 @@ class basic_json = 0> basic_json(const CompatibleStringType& val) : basic_json(string_t(val)) - {} + { + assert_invariant(); + } /*! @brief create a boolean (explicit) @@ -1309,7 +1350,9 @@ class basic_json */ basic_json(boolean_t val) noexcept : m_type(value_t::boolean), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an integer number (explicit) @@ -1342,7 +1385,9 @@ class basic_json = 0> basic_json(const number_integer_t val) noexcept : m_type(value_t::number_integer), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an integer number from an enum type (explicit) @@ -1372,7 +1417,9 @@ class basic_json basic_json(const int val) noexcept : m_type(value_t::number_integer), m_value(static_cast(val)) - {} + { + assert_invariant(); + } /*! @brief create an integer number (implicit) @@ -1409,7 +1456,9 @@ class basic_json basic_json(const CompatibleNumberIntegerType val) noexcept : m_type(value_t::number_integer), m_value(static_cast(val)) - {} + { + assert_invariant(); + } /*! @brief create an unsigned integer number (explicit) @@ -1436,7 +1485,9 @@ class basic_json = 0> basic_json(const number_unsigned_t val) noexcept : m_type(value_t::number_unsigned), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an unsigned number (implicit) @@ -1468,7 +1519,9 @@ class basic_json basic_json(const CompatibleNumberUnsignedType val) noexcept : m_type(value_t::number_unsigned), m_value(static_cast(val)) - {} + { + assert_invariant(); + } /*! @brief create a floating-point number (explicit) @@ -1503,6 +1556,8 @@ class basic_json m_type = value_t::null; m_value = json_value(); } + + assert_invariant(); } /*! @@ -1543,7 +1598,9 @@ class basic_json > basic_json(const CompatibleNumberFloatType val) noexcept : basic_json(number_float_t(val)) - {} + { + assert_invariant(); + } /*! @brief create a container (array or object) from an initializer list @@ -1648,8 +1705,6 @@ class basic_json m_type = value_t::object; m_value = value_t::object; - assert(m_value.object != nullptr); - std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); @@ -1661,6 +1716,8 @@ class basic_json m_type = value_t::array; m_value.array = create(init); } + + assert_invariant(); } /*! @@ -1765,6 +1822,7 @@ class basic_json : m_type(value_t::array) { m_value.array = create(cnt, val); + assert_invariant(); } /*! @@ -1894,6 +1952,8 @@ class basic_json throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); } } + + assert_invariant(); } /*! @@ -1919,6 +1979,7 @@ class basic_json explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) { *this = parser(i, cb).parse(); + assert_invariant(); } /////////////////////////////////////// @@ -1950,25 +2011,25 @@ class basic_json basic_json(const basic_json& other) : m_type(other.m_type) { + // check of passed value is valid + other.assert_invariant(); + switch (m_type) { case value_t::object: { - assert(other.m_value.object != nullptr); m_value = *other.m_value.object; break; } case value_t::array: { - assert(other.m_value.array != nullptr); m_value = *other.m_value.array; break; } case value_t::string: { - assert(other.m_value.string != nullptr); m_value = *other.m_value.string; break; } @@ -2002,6 +2063,8 @@ class basic_json break; } } + + assert_invariant(); } /*! @@ -2026,9 +2089,14 @@ class basic_json : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) { + // check that passed value is valid + other.assert_invariant(); + // invalidate payload other.m_type = value_t::null; other.m_value = {}; + + assert_invariant(); } /*! @@ -2061,9 +2129,14 @@ class basic_json std::is_nothrow_move_assignable::value ) { + // check that passed value is valid + other.assert_invariant(); + using std::swap; swap(m_type, other.m_type); swap(m_value, other.m_value); + + assert_invariant(); return *this; } @@ -2084,6 +2157,8 @@ class basic_json */ ~basic_json() { + assert_invariant(); + switch (m_type) { case value_t::object: @@ -2548,7 +2623,6 @@ class basic_json { if (is_object()) { - assert(m_value.object != nullptr); return T(m_value.object->begin(), m_value.object->end()); } else @@ -2562,7 +2636,6 @@ class basic_json { if (is_object()) { - assert(m_value.object != nullptr); return *(m_value.object); } else @@ -2585,7 +2658,6 @@ class basic_json if (is_array()) { T to_vector; - assert(m_value.array != nullptr); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) { @@ -2610,7 +2682,6 @@ class basic_json if (is_array()) { std::vector to_vector; - assert(m_value.array != nullptr); to_vector.reserve(m_value.array->size()); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) @@ -2635,7 +2706,6 @@ class basic_json { if (is_array()) { - assert(m_value.array != nullptr); return T(m_value.array->begin(), m_value.array->end()); } else @@ -2649,7 +2719,6 @@ class basic_json { if (is_array()) { - assert(m_value.array != nullptr); return *(m_value.array); } else @@ -2667,7 +2736,6 @@ class basic_json { if (is_string()) { - assert(m_value.string != nullptr); return *m_value.string; } else @@ -3143,7 +3211,6 @@ class basic_json { try { - assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3187,7 +3254,6 @@ class basic_json { try { - assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3235,7 +3301,6 @@ class basic_json { try { - assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3283,7 +3348,6 @@ class basic_json { try { - assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3330,13 +3394,13 @@ class basic_json { m_type = value_t::array; m_value.array = create(); + assert_invariant(); } // operator[] only works for arrays if (is_array()) { // fill up array with null values if given idx is outside range - assert(m_value.array != nullptr); if (idx >= m_value.array->size()) { m_value.array->insert(m_value.array->end(), @@ -3376,7 +3440,6 @@ class basic_json // const operator[] only works for arrays if (is_array()) { - assert(m_value.array != nullptr); return m_value.array->operator[](idx); } else @@ -3419,12 +3482,12 @@ class basic_json { m_type = value_t::object; m_value.object = create(); + assert_invariant(); } // operator[] only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->operator[](key); } else @@ -3465,7 +3528,6 @@ class basic_json // const operator[] only works for objects if (is_object()) { - assert(m_value.object != nullptr); assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } @@ -3578,12 +3640,12 @@ class basic_json { m_type = value_t::object; m_value = value_t::object; + assert_invariant(); } // at only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->operator[](key); } else @@ -3625,7 +3687,6 @@ class basic_json // at only works for objects if (is_object()) { - assert(m_value.object != nullptr); assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } @@ -3952,24 +4013,25 @@ class basic_json if (is_string()) { - delete m_value.string; + AllocatorType alloc; + alloc.destroy(m_value.string); + alloc.deallocate(m_value.string, 1); m_value.string = nullptr; } m_type = value_t::null; + assert_invariant(); break; } case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } @@ -4060,17 +4122,19 @@ class basic_json if (is_string()) { - delete m_value.string; + AllocatorType alloc; + alloc.destroy(m_value.string); + alloc.deallocate(m_value.string, 1); m_value.string = nullptr; } m_type = value_t::null; + assert_invariant(); break; } case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; @@ -4078,7 +4142,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; @@ -4127,7 +4190,6 @@ class basic_json // this erase only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->erase(key); } else @@ -4170,7 +4232,6 @@ class basic_json throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); } - assert(m_value.array != nullptr); m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else @@ -4213,7 +4274,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4230,7 +4290,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4258,7 +4317,6 @@ class basic_json size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types - assert(not is_object() or m_value.object != nullptr); return is_object() ? m_value.object->count(key) : 0; } @@ -4634,14 +4692,12 @@ class basic_json case value_t::array: { // delegate call to array_t::empty() - assert(m_value.array != nullptr); return m_value.array->empty(); } case value_t::object: { // delegate call to object_t::empty() - assert(m_value.object != nullptr); return m_value.object->empty(); } @@ -4704,14 +4760,12 @@ class basic_json case value_t::array: { // delegate call to array_t::size() - assert(m_value.array != nullptr); return m_value.array->size(); } case value_t::object: { // delegate call to object_t::size() - assert(m_value.object != nullptr); return m_value.object->size(); } @@ -4766,14 +4820,12 @@ class basic_json case value_t::array: { // delegate call to array_t::max_size() - assert(m_value.array != nullptr); return m_value.array->max_size(); } case value_t::object: { // delegate call to object_t::max_size() - assert(m_value.object != nullptr); return m_value.object->max_size(); } @@ -4850,21 +4902,18 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); m_value.string->clear(); break; } case value_t::array: { - assert(m_value.array != nullptr); m_value.array->clear(); break; } case value_t::object: { - assert(m_value.object != nullptr); m_value.object->clear(); break; } @@ -4909,10 +4958,10 @@ class basic_json { m_type = value_t::array; m_value = value_t::array; + assert_invariant(); } // add element to array (move semantics) - assert(m_value.array != nullptr); m_value.array->push_back(std::move(val)); // invalidate object val.m_type = value_t::null; @@ -4945,10 +4994,10 @@ class basic_json { m_type = value_t::array; m_value = value_t::array; + assert_invariant(); } // add element to array - assert(m_value.array != nullptr); m_value.array->push_back(val); } @@ -4995,10 +5044,10 @@ class basic_json { m_type = value_t::object; m_value = value_t::object; + assert_invariant(); } // add element to array - assert(m_value.object != nullptr); m_value.object->insert(val); } @@ -5095,7 +5144,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } @@ -5151,7 +5199,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } @@ -5218,7 +5265,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert( pos.m_it.array_iterator, first.m_it.array_iterator, @@ -5266,7 +5312,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); return result; } @@ -5297,6 +5342,7 @@ class basic_json { std::swap(m_type, other.m_type); std::swap(m_value, other.m_value); + assert_invariant(); } /*! @@ -5324,7 +5370,6 @@ class basic_json // swap only works for arrays if (is_array()) { - assert(m_value.array != nullptr); std::swap(*(m_value.array), other); } else @@ -5358,7 +5403,6 @@ class basic_json // swap only works for objects if (is_object()) { - assert(m_value.object != nullptr); std::swap(*(m_value.object), other); } else @@ -5392,7 +5436,6 @@ class basic_json // swap only works for strings if (is_string()) { - assert(m_value.string != nullptr); std::swap(*(m_value.string), other); } else @@ -5479,14 +5522,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array == *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object == *rhs.m_value.object; } case value_t::null: @@ -5495,8 +5534,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string == *rhs.m_value.string; } case value_t::boolean: @@ -5669,14 +5706,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: @@ -5685,8 +5718,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: @@ -6232,8 +6263,6 @@ class basic_json { case value_t::object: { - assert(m_value.object != nullptr); - if (m_value.object->empty()) { o << "{}"; @@ -6274,8 +6303,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); - if (m_value.array->empty()) { o << "[]"; @@ -6314,7 +6341,6 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); o << string_t("\"") << escape_string(*m_value.string) << "\""; return; } @@ -6701,14 +6727,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object != nullptr); m_it.object_iterator = m_object->m_value.object->begin(); break; } case basic_json::value_t::array: { - assert(m_object->m_value.array != nullptr); m_it.array_iterator = m_object->m_value.array->begin(); break; } @@ -6740,14 +6764,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object != nullptr); m_it.object_iterator = m_object->m_value.object->end(); break; } case basic_json::value_t::array: { - assert(m_object->m_value.array != nullptr); m_it.array_iterator = m_object->m_value.array->end(); break; } @@ -6773,14 +6795,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object); assert(m_it.object_iterator != m_object->m_value.object->end()); return m_it.object_iterator->second; } case basic_json::value_t::array: { - assert(m_object->m_value.array); assert(m_it.array_iterator != m_object->m_value.array->end()); return *m_it.array_iterator; } @@ -6816,14 +6836,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object); assert(m_it.object_iterator != m_object->m_value.object->end()); return &(m_it.object_iterator->second); } case basic_json::value_t::array: { - assert(m_object->m_value.array); assert(m_it.array_iterator != m_object->m_value.array->end()); return &*m_it.array_iterator; } @@ -8846,6 +8864,7 @@ basic_json_parser_63: basic_json parse() { basic_json result = parse_internal(true); + result.assert_invariant(); expect(lexer::token_type::end_of_input); @@ -8868,7 +8887,7 @@ basic_json_parser_63: { // explicitly set result to object to cope with {} result.m_type = value_t::object; - result.m_value = json_value(value_t::object); + result.m_value = value_t::object; } // read next token @@ -8946,7 +8965,7 @@ basic_json_parser_63: { // explicitly set result to object to cope with [] result.m_type = value_t::array; - result.m_value = json_value(value_t::array); + result.m_value = value_t::array; } // read next token @@ -9638,7 +9657,6 @@ basic_json_parser_63: basic_json result; // iterate the JSON object values - assert(value.m_value.object != nullptr); for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 7bc0f360e..09866a81b 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -190,6 +190,13 @@ default) JSON values can be used like STL containers and provide reverse iterator access. +@invariant The member variables @a m_value and @a m_type have the following +relationship: +- If `m_type == value_t::object`, then `m_value.object != nullptr`. +- If `m_type == value_t::array`, then `m_value.array != nullptr`. +- If `m_type == value_t::string`, then `m_value.string != nullptr`. +The invariants are checked by member function assert_invariant(). + @internal @note ObjectType trick from http://stackoverflow.com/a/9860911 @endinternal @@ -891,6 +898,21 @@ class basic_json } }; + /*! + @brief checks the class invariants + + This function asserts the class invariants. It needs to be called at the + end of every constructor to make sure that created objects respect the + invariant. Furthermore, it has to be called each time the type of a JSON + value is changed, because the invariant expresses a relationship between + @a m_type and @a m_value. + */ + void assert_invariant() const + { + assert(m_type != value_t::object or m_value.object != nullptr); + assert(m_type != value_t::array or m_value.array != nullptr); + assert(m_type != value_t::string or m_value.string != nullptr); + } public: ////////////////////////// @@ -1030,7 +1052,9 @@ class basic_json */ basic_json(const value_t value_type) : m_type(value_type), m_value(value_type) - {} + { + assert_invariant(); + } /*! @brief create a null object (implicitly) @@ -1038,6 +1062,9 @@ class basic_json Create a `null` JSON value. This is the implicit version of the `null` value constructor as it takes no parameters. + @note The class invariant is satisfied, because it poses no requirements + for null values. + @complexity Constant. @exceptionsafety No-throw guarantee: this constructor never throws @@ -1082,7 +1109,9 @@ class basic_json */ basic_json(std::nullptr_t) noexcept : basic_json(value_t::null) - {} + { + assert_invariant(); + } /*! @brief create an object (explicit) @@ -1105,7 +1134,9 @@ class basic_json */ basic_json(const object_t& val) : m_type(value_t::object), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an object (implicit) @@ -1144,6 +1175,7 @@ class basic_json using std::begin; using std::end; m_value.object = create(begin(val), end(val)); + assert_invariant(); } /*! @@ -1167,7 +1199,9 @@ class basic_json */ basic_json(const array_t& val) : m_type(value_t::array), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an array (implicit) @@ -1211,6 +1245,7 @@ class basic_json using std::begin; using std::end; m_value.array = create(begin(val), end(val)); + assert_invariant(); } /*! @@ -1236,7 +1271,9 @@ class basic_json */ basic_json(const string_t& val) : m_type(value_t::string), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create a string (explicit) @@ -1260,7 +1297,9 @@ class basic_json */ basic_json(const typename string_t::value_type* val) : basic_json(string_t(val)) - {} + { + assert_invariant(); + } /*! @brief create a string (implicit) @@ -1291,7 +1330,9 @@ class basic_json = 0> basic_json(const CompatibleStringType& val) : basic_json(string_t(val)) - {} + { + assert_invariant(); + } /*! @brief create a boolean (explicit) @@ -1309,7 +1350,9 @@ class basic_json */ basic_json(boolean_t val) noexcept : m_type(value_t::boolean), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an integer number (explicit) @@ -1342,7 +1385,9 @@ class basic_json = 0> basic_json(const number_integer_t val) noexcept : m_type(value_t::number_integer), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an integer number from an enum type (explicit) @@ -1372,7 +1417,9 @@ class basic_json basic_json(const int val) noexcept : m_type(value_t::number_integer), m_value(static_cast(val)) - {} + { + assert_invariant(); + } /*! @brief create an integer number (implicit) @@ -1409,7 +1456,9 @@ class basic_json basic_json(const CompatibleNumberIntegerType val) noexcept : m_type(value_t::number_integer), m_value(static_cast(val)) - {} + { + assert_invariant(); + } /*! @brief create an unsigned integer number (explicit) @@ -1436,7 +1485,9 @@ class basic_json = 0> basic_json(const number_unsigned_t val) noexcept : m_type(value_t::number_unsigned), m_value(val) - {} + { + assert_invariant(); + } /*! @brief create an unsigned number (implicit) @@ -1468,7 +1519,9 @@ class basic_json basic_json(const CompatibleNumberUnsignedType val) noexcept : m_type(value_t::number_unsigned), m_value(static_cast(val)) - {} + { + assert_invariant(); + } /*! @brief create a floating-point number (explicit) @@ -1503,6 +1556,8 @@ class basic_json m_type = value_t::null; m_value = json_value(); } + + assert_invariant(); } /*! @@ -1543,7 +1598,9 @@ class basic_json > basic_json(const CompatibleNumberFloatType val) noexcept : basic_json(number_float_t(val)) - {} + { + assert_invariant(); + } /*! @brief create a container (array or object) from an initializer list @@ -1648,8 +1705,6 @@ class basic_json m_type = value_t::object; m_value = value_t::object; - assert(m_value.object != nullptr); - std::for_each(init.begin(), init.end(), [this](const basic_json & element) { m_value.object->emplace(*(element[0].m_value.string), element[1]); @@ -1661,6 +1716,8 @@ class basic_json m_type = value_t::array; m_value.array = create(init); } + + assert_invariant(); } /*! @@ -1765,6 +1822,7 @@ class basic_json : m_type(value_t::array) { m_value.array = create(cnt, val); + assert_invariant(); } /*! @@ -1894,6 +1952,8 @@ class basic_json throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); } } + + assert_invariant(); } /*! @@ -1919,6 +1979,7 @@ class basic_json explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr) { *this = parser(i, cb).parse(); + assert_invariant(); } /////////////////////////////////////// @@ -1950,25 +2011,25 @@ class basic_json basic_json(const basic_json& other) : m_type(other.m_type) { + // check of passed value is valid + other.assert_invariant(); + switch (m_type) { case value_t::object: { - assert(other.m_value.object != nullptr); m_value = *other.m_value.object; break; } case value_t::array: { - assert(other.m_value.array != nullptr); m_value = *other.m_value.array; break; } case value_t::string: { - assert(other.m_value.string != nullptr); m_value = *other.m_value.string; break; } @@ -2002,6 +2063,8 @@ class basic_json break; } } + + assert_invariant(); } /*! @@ -2026,9 +2089,14 @@ class basic_json : m_type(std::move(other.m_type)), m_value(std::move(other.m_value)) { + // check that passed value is valid + other.assert_invariant(); + // invalidate payload other.m_type = value_t::null; other.m_value = {}; + + assert_invariant(); } /*! @@ -2061,9 +2129,14 @@ class basic_json std::is_nothrow_move_assignable::value ) { + // check that passed value is valid + other.assert_invariant(); + using std::swap; swap(m_type, other.m_type); swap(m_value, other.m_value); + + assert_invariant(); return *this; } @@ -2084,6 +2157,8 @@ class basic_json */ ~basic_json() { + assert_invariant(); + switch (m_type) { case value_t::object: @@ -2548,7 +2623,6 @@ class basic_json { if (is_object()) { - assert(m_value.object != nullptr); return T(m_value.object->begin(), m_value.object->end()); } else @@ -2562,7 +2636,6 @@ class basic_json { if (is_object()) { - assert(m_value.object != nullptr); return *(m_value.object); } else @@ -2585,7 +2658,6 @@ class basic_json if (is_array()) { T to_vector; - assert(m_value.array != nullptr); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) { @@ -2610,7 +2682,6 @@ class basic_json if (is_array()) { std::vector to_vector; - assert(m_value.array != nullptr); to_vector.reserve(m_value.array->size()); std::transform(m_value.array->begin(), m_value.array->end(), std::inserter(to_vector, to_vector.end()), [](basic_json i) @@ -2635,7 +2706,6 @@ class basic_json { if (is_array()) { - assert(m_value.array != nullptr); return T(m_value.array->begin(), m_value.array->end()); } else @@ -2649,7 +2719,6 @@ class basic_json { if (is_array()) { - assert(m_value.array != nullptr); return *(m_value.array); } else @@ -2667,7 +2736,6 @@ class basic_json { if (is_string()) { - assert(m_value.string != nullptr); return *m_value.string; } else @@ -3143,7 +3211,6 @@ class basic_json { try { - assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3187,7 +3254,6 @@ class basic_json { try { - assert(m_value.array != nullptr); return m_value.array->at(idx); } catch (std::out_of_range&) @@ -3235,7 +3301,6 @@ class basic_json { try { - assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3283,7 +3348,6 @@ class basic_json { try { - assert(m_value.object != nullptr); return m_value.object->at(key); } catch (std::out_of_range&) @@ -3330,13 +3394,13 @@ class basic_json { m_type = value_t::array; m_value.array = create(); + assert_invariant(); } // operator[] only works for arrays if (is_array()) { // fill up array with null values if given idx is outside range - assert(m_value.array != nullptr); if (idx >= m_value.array->size()) { m_value.array->insert(m_value.array->end(), @@ -3376,7 +3440,6 @@ class basic_json // const operator[] only works for arrays if (is_array()) { - assert(m_value.array != nullptr); return m_value.array->operator[](idx); } else @@ -3419,12 +3482,12 @@ class basic_json { m_type = value_t::object; m_value.object = create(); + assert_invariant(); } // operator[] only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->operator[](key); } else @@ -3465,7 +3528,6 @@ class basic_json // const operator[] only works for objects if (is_object()) { - assert(m_value.object != nullptr); assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } @@ -3578,12 +3640,12 @@ class basic_json { m_type = value_t::object; m_value = value_t::object; + assert_invariant(); } // at only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->operator[](key); } else @@ -3625,7 +3687,6 @@ class basic_json // at only works for objects if (is_object()) { - assert(m_value.object != nullptr); assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } @@ -3952,24 +4013,25 @@ class basic_json if (is_string()) { - delete m_value.string; + AllocatorType alloc; + alloc.destroy(m_value.string); + alloc.deallocate(m_value.string, 1); m_value.string = nullptr; } m_type = value_t::null; + assert_invariant(); break; } case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } @@ -4060,17 +4122,19 @@ class basic_json if (is_string()) { - delete m_value.string; + AllocatorType alloc; + alloc.destroy(m_value.string); + alloc.deallocate(m_value.string, 1); m_value.string = nullptr; } m_type = value_t::null; + assert_invariant(); break; } case value_t::object: { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; @@ -4078,7 +4142,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; @@ -4127,7 +4190,6 @@ class basic_json // this erase only works for objects if (is_object()) { - assert(m_value.object != nullptr); return m_value.object->erase(key); } else @@ -4170,7 +4232,6 @@ class basic_json throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); } - assert(m_value.array != nullptr); m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else @@ -4213,7 +4274,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4230,7 +4290,6 @@ class basic_json if (is_object()) { - assert(m_value.object != nullptr); result.m_it.object_iterator = m_value.object->find(key); } @@ -4258,7 +4317,6 @@ class basic_json size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types - assert(not is_object() or m_value.object != nullptr); return is_object() ? m_value.object->count(key) : 0; } @@ -4634,14 +4692,12 @@ class basic_json case value_t::array: { // delegate call to array_t::empty() - assert(m_value.array != nullptr); return m_value.array->empty(); } case value_t::object: { // delegate call to object_t::empty() - assert(m_value.object != nullptr); return m_value.object->empty(); } @@ -4704,14 +4760,12 @@ class basic_json case value_t::array: { // delegate call to array_t::size() - assert(m_value.array != nullptr); return m_value.array->size(); } case value_t::object: { // delegate call to object_t::size() - assert(m_value.object != nullptr); return m_value.object->size(); } @@ -4766,14 +4820,12 @@ class basic_json case value_t::array: { // delegate call to array_t::max_size() - assert(m_value.array != nullptr); return m_value.array->max_size(); } case value_t::object: { // delegate call to object_t::max_size() - assert(m_value.object != nullptr); return m_value.object->max_size(); } @@ -4850,21 +4902,18 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); m_value.string->clear(); break; } case value_t::array: { - assert(m_value.array != nullptr); m_value.array->clear(); break; } case value_t::object: { - assert(m_value.object != nullptr); m_value.object->clear(); break; } @@ -4909,10 +4958,10 @@ class basic_json { m_type = value_t::array; m_value = value_t::array; + assert_invariant(); } // add element to array (move semantics) - assert(m_value.array != nullptr); m_value.array->push_back(std::move(val)); // invalidate object val.m_type = value_t::null; @@ -4945,10 +4994,10 @@ class basic_json { m_type = value_t::array; m_value = value_t::array; + assert_invariant(); } // add element to array - assert(m_value.array != nullptr); m_value.array->push_back(val); } @@ -4995,10 +5044,10 @@ class basic_json { m_type = value_t::object; m_value = value_t::object; + assert_invariant(); } // add element to array - assert(m_value.object != nullptr); m_value.object->insert(val); } @@ -5095,7 +5144,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } @@ -5151,7 +5199,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } @@ -5218,7 +5265,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert( pos.m_it.array_iterator, first.m_it.array_iterator, @@ -5266,7 +5312,6 @@ class basic_json // insert to array and return iterator iterator result(this); - assert(m_value.array != nullptr); result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist); return result; } @@ -5297,6 +5342,7 @@ class basic_json { std::swap(m_type, other.m_type); std::swap(m_value, other.m_value); + assert_invariant(); } /*! @@ -5324,7 +5370,6 @@ class basic_json // swap only works for arrays if (is_array()) { - assert(m_value.array != nullptr); std::swap(*(m_value.array), other); } else @@ -5358,7 +5403,6 @@ class basic_json // swap only works for objects if (is_object()) { - assert(m_value.object != nullptr); std::swap(*(m_value.object), other); } else @@ -5392,7 +5436,6 @@ class basic_json // swap only works for strings if (is_string()) { - assert(m_value.string != nullptr); std::swap(*(m_value.string), other); } else @@ -5479,14 +5522,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array == *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object == *rhs.m_value.object; } case value_t::null: @@ -5495,8 +5534,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string == *rhs.m_value.string; } case value_t::boolean: @@ -5669,14 +5706,10 @@ class basic_json { case value_t::array: { - assert(lhs.m_value.array != nullptr); - assert(rhs.m_value.array != nullptr); return *lhs.m_value.array < *rhs.m_value.array; } case value_t::object: { - assert(lhs.m_value.object != nullptr); - assert(rhs.m_value.object != nullptr); return *lhs.m_value.object < *rhs.m_value.object; } case value_t::null: @@ -5685,8 +5718,6 @@ class basic_json } case value_t::string: { - assert(lhs.m_value.string != nullptr); - assert(rhs.m_value.string != nullptr); return *lhs.m_value.string < *rhs.m_value.string; } case value_t::boolean: @@ -6232,8 +6263,6 @@ class basic_json { case value_t::object: { - assert(m_value.object != nullptr); - if (m_value.object->empty()) { o << "{}"; @@ -6274,8 +6303,6 @@ class basic_json case value_t::array: { - assert(m_value.array != nullptr); - if (m_value.array->empty()) { o << "[]"; @@ -6314,7 +6341,6 @@ class basic_json case value_t::string: { - assert(m_value.string != nullptr); o << string_t("\"") << escape_string(*m_value.string) << "\""; return; } @@ -6701,14 +6727,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object != nullptr); m_it.object_iterator = m_object->m_value.object->begin(); break; } case basic_json::value_t::array: { - assert(m_object->m_value.array != nullptr); m_it.array_iterator = m_object->m_value.array->begin(); break; } @@ -6740,14 +6764,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object != nullptr); m_it.object_iterator = m_object->m_value.object->end(); break; } case basic_json::value_t::array: { - assert(m_object->m_value.array != nullptr); m_it.array_iterator = m_object->m_value.array->end(); break; } @@ -6773,14 +6795,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object); assert(m_it.object_iterator != m_object->m_value.object->end()); return m_it.object_iterator->second; } case basic_json::value_t::array: { - assert(m_object->m_value.array); assert(m_it.array_iterator != m_object->m_value.array->end()); return *m_it.array_iterator; } @@ -6816,14 +6836,12 @@ class basic_json { case basic_json::value_t::object: { - assert(m_object->m_value.object); assert(m_it.object_iterator != m_object->m_value.object->end()); return &(m_it.object_iterator->second); } case basic_json::value_t::array: { - assert(m_object->m_value.array); assert(m_it.array_iterator != m_object->m_value.array->end()); return &*m_it.array_iterator; } @@ -8143,6 +8161,7 @@ class basic_json basic_json parse() { basic_json result = parse_internal(true); + result.assert_invariant(); expect(lexer::token_type::end_of_input); @@ -8165,7 +8184,7 @@ class basic_json { // explicitly set result to object to cope with {} result.m_type = value_t::object; - result.m_value = json_value(value_t::object); + result.m_value = value_t::object; } // read next token @@ -8243,7 +8262,7 @@ class basic_json { // explicitly set result to object to cope with [] result.m_type = value_t::array; - result.m_value = json_value(value_t::array); + result.m_value = value_t::array; } // read next token @@ -8935,7 +8954,6 @@ class basic_json basic_json result; // iterate the JSON object values - assert(value.m_value.object != nullptr); for (const auto& element : *value.m_value.object) { if (not element.second.is_primitive()) From a05df038cd952b6e586e40526df061d73059fb07 Mon Sep 17 00:00:00 2001 From: Niels Date: Sun, 31 Jul 2016 13:37:04 +0200 Subject: [PATCH 48/48] prepared release --- CMakeLists.txt | 2 +- ChangeLog.md | 5 ++--- Makefile | 4 +++- README.md | 2 +- doc/Doxyfile | 2 +- doc/examples/README.link | 2 +- doc/index.md | 2 +- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- test/src/fuzz.cpp | 2 +- test/src/unit.cpp | 2 +- 11 files changed, 14 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0488b3b3..72802b29b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.0) # define the project -project(nlohmann_json VERSION 2.0.0 LANGUAGES CXX) +project(nlohmann_json VERSION 2.0.2 LANGUAGES CXX) enable_testing() diff --git a/ChangeLog.md b/ChangeLog.md index 901e37c10..8062f3b31 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,9 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [Unreleased](https://github.com/nlohmann/json/tree/HEAD) - -[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.1...HEAD) +## [v2.0.2](https://github.com/nlohmann/json/releases/tag/v2.0.2) (2016-07-30) +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.1...v2.0.2) - value\(\) does not work with \_json\_pointer types [\#283](https://github.com/nlohmann/json/issues/283) - Easy serialization of classes [\#280](https://github.com/nlohmann/json/issues/280) diff --git a/Makefile b/Makefile index 98f076876..15d00f6e5 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,9 @@ json_benchmarks: benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/ # changelog ########################################################################## +NEXT_VERSION ?= "unreleased" + ChangeLog.md: - github_changelog_generator -o ChangeLog.md --simple-list --release-url https://github.com/nlohmann/json/releases/tag/%s + github_changelog_generator -o ChangeLog.md --simple-list --release-url https://github.com/nlohmann/json/releases/tag/%s --future-release $(NEXT_VERSION) gsed -i 's|https://github.com/nlohmann/json/releases/tag/HEAD|https://github.com/nlohmann/json/tree/HEAD|' ChangeLog.md gsed -i '2i All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).' ChangeLog.md diff --git a/README.md b/README.md index 584906799..c0bb61b17 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk?svg=true)](https://ci.appveyor.com/project/nlohmann/json) [![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json) -[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/wuiuqYiYqRTdI3rG) +[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/p5o4znPnGHJpDVqN) [![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) [![Github Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases) diff --git a/doc/Doxyfile b/doc/Doxyfile index e74a8a850..e0055d651 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "JSON for Modern C++" -PROJECT_NUMBER = 2.0.0 +PROJECT_NUMBER = 2.0.2 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = . diff --git a/doc/examples/README.link b/doc/examples/README.link index ed559e19f..0e87a79e6 100644 --- a/doc/examples/README.link +++ b/doc/examples/README.link @@ -1 +1 @@ -online \ No newline at end of file +online \ No newline at end of file diff --git a/doc/index.md b/doc/index.md index 5373d4f34..cf32a7a55 100644 --- a/doc/index.md +++ b/doc/index.md @@ -268,4 +268,4 @@ The container functions known from STL have been extended to support the differe @author [Niels Lohmann](http://nlohmann.me) @see https://github.com/nlohmann/json to download the source code -@version 2.0.0 +@version 2.0.2 diff --git a/src/json.hpp b/src/json.hpp index 7120ad80e..878fb899f 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.1 +| | |__ | | | | | | version 2.0.2 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 09866a81b..32482ea85 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.1 +| | |__ | | | | | | version 2.0.2 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/fuzz.cpp b/test/src/fuzz.cpp index d8b7ef7cf..de8ad42c1 100644 --- a/test/src/fuzz.cpp +++ b/test/src/fuzz.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.0.0 +| | |__ | | | | | | version 2.0.2 |_____|_____|_____|_|___| https://github.com/nlohmann/json Run "make fuzz_testing" and follow the instructions. diff --git a/test/src/unit.cpp b/test/src/unit.cpp index edbafacf2..79a4bb090 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.1 +| | |__ | | | | | | version 2.0.2 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License .