From 29f7abf57d85547fecbc11b8cc8457a91d516fae Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 15 Jan 2021 17:01:47 +0100 Subject: [PATCH 01/58] :rotating_light: fix format-truncation warning #2572 --- include/nlohmann/detail/output/serializer.hpp | 4 ++-- single_include/nlohmann/json.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index 0a34c8011..9e3f75660 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -497,7 +497,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(3, '\0'); + std::string sn(8, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); } @@ -591,7 +591,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(3, '\0'); + std::string sn(8, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 492118a5f..32865fd8e 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -16052,7 +16052,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(3, '\0'); + std::string sn(8, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); } @@ -16146,7 +16146,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(3, '\0'); + std::string sn(8, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); } From 42218cac1b8d79af5117da6cf8b64b9afcffdc05 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 21 Jan 2021 22:01:09 +0100 Subject: [PATCH 02/58] :alembic: try 9 bytes --- include/nlohmann/detail/output/serializer.hpp | 4 ++-- single_include/nlohmann/json.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index 9e3f75660..90bc65f93 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -497,7 +497,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(8, '\0'); + std::string sn(9, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); } @@ -591,7 +591,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(8, '\0'); + std::string sn(9, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 32865fd8e..768567567 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -16052,7 +16052,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(8, '\0'); + std::string sn(9, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); } @@ -16146,7 +16146,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(8, '\0'); + std::string sn(9, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); } From 1a1381f071156cffdc8f3d90d413e721ea6467a7 Mon Sep 17 00:00:00 2001 From: David Pfahler Date: Wed, 21 Apr 2021 10:24:01 +0200 Subject: [PATCH 03/58] Fixes #2728 includes some macros to be defined for using without file io. --- include/nlohmann/detail/input/input_adapters.hpp | 4 ++++ include/nlohmann/detail/output/output_adapters.hpp | 4 ++++ include/nlohmann/json.hpp | 8 ++++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index 63921ca55..9bb4a2b48 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -26,6 +26,7 @@ enum class input_format_t { json, cbor, msgpack, ubjson, bson }; // input adapters // //////////////////// +#ifndef JSON_NO_IO /*! Input adapter for stdio file access. This adapter read only 1 byte and do not use any buffer. This adapter is a very low level adapter. @@ -115,6 +116,7 @@ class input_stream_adapter std::istream* is = nullptr; std::streambuf* sb = nullptr; }; +#endif // JSON_NO_IO // General-purpose iterator-based adapter. It might not be as fast as // theoretically possible for some containers, but it is extremely versatile. @@ -381,6 +383,7 @@ auto input_adapter(const ContainerType& container) -> decltype(input_adapter(beg return input_adapter(begin(container), end(container)); } +#ifndef JSON_NO_IO // Special cases with fast paths inline file_input_adapter input_adapter(std::FILE* file) { @@ -396,6 +399,7 @@ inline input_stream_adapter input_adapter(std::istream&& stream) { return input_stream_adapter(stream); } +#endif // JSON_NO_IO using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); diff --git a/include/nlohmann/detail/output/output_adapters.hpp b/include/nlohmann/detail/output/output_adapters.hpp index 71ca65b92..46c82e9fd 100644 --- a/include/nlohmann/detail/output/output_adapters.hpp +++ b/include/nlohmann/detail/output/output_adapters.hpp @@ -50,6 +50,7 @@ class output_vector_adapter : public output_adapter_protocol std::vector& v; }; +#ifndef JSON_NO_IO /// output adapter for output streams template class output_stream_adapter : public output_adapter_protocol @@ -73,6 +74,7 @@ class output_stream_adapter : public output_adapter_protocol private: std::basic_ostream& stream; }; +#endif // JSON_NO_IO /// output adapter for basic_string template> @@ -105,8 +107,10 @@ class output_adapter output_adapter(std::vector& vec) : oa(std::make_shared>(vec)) {} +#ifndef JSON_NO_IO output_adapter(std::basic_ostream& s) : oa(std::make_shared>(s)) {} +#endif // JSON_NO_IO output_adapter(StringType& s) : oa(std::make_shared>(s)) {} diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index a9e6c76d1..a783e3d59 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -6521,7 +6521,7 @@ class basic_json /// @name serialization /// @{ - +#ifndef JSON_NO_IO /*! @brief serialize to stream @@ -6581,7 +6581,7 @@ class basic_json { return o << j; } - +#endif // JSON_NO_IO /// @} @@ -6837,7 +6837,7 @@ class basic_json ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); } - +#ifndef JSON_NO_IO /*! @brief deserialize from stream @deprecated This stream operator is deprecated and will be removed in @@ -6882,7 +6882,7 @@ class basic_json parser(detail::input_adapter(i)).parse(false, j); return i; } - +#endif // JSON_NO_IO /// @} /////////////////////////// From 0a2de2f5b9149c80825d2cf19ebf7f2c5cb8b511 Mon Sep 17 00:00:00 2001 From: David Pfahler Date: Wed, 21 Apr 2021 12:54:55 +0200 Subject: [PATCH 04/58] fixed amalgation file for #2728 --- single_include/nlohmann/json.hpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index a70aaf8cb..752f8d8af 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4747,6 +4747,7 @@ enum class input_format_t { json, cbor, msgpack, ubjson, bson }; // input adapters // //////////////////// +#ifndef JSON_NO_IO /*! Input adapter for stdio file access. This adapter read only 1 byte and do not use any buffer. This adapter is a very low level adapter. @@ -4836,6 +4837,7 @@ class input_stream_adapter std::istream* is = nullptr; std::streambuf* sb = nullptr; }; +#endif // JSON_NO_IO // General-purpose iterator-based adapter. It might not be as fast as // theoretically possible for some containers, but it is extremely versatile. @@ -5102,6 +5104,7 @@ auto input_adapter(const ContainerType& container) -> decltype(input_adapter(beg return input_adapter(begin(container), end(container)); } +#ifndef JSON_NO_IO // Special cases with fast paths inline file_input_adapter input_adapter(std::FILE* file) { @@ -5117,6 +5120,7 @@ inline input_stream_adapter input_adapter(std::istream&& stream) { return input_stream_adapter(stream); } +#endif // JSON_NO_IO using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); @@ -12664,6 +12668,7 @@ class output_vector_adapter : public output_adapter_protocol std::vector& v; }; +#ifndef JSON_NO_IO /// output adapter for output streams template class output_stream_adapter : public output_adapter_protocol @@ -12687,6 +12692,7 @@ class output_stream_adapter : public output_adapter_protocol private: std::basic_ostream& stream; }; +#endif // JSON_NO_IO /// output adapter for basic_string template> @@ -12719,8 +12725,10 @@ class output_adapter output_adapter(std::vector& vec) : oa(std::make_shared>(vec)) {} +#ifndef JSON_NO_IO output_adapter(std::basic_ostream& s) : oa(std::make_shared>(s)) {} +#endif // JSON_NO_IO output_adapter(StringType& s) : oa(std::make_shared>(s)) {} @@ -23009,7 +23017,7 @@ class basic_json /// @name serialization /// @{ - +#ifndef JSON_NO_IO /*! @brief serialize to stream @@ -23069,7 +23077,7 @@ class basic_json { return o << j; } - +#endif // JSON_NO_IO /// @} @@ -23325,7 +23333,7 @@ class basic_json ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); } - +#ifndef JSON_NO_IO /*! @brief deserialize from stream @deprecated This stream operator is deprecated and will be removed in @@ -23370,7 +23378,7 @@ class basic_json parser(detail::input_adapter(i)).parse(false, j); return i; } - +#endif // JSON_NO_IO /// @} /////////////////////////// From b08139ea4b5940c396311c4f4f428dbebc061e02 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 4 May 2021 10:22:34 +0200 Subject: [PATCH 05/58] :recycle: replace EOF with std::char_traits::eof() --- include/nlohmann/detail/input/input_adapters.hpp | 2 +- single_include/nlohmann/json.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index 5d0b59b57..dced9bfff 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -105,7 +105,7 @@ class input_stream_adapter { auto res = sb->sbumpc(); // set eof manually, as we don't use the istream interface. - if (JSON_HEDLEY_UNLIKELY(res == EOF)) + if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) { is->clear(is->rdstate() | std::ios::eofbit); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index b3c568b1a..2716e1e7b 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -5332,7 +5332,7 @@ class input_stream_adapter { auto res = sb->sbumpc(); // set eof manually, as we don't use the istream interface. - if (JSON_HEDLEY_UNLIKELY(res == EOF)) + if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) { is->clear(is->rdstate() | std::ios::eofbit); } From 1d8869f8bc5958af0a3a2f83177f843cbd3cd868 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 8 May 2021 13:33:30 +0200 Subject: [PATCH 06/58] :construction_worker: add Drone CI --- .drone.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 000000000..22be5cc4d --- /dev/null +++ b/.drone.yml @@ -0,0 +1,14 @@ +kind: pipeline +name: test-on-arm64 + +platform: + arch: arm64 + +steps: +- name: build + image: gcc + commands: + - mkdir build + - cd build + - cmake .. + - cmake --build . From 77a5cd247edf673157ae70a983623e4b63ba2ec4 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 8 May 2021 13:56:19 +0200 Subject: [PATCH 07/58] :wrench: build cmake --- .drone.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.drone.yml b/.drone.yml index 22be5cc4d..847724dbc 100644 --- a/.drone.yml +++ b/.drone.yml @@ -8,6 +8,11 @@ steps: - name: build image: gcc commands: + - wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz + - tar xfz cmake-3.20.2.tar.gz + - cd cmake-3.20.2 + - ./configure + - make - mkdir build - cd build - cmake .. From a6e2fd1b15d763fb5dc6837f72fce269a9fc4a9c Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 8 May 2021 14:41:43 +0200 Subject: [PATCH 08/58] :wrench: use built CMake --- .drone.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index 847724dbc..83678f5d4 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,8 +12,9 @@ steps: - tar xfz cmake-3.20.2.tar.gz - cd cmake-3.20.2 - ./configure - - make + - make cmake -j10 + - cd .. - mkdir build - cd build - - cmake .. + - ../cmake-3.20.2/bin/cmake .. - cmake --build . From 27a71ccdd8d1729b15e08023bfe13755875eb499 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 8 May 2021 20:42:24 +0200 Subject: [PATCH 09/58] :wrench: fix path --- .drone.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 83678f5d4..0ea69aa3f 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,4 +17,6 @@ steps: - mkdir build - cd build - ../cmake-3.20.2/bin/cmake .. - - cmake --build . + - make -j10 + - cd test + - ctest -j10 From 9ec8f4efa86484aa43cd2c2e46072dfa1a8dbcbb Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 10:39:37 +0200 Subject: [PATCH 10/58] :wrench: fix ctest path --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 0ea69aa3f..36a796045 100644 --- a/.drone.yml +++ b/.drone.yml @@ -19,4 +19,4 @@ steps: - ../cmake-3.20.2/bin/cmake .. - make -j10 - cd test - - ctest -j10 + - ../../cmake-3.20.2/bin/ctest -j10 From f3193e1e94a7ab5c1382562e5ac17b8b63017381 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 11:07:57 +0200 Subject: [PATCH 11/58] :wrench: build ctest --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 36a796045..4416c8522 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,7 +12,7 @@ steps: - tar xfz cmake-3.20.2.tar.gz - cd cmake-3.20.2 - ./configure - - make cmake -j10 + - make cmake ctest -j10 - cd .. - mkdir build - cd build From 42f251229007014c33f43dbe99fbaf302e157a1c Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:00:35 +0200 Subject: [PATCH 12/58] :wrench: skip slow tests --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 4416c8522..3cdefe4b9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -16,7 +16,7 @@ steps: - cd .. - mkdir build - cd build - - ../cmake-3.20.2/bin/cmake .. + - ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON - make -j10 - cd test - ../../cmake-3.20.2/bin/ctest -j10 From e6e7309514daa2aed5a8726bad4d7fb7d8df39e7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:31:27 +0200 Subject: [PATCH 13/58] :construction_worker: arm and arm64 --- .drone.yml | 52 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/.drone.yml b/.drone.yml index 3cdefe4b9..4f87bc52c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,22 +1,32 @@ -kind: pipeline -name: test-on-arm64 +local Pipeline(version, arch) = { + kind: "pipeline", + name: "test-on-"+arch, + platform: { + arch: arch + } + steps: [ + { + name: "build", + image: "gcc", + commands: [ + "wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz", + "tar xfz cmake-3.20.2.tar.gz", + "cd cmake-3.20.2", + "./configure", + "make cmake ctest -j10", + "cd ..", + "mkdir build", + "cd build", + "../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON", + "make -j10", + "cd test", + "../../cmake-3.20.2/bin/ctest -j10" + ] + } + ] +}; -platform: - arch: arm64 - -steps: -- name: build - image: gcc - commands: - - wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz - - tar xfz cmake-3.20.2.tar.gz - - cd cmake-3.20.2 - - ./configure - - make cmake ctest -j10 - - cd .. - - mkdir build - - cd build - - ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON - - make -j10 - - cd test - - ../../cmake-3.20.2/bin/ctest -j10 +[ + Pipeline("arm"), + Pipeline("arm64") +] From df6fa6c11c1473a5133653b89726b7df75893402 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:32:50 +0200 Subject: [PATCH 14/58] :construction_worker: arm and arm64 --- .drone.yml | 76 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/.drone.yml b/.drone.yml index 4f87bc52c..f773009a2 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,32 +1,46 @@ -local Pipeline(version, arch) = { - kind: "pipeline", - name: "test-on-"+arch, - platform: { - arch: arch - } - steps: [ - { - name: "build", - image: "gcc", - commands: [ - "wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz", - "tar xfz cmake-3.20.2.tar.gz", - "cd cmake-3.20.2", - "./configure", - "make cmake ctest -j10", - "cd ..", - "mkdir build", - "cd build", - "../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON", - "make -j10", - "cd test", - "../../cmake-3.20.2/bin/ctest -j10" - ] - } - ] -}; +kind: pipeline +name: test-on-arm -[ - Pipeline("arm"), - Pipeline("arm64") -] +platform: + arch: arm + +steps: +- name: build + image: gcc + commands: + - wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz + - tar xfz cmake-3.20.2.tar.gz + - cd cmake-3.20.2 + - ./configure + - make cmake ctest -j10 + - cd .. + - mkdir build + - cd build + - ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON + - make -j10 + - cd test + - ../../cmake-3.20.2/bin/ctest -j10 + +--- +kind: pipeline +name: test-on-arm64 + +platform: + arch: arm64 + +steps: +- name: build + image: gcc + commands: + - wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz + - tar xfz cmake-3.20.2.tar.gz + - cd cmake-3.20.2 + - ./configure + - make cmake ctest -j10 + - cd .. + - mkdir build + - cd build + - ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON + - make -j10 + - cd test + - ../../cmake-3.20.2/bin/ctest -j10 From 9746f72d7151494c1b50a1d3c3ca47eeb67d62f3 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:34:28 +0200 Subject: [PATCH 15/58] :hammer: do not check certificate --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index f773009a2..471ce1095 100644 --- a/.drone.yml +++ b/.drone.yml @@ -8,7 +8,7 @@ steps: - name: build image: gcc commands: - - wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz + - wget --no-check-certificates https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz - tar xfz cmake-3.20.2.tar.gz - cd cmake-3.20.2 - ./configure From 3685dbdcfdf9379869f82a07473ce89c7c35eab1 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:41:40 +0200 Subject: [PATCH 16/58] :wrench: checkout cmake via git --- .drone.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.drone.yml b/.drone.yml index 471ce1095..9fdae5a0a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -8,18 +8,17 @@ steps: - name: build image: gcc commands: - - wget --no-check-certificates https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz - - tar xfz cmake-3.20.2.tar.gz - - cd cmake-3.20.2 + - git clone https://github.com/Kitware/CMake.git + - cd CMake - ./configure - make cmake ctest -j10 - cd .. - mkdir build - cd build - - ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON + - ../CMake/bin/cmake .. -DJSON_FastTests=ON - make -j10 - cd test - - ../../cmake-3.20.2/bin/ctest -j10 + - ../../CMake/bin/ctest -j10 --- kind: pipeline From c73bd8b251b42c1d5941faa3e142d66c7567fa81 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:44:21 +0200 Subject: [PATCH 17/58] :wrench: ignore certificate --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 9fdae5a0a..ebb8615c8 100644 --- a/.drone.yml +++ b/.drone.yml @@ -8,7 +8,7 @@ steps: - name: build image: gcc commands: - - git clone https://github.com/Kitware/CMake.git + - git -c http.sslVerify=false clone https://github.com/Kitware/CMake.git - cd CMake - ./configure - make cmake ctest -j10 From 0c62748b75a9750f7ce0c39e052782d9c41981a7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:46:48 +0200 Subject: [PATCH 18/58] :wrench: change repository --- .drone.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.drone.yml b/.drone.yml index ebb8615c8..c2f32dd32 100644 --- a/.drone.yml +++ b/.drone.yml @@ -8,17 +8,17 @@ steps: - name: build image: gcc commands: - - git -c http.sslVerify=false clone https://github.com/Kitware/CMake.git - - cd CMake + - git -c http.sslVerify=false clone https://gitlab.kitware.com/cmake/cmake.git + - cd cmake - ./configure - make cmake ctest -j10 - cd .. - mkdir build - cd build - - ../CMake/bin/cmake .. -DJSON_FastTests=ON + - ../cmake/bin/cmake .. -DJSON_FastTests=ON - make -j10 - cd test - - ../../CMake/bin/ctest -j10 + - ../../cmake/bin/ctest -j10 --- kind: pipeline From 014724f362b0869e99e01c01cc86cc02198646d3 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:49:42 +0200 Subject: [PATCH 19/58] :alembic: change path --- .drone.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.drone.yml b/.drone.yml index c2f32dd32..f5b0933f2 100644 --- a/.drone.yml +++ b/.drone.yml @@ -8,6 +8,8 @@ steps: - name: build image: gcc commands: + - mkdir cm + - cd cm - git -c http.sslVerify=false clone https://gitlab.kitware.com/cmake/cmake.git - cd cmake - ./configure From a44b29ecf104d2a496fb4da875fca14655e207be Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 13:52:16 +0200 Subject: [PATCH 20/58] :wrench: fix paths --- .drone.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index f5b0933f2..43e515af4 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,10 +17,10 @@ steps: - cd .. - mkdir build - cd build - - ../cmake/bin/cmake .. -DJSON_FastTests=ON + - ../cm/cmake/bin/cmake .. -DJSON_FastTests=ON - make -j10 - cd test - - ../../cmake/bin/ctest -j10 + - ../../cm/cmake/bin/ctest -j10 --- kind: pipeline From e856b507918f2d013089122eaa8bd9c925a9b815 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 9 May 2021 14:22:46 +0200 Subject: [PATCH 21/58] :fire: remove arm build --- .drone.yml | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/.drone.yml b/.drone.yml index 43e515af4..3cdefe4b9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,29 +1,4 @@ kind: pipeline -name: test-on-arm - -platform: - arch: arm - -steps: -- name: build - image: gcc - commands: - - mkdir cm - - cd cm - - git -c http.sslVerify=false clone https://gitlab.kitware.com/cmake/cmake.git - - cd cmake - - ./configure - - make cmake ctest -j10 - - cd .. - - mkdir build - - cd build - - ../cm/cmake/bin/cmake .. -DJSON_FastTests=ON - - make -j10 - - cd test - - ../../cm/cmake/bin/ctest -j10 - ---- -kind: pipeline name: test-on-arm64 platform: From 7cafc5c63f412bf5e2583b8ea71b34996f6283ea Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 10 May 2021 14:23:27 +0200 Subject: [PATCH 22/58] :memo: document Drone CI --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3309190e0..95d64752b 100644 --- a/README.md +++ b/README.md @@ -1227,7 +1227,7 @@ Please note: - Unsupported versions of GCC and Clang are rejected by `#error` directives. This can be switched off by defining `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`. Note that you can expect no support in this case. -The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json), [AppVeyor](https://ci.appveyor.com/project/nlohmann/json), and [GitHub Actions](https://github.com/nlohmann/json/actions): +The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json), [AppVeyor](https://ci.appveyor.com/project/nlohmann/json), [Drone CI](https://cloud.drone.io/nlohmann/json), and [GitHub Actions](https://github.com/nlohmann/json/actions): | Compiler | Operating System | CI Provider | |-------------------------------------------------------------------|--------------------|----------------| @@ -1256,6 +1256,7 @@ The following compilers are currently used in continuous integration at [Travis] | GCC 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) | Ubuntu 20.04.2 LTS | GitHub Actions | | GCC 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04) | Ubuntu 20.04.2 LTS | GitHub Actions | | GCC 11.0.1 20210321 (experimental) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 11.1.0 | Ubuntu (aarch64) | Drone CI | | Clang 3.5.2 (3.5.2-3ubuntu1) | Ubuntu 20.04.2 LTS | GitHub Actions | | Clang 3.6.2 (3.6.2-3ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions | | Clang 3.7.1 (3.7.1-2ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions | From 6d7959e05d2ef67eb841f190c41fbbb3d13073de Mon Sep 17 00:00:00 2001 From: Jason Dsouza <61184127+jasmcaus@users.noreply.github.com> Date: Wed, 12 May 2021 19:25:06 +0530 Subject: [PATCH 23/58] Keep consistent formatting --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 163657559..ee763cc34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ project(nlohmann_json VERSION 3.9.1 LANGUAGES CXX) ## set(MAIN_PROJECT OFF) if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - set(MAIN_PROJECT ON) + set(MAIN_PROJECT ON) endif() ## @@ -113,8 +113,8 @@ endif() # Install a pkg-config file, so other tools can find this. CONFIGURE_FILE( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" ) ## @@ -160,7 +160,7 @@ if(JSON_Install) FILES ${NLOHMANN_NATVIS_FILE} DESTINATION . ) -endif() + endif() # NLOHMANN_ADD_NATVIS export( TARGETS ${NLOHMANN_JSON_TARGET_NAME} NAMESPACE ${PROJECT_NAME}:: @@ -180,4 +180,4 @@ endif() FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" DESTINATION ${NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR} ) -endif() +endif() # JSON_Install From 7935a683f5ac931938ba7532534d19ed2b18cb80 Mon Sep 17 00:00:00 2001 From: offa Date: Wed, 12 May 2021 16:46:32 +0200 Subject: [PATCH 24/58] link to conan package in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 95d64752b..242e09841 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ If you are using the [Meson Build System](https://mesonbuild.com), add this sour The provided meson.build can also be used as an alternative to cmake for installing `nlohmann_json` system-wide in which case a pkg-config file is installed. To use it, simply have your build system require the `nlohmann_json` pkg-config dependency. In Meson, it is preferred to use the [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than using the subproject directly. -If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `nlohmann_json/x.y.z` to your `conanfile`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/conan-io/conan-center-index/issues) if you experience problems with the packages. +If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add [`nlohmann_json/x.y.z`](https://conan.io/center/nlohmann_json) to your `conanfile`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/conan-io/conan-center-index/issues) if you experience problems with the packages. If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the [`nlohmann-json` package](https://spack.readthedocs.io/en/latest/package_list.html#nlohmann-json). Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging. From f118091eaa73f436ec05ad6ec69b750683f12a3b Mon Sep 17 00:00:00 2001 From: Jason Dsouza <61184127+jasmcaus@users.noreply.github.com> Date: Sat, 15 May 2021 23:39:15 +0530 Subject: [PATCH 25/58] Update CMakeLists.txt --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee763cc34..3c629ee6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,7 +160,7 @@ if(JSON_Install) FILES ${NLOHMANN_NATVIS_FILE} DESTINATION . ) - endif() # NLOHMANN_ADD_NATVIS + endif() export( TARGETS ${NLOHMANN_JSON_TARGET_NAME} NAMESPACE ${PROJECT_NAME}:: @@ -180,4 +180,4 @@ if(JSON_Install) FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" DESTINATION ${NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR} ) -endif() # JSON_Install +endif() From 9a599ae63a5b319a07fc1cca9871694fe687cef6 Mon Sep 17 00:00:00 2001 From: TotalCaesar659 <14265316+TotalCaesar659@users.noreply.github.com> Date: Fri, 28 May 2021 00:53:17 +0300 Subject: [PATCH 26/58] Update URLs to HTTPS --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 242e09841..127b8d205 100644 --- a/README.md +++ b/README.md @@ -1126,7 +1126,7 @@ Other Important points: ### Binary formats (BSON, CBOR, MessagePack, and UBJSON) -Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [BSON](http://bsonspec.org) (Binary JSON), [CBOR](https://cbor.io) (Concise Binary Object Representation), [MessagePack](https://msgpack.org), and [UBJSON](http://ubjson.org) (Universal Binary JSON Specification) to efficiently encode JSON values to byte vectors and to decode such vectors. +Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [BSON](https://bsonspec.org) (Binary JSON), [CBOR](https://cbor.io) (Concise Binary Object Representation), [MessagePack](https://msgpack.org), and [UBJSON](https://ubjson.org) (Universal Binary JSON Specification) to efficiently encode JSON values to byte vectors and to decode such vectors. ```cpp // create a JSON value @@ -1282,9 +1282,9 @@ The following compilers are currently used in continuous integration at [Travis] ## License - + -The class is licensed under the [MIT License](http://opensource.org/licenses/MIT): +The class is licensed under the [MIT License](https://opensource.org/licenses/MIT): Copyright © 2013-2021 [Niels Lohmann](https://nlohmann.me) @@ -1296,9 +1296,9 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I * * * -The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](https://bjoern.hoehrmann.de/) +The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](https://bjoern.hoehrmann.de/) -The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/) +The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/) The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/). @@ -1574,7 +1574,7 @@ The library itself consists of a single header file licensed under the MIT licen - [**libFuzzer**](https://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz - [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library ([project repository](https://github.com/google/oss-fuzz/tree/master/projects/json)) - [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments. -- [**send_to_wandbox**](https://github.com/nlohmann/json/blob/develop/doc/scripts/send_to_wandbox.py) to send code examples to [Wandbox](http://melpon.org/wandbox) +- [**send_to_wandbox**](https://github.com/nlohmann/json/blob/develop/doc/scripts/send_to_wandbox.py) to send code examples to [Wandbox](https://wandbox.org) - [**Travis**](https://travis-ci.org) for [continuous integration](https://travis-ci.org/nlohmann/json) on Linux and macOS - [**Valgrind**](https://valgrind.org) to check for correct memory management - [**Wandbox**](https://wandbox.org) for [online examples](https://wandbox.org/permlink/3lCHrFUZANONKv7a) From 311730bc3dbf09b4b739ea682fe406eb4f5499b5 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 28 May 2021 22:23:50 +0200 Subject: [PATCH 27/58] :construction_worker: add C++ standards to macOS matrix #2491 --- .github/workflows/macos.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 42e9098b5..22d81a05f 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -13,13 +13,14 @@ jobs: strategy: matrix: xcode: [12.4, 12.3, 12.2, 12.1.1, 12.1, 12, 11.7, 11.6, 11.5, 11.4.1, 11.3.1, 11.2.1, 10.3] + standard: [11, 14, 17, 20] env: DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer steps: - uses: actions/checkout@v2 - name: cmake - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_STANDARD={{ matrix.standard }} -DCMAKE_CXX_STANDARD_REQUIRED=ON - name: build run: cmake --build build --parallel 10 - name: test From 9f5ee3f1453bc2921bee720c99868ebfcdace4cd Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 28 May 2021 22:27:46 +0200 Subject: [PATCH 28/58] :construction_worker: fix syntax --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 22d81a05f..ecc51d6f5 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: cmake - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_STANDARD={{ matrix.standard }} -DCMAKE_CXX_STANDARD_REQUIRED=ON + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DCMAKE_CXX_STANDARD_REQUIRED=ON - name: build run: cmake --build build --parallel 10 - name: test From 2b685c744bacd31cfd286a05de5d512bd142a2e9 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 29 May 2021 13:10:28 +0200 Subject: [PATCH 29/58] :construction_worker: reduce load --- .github/workflows/macos.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index ecc51d6f5..13d1192fd 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -13,10 +13,26 @@ jobs: strategy: matrix: xcode: [12.4, 12.3, 12.2, 12.1.1, 12.1, 12, 11.7, 11.6, 11.5, 11.4.1, 11.3.1, 11.2.1, 10.3] - standard: [11, 14, 17, 20] env: DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer + steps: + - uses: actions/checkout@v2 + - name: cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON + - name: build + run: cmake --build build --parallel 10 + - name: test + run: cd build ; ctest -j 10 --output-on-failure + + xcode_standards: + runs-on: macos-10.15 + strategy: + matrix: + standard: [11, 14, 17, 20] + env: + DEVELOPER_DIR: /Applications/Xcode_12.4.app/Contents/Developer + steps: - uses: actions/checkout@v2 - name: cmake From 30e52eb0464bb7654da7393bc2804b7a15662d24 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 30 May 2021 13:28:58 +0200 Subject: [PATCH 30/58] :construction_worker: execute all tests --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 13d1192fd..bf9549fcf 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -36,7 +36,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: cmake - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DCMAKE_CXX_STANDARD_REQUIRED=ON + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DCMAKE_CXX_STANDARD_REQUIRED=ON - name: build run: cmake --build build --parallel 10 - name: test From ae9bbbc9412656e9d71be0862ba919dccf0b21ec Mon Sep 17 00:00:00 2001 From: David Pfahler Date: Mon, 31 May 2021 14:26:45 +0200 Subject: [PATCH 31/58] include io only if JSON_NO_IO is not set for #2728 --- include/nlohmann/detail/input/input_adapters.hpp | 7 +++++-- include/nlohmann/detail/output/output_adapters.hpp | 8 ++++++-- include/nlohmann/json.hpp | 6 ++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index 9bb4a2b48..fd9a3ab88 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -2,9 +2,7 @@ #include // array #include // size_t -#include //FILE * #include // strlen -#include // istream #include // begin, end, iterator_traits, random_access_iterator_tag, distance, next #include // shared_ptr, make_shared, addressof #include // accumulate @@ -12,6 +10,11 @@ #include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer #include // pair, declval +#ifndef JSON_NO_IO + #include //FILE * + #include // istream +#endif // JSON_NO_IO + #include #include diff --git a/include/nlohmann/detail/output/output_adapters.hpp b/include/nlohmann/detail/output/output_adapters.hpp index 46c82e9fd..d192da4e5 100644 --- a/include/nlohmann/detail/output/output_adapters.hpp +++ b/include/nlohmann/detail/output/output_adapters.hpp @@ -2,12 +2,16 @@ #include // copy #include // size_t -#include // streamsize #include // back_inserter #include // shared_ptr, make_shared -#include // basic_ostream #include // basic_string #include // vector + +#ifndef JSON_NO_IO + #include // streamsize + #include // basic_ostream +#endif // JSON_NO_IO + #include namespace nlohmann diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index a783e3d59..70e263bf4 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -38,7 +38,9 @@ SOFTWARE. #include // nullptr_t, ptrdiff_t, size_t #include // hash, less #include // initializer_list -#include // istream, ostream +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO #include // random_access_iterator_tag #include // unique_ptr #include // accumulate @@ -6882,7 +6884,7 @@ class basic_json parser(detail::input_adapter(i)).parse(false, j); return i; } -#endif // JSON_NO_IO +#endif // JSON_NO_IO /// @} /////////////////////////// From e939b59683281cc4c061597868e78786a9812482 Mon Sep 17 00:00:00 2001 From: David Pfahler Date: Mon, 31 May 2021 14:27:23 +0200 Subject: [PATCH 32/58] fixed amalgation file for #2728 --- single_include/nlohmann/json.hpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 752f8d8af..3ccab3001 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -38,7 +38,9 @@ SOFTWARE. #include // nullptr_t, ptrdiff_t, size_t #include // hash, less #include // initializer_list -#include // istream, ostream +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO #include // random_access_iterator_tag #include // unique_ptr #include // accumulate @@ -4721,9 +4723,7 @@ std::size_t hash(const BasicJsonType& j) #include // array #include // size_t -#include //FILE * #include // strlen -#include // istream #include // begin, end, iterator_traits, random_access_iterator_tag, distance, next #include // shared_ptr, make_shared, addressof #include // accumulate @@ -4731,6 +4731,11 @@ std::size_t hash(const BasicJsonType& j) #include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer #include // pair, declval +#ifndef JSON_NO_IO + #include //FILE * + #include // istream +#endif // JSON_NO_IO + // #include // #include @@ -12619,12 +12624,16 @@ class json_ref #include // copy #include // size_t -#include // streamsize #include // back_inserter #include // shared_ptr, make_shared -#include // basic_ostream #include // basic_string #include // vector + +#ifndef JSON_NO_IO + #include // streamsize + #include // basic_ostream +#endif // JSON_NO_IO + // #include @@ -23378,7 +23387,7 @@ class basic_json parser(detail::input_adapter(i)).parse(false, j); return i; } -#endif // JSON_NO_IO +#endif // JSON_NO_IO /// @} /////////////////////////// From 032f32ebe43cb44ebbebb4540769c9b36353f3a1 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 13 Jun 2021 14:04:20 +0200 Subject: [PATCH 33/58] :construction_worker: add Clang 12 --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index c9f4e3b9b..c696cb9dd 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -98,7 +98,7 @@ jobs: runs-on: windows-latest strategy: matrix: - version: [10, 11] + version: [10, 11, 12] steps: - uses: actions/checkout@v2 From 802895b48303efb066c5b6b53a65166824c984b2 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 13 Jun 2021 14:14:10 +0200 Subject: [PATCH 34/58] :construction_worker: remove Clang 10 --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index c696cb9dd..fad51b632 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -98,7 +98,7 @@ jobs: runs-on: windows-latest strategy: matrix: - version: [10, 11, 12] + version: [11, 12] steps: - uses: actions/checkout@v2 From 9710108d6aa8ec3b17564b1bc62ea904e570b3d9 Mon Sep 17 00:00:00 2001 From: justanotheranonymoususer Date: Thu, 17 Jun 2021 21:39:29 +0300 Subject: [PATCH 35/58] Consistency with `using` in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 127b8d205..1c11617b2 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Thanks everyone! #include // for convenience -using json = nlohmann::json; +using nlohmann::json; ``` to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang). From c3d7fcb76ced6746e67fa9a63bb995468b090134 Mon Sep 17 00:00:00 2001 From: justanotheranonymoususer Date: Fri, 18 Jun 2021 11:04:53 +0300 Subject: [PATCH 36/58] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1c11617b2..96e7a22e1 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Thanks everyone! #include // for convenience -using nlohmann::json; +using json = nlohmann::json; ``` to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang). @@ -870,7 +870,7 @@ assert(p == p2); To make this work with one of your types, you only need to provide two functions: ```cpp -using nlohmann::json; +using json = nlohmann::json; namespace ns { void to_json(json& j, const person& p) { From e970f310668bd19d74c3596b8eb3cfa2daaa90b2 Mon Sep 17 00:00:00 2001 From: justanotheranonymoususer Date: Fri, 18 Jun 2021 12:44:27 +0300 Subject: [PATCH 37/58] Update arbitrary_types.md --- doc/mkdocs/docs/features/arbitrary_types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/mkdocs/docs/features/arbitrary_types.md b/doc/mkdocs/docs/features/arbitrary_types.md index 23913bba2..423419130 100644 --- a/doc/mkdocs/docs/features/arbitrary_types.md +++ b/doc/mkdocs/docs/features/arbitrary_types.md @@ -54,7 +54,7 @@ assert(p == p2); To make this work with one of your types, you only need to provide two functions: ```cpp -using nlohmann::json; +using json = nlohmann::json; namespace ns { void to_json(json& j, const person& p) { From b7e493e98ad8351e5e9d0d21550e350d04fa34e3 Mon Sep 17 00:00:00 2001 From: Rafail Giavrimis <47496212+grafail@users.noreply.github.com> Date: Tue, 1 Jun 2021 13:17:53 +0100 Subject: [PATCH 38/58] Specified git branch for google benchmark fetch The default branch was renamed from "master" to "main", which breaks the cloning process. --- benchmarks/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index ee4db1912..1243f54ea 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -11,6 +11,7 @@ include(FetchContent) FetchContent_Declare( benchmark GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG origin/main GIT_SHALLOW TRUE ) From 71fd9bd954e96643e21c74bb7085c1e19873255b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 6 Jul 2021 08:46:17 +0200 Subject: [PATCH 39/58] :memo: fix documentation (#2845) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96e7a22e1..eabf1302a 100644 --- a/README.md +++ b/README.md @@ -1650,7 +1650,7 @@ $ ctest --output-on-failure Note that during the `ctest` stage, several JSON test files are downloaded from an [external repository](https://github.com/nlohmann/json_test_data). If policies forbid downloading artifacts during testing, you can download the files yourself and pass the directory with the test files via `-DJSON_TestDataDirectory=path` to CMake. Then, no Internet connectivity is required. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information. -In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure`. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information. +In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure` will fail. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information. Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. From 5c8d0af5cea8614b1b48ad382550748651154582 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 10 Jul 2021 12:50:59 +0200 Subject: [PATCH 40/58] :memo: add comment for handling of negative zeros #2854 --- doc/mkdocs/docs/features/types/number_handling.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/mkdocs/docs/features/types/number_handling.md b/doc/mkdocs/docs/features/types/number_handling.md index 4224c155b..aa8df7ad8 100644 --- a/doc/mkdocs/docs/features/types/number_handling.md +++ b/doc/mkdocs/docs/features/types/number_handling.md @@ -96,6 +96,21 @@ This is the same behavior as the code `#!c double x = 3.141592653589793238462643 - All integers outside the range $[-2^{63}, 2^{64}-1]$, as well as floating-point numbers are stored as `double`. This also concurs with the specification above. +### Zeros + +The JSON number grammar allows for different ways to express zero, and this library will store zeros differently: + +| Literal | Stored value and type | Serialization | +| ------- | --------------------- | ------------- | +| `0` | `#!c std::uint64_t(0)` | `0` | +| `-0` | `#!c std::int64_t(0)` | `0` | +| `0.0` | `#!c double(0.0)` | `0.0` | +| `-0.0` | `#!c double(-0.0)` | `-0.0` | +| `0E0` | `#!c double(0.0)` | `0.0` | +| `-0E0` | `#!c double(-0.0)` | `-0.0` | + +That is, `-0` is stored as a signed integer, but the serialization does not reproduce the `-`. + ### Number serialization - Integer numbers are serialized as is; that is, no scientific notation is used. From a82f66beed60cab657a909be7eb9192dbcb3982f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 10 Jul 2021 12:51:18 +0200 Subject: [PATCH 41/58] :memo: document JSON_NO_IO macro #2842 --- doc/mkdocs/docs/features/macros.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/mkdocs/docs/features/macros.md b/doc/mkdocs/docs/features/macros.md index ee401c5dc..d008393f7 100644 --- a/doc/mkdocs/docs/features/macros.md +++ b/doc/mkdocs/docs/features/macros.md @@ -32,6 +32,10 @@ When defining `JSON_NOEXCEPTION`, `#!cpp try` is replaced by `#!cpp if (true)`, The same effect is achieved by setting the compiler flag `-fno-exceptions`. +## `JSON_NO_IO` + +When defined, headers ``, ``, ``, ``, and `` are not included and parse functions relying on these headers are excluded. This is relevant for environment where these I/O functions are disallowed for security reasons (e.g., Intel Software Guard Extensions (SGX)). + ## `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK` When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used. From 7442c24662dd97fbbf12077b1dfa1aa0da8258ea Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 10 Jul 2021 13:44:13 +0200 Subject: [PATCH 42/58] :rotating_light: suppress missingReturn warnings --- cmake/ci.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/ci.cmake b/cmake/ci.cmake index d7d94b2bf..e2d175d41 100644 --- a/cmake/ci.cmake +++ b/cmake/ci.cmake @@ -560,7 +560,7 @@ add_custom_target(ci_clang_analyze ############################################################################### add_custom_target(ci_cppcheck - COMMAND ${CPPCHECK_TOOL} --enable=warning --inline-suppr --inconclusive --force --std=c++11 ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp --error-exitcode=1 + COMMAND ${CPPCHECK_TOOL} --enable=warning --suppress=missingReturn --inline-suppr --inconclusive --force --std=c++11 ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp --error-exitcode=1 COMMENT "Check code with Cppcheck" ) From 249688037fab6144bb0279aeed687efcde4b3baa Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 11 Jul 2021 09:33:43 +0200 Subject: [PATCH 43/58] :alembic: fix coverage --- cmake/ci.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/ci.cmake b/cmake/ci.cmake index e2d175d41..84cbfe4c2 100644 --- a/cmake/ci.cmake +++ b/cmake/ci.cmake @@ -467,7 +467,7 @@ add_custom_target(ci_test_diagnostics ############################################################################### add_custom_target(ci_test_coverage - COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND} + COMMAND CXX=g++ ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="--coverage;-fprofile-arcs;-ftest-coverage" -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage @@ -475,7 +475,7 @@ add_custom_target(ci_test_coverage COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure COMMAND ${LCOV_TOOL} --directory . --capture --output-file json.info --rc lcov_branch_coverage=1 - COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --gcov-tool ${GCOV_TOOL} --rc lcov_branch_coverage=1 + COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --rc lcov_branch_coverage=1 COMMAND ${CMAKE_SOURCE_DIR}/test/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.filtered.noexcept From d40e98ecef776b909af4d91ffa266a966290e73f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 12 Jul 2021 13:38:28 +0200 Subject: [PATCH 44/58] :bug: fix assertion failure #2838 --- include/nlohmann/json.hpp | 61 ++++++++++++++++++++++++++------ single_include/nlohmann/json.hpp | 61 ++++++++++++++++++++++++++------ test/src/unit-diagnostics.cpp | 57 +++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 22 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index c55bdf54b..0622d1a9c 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -5371,8 +5371,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array (move semantics) + const auto capacity = m_value.array->capacity(); m_value.array->push_back(std::move(val)); - set_parent(m_value.array->back()); + if (capacity == m_value.array->capacity()) + { + // capacity has not changed: updating parent of last element is sufficient + set_parent(m_value.array->back()); + } + else + { + // capacity has changed: update all elements' parents + set_parents(); + } // if val is moved from, basic_json move constructor marks it null so we do not call the destructor } @@ -5407,7 +5417,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array + const auto capacity = m_value.array->capacity(); m_value.array->push_back(val); + if (capacity == m_value.array->capacity()) + { + // capacity has not changed: updating parent of last element is sufficient + set_parent(m_value.array->back()); + } + else + { + // capacity has changed: update all elements' parents + set_parents(); + } set_parent(m_value.array->back()); } @@ -5562,12 +5583,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array (perfect forwarding) -#ifdef JSON_HAS_CPP_17 - return set_parent(m_value.array->emplace_back(std::forward(args)...)); -#else + const auto capacity = m_value.array->capacity(); m_value.array->emplace_back(std::forward(args)...); - return set_parent(m_value.array->back()); -#endif + + if (capacity == m_value.array->capacity()) + { + // capacity has not changed: updating parent of last element is sufficient + return set_parent(m_value.array->back()); + } + + // capacity has changed: update all elements' parents + set_parents(); + return m_value.array->back(); } /*! @@ -5630,12 +5657,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @note: This uses std::distance to support GCC 4.8, /// see https://github.com/nlohmann/json/pull/1257 template - iterator insert_iterator(const_iterator pos, Args&& ... args) + iterator insert_iterator(const_iterator pos, typename iterator::difference_type cnt, Args&& ... args) { iterator result(this); JSON_ASSERT(m_value.array != nullptr); auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + const auto capacity = m_value.array->capacity(); m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); result.m_it.array_iterator = m_value.array->begin() + insert_pos; @@ -5643,6 +5671,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); // but the return value of insert is missing in GCC 4.8, so it is written this way instead. + if (capacity == m_value.array->capacity()) + { + // capacity has not changed: updating parent of inserted elements is sufficient + set_parents(result, cnt); + } + else + { + // capacity has changed: update all elements' parents + set_parents(); + } + return result; } @@ -5680,7 +5719,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return set_parents(insert_iterator(pos, val), static_cast(1)); + return insert_iterator(pos, static_cast(1), val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); @@ -5731,7 +5770,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return set_parents(insert_iterator(pos, cnt, val), static_cast(cnt)); + return insert_iterator(pos, static_cast(cnt), cnt, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); @@ -5793,7 +5832,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return set_parents(insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator), std::distance(first, last)); + return insert_iterator(pos, std::distance(first, last), first.m_it.array_iterator, last.m_it.array_iterator); } /*! @@ -5835,7 +5874,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return set_parents(insert_iterator(pos, ilist.begin(), ilist.end()), static_cast(ilist.size())); + return insert_iterator(pos, static_cast(ilist.size()), ilist.begin(), ilist.end()); } /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index cbe69ef47..999d136aa 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -22406,8 +22406,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array (move semantics) + const auto capacity = m_value.array->capacity(); m_value.array->push_back(std::move(val)); - set_parent(m_value.array->back()); + if (capacity == m_value.array->capacity()) + { + // capacity has not changed: updating parent of last element is sufficient + set_parent(m_value.array->back()); + } + else + { + // capacity has changed: update all elements' parents + set_parents(); + } // if val is moved from, basic_json move constructor marks it null so we do not call the destructor } @@ -22442,7 +22452,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array + const auto capacity = m_value.array->capacity(); m_value.array->push_back(val); + if (capacity == m_value.array->capacity()) + { + // capacity has not changed: updating parent of last element is sufficient + set_parent(m_value.array->back()); + } + else + { + // capacity has changed: update all elements' parents + set_parents(); + } set_parent(m_value.array->back()); } @@ -22597,12 +22618,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array (perfect forwarding) -#ifdef JSON_HAS_CPP_17 - return set_parent(m_value.array->emplace_back(std::forward(args)...)); -#else + const auto capacity = m_value.array->capacity(); m_value.array->emplace_back(std::forward(args)...); - return set_parent(m_value.array->back()); -#endif + + if (capacity == m_value.array->capacity()) + { + // capacity has not changed: updating parent of last element is sufficient + return set_parent(m_value.array->back()); + } + + // capacity has changed: update all elements' parents + set_parents(); + return m_value.array->back(); } /*! @@ -22665,12 +22692,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @note: This uses std::distance to support GCC 4.8, /// see https://github.com/nlohmann/json/pull/1257 template - iterator insert_iterator(const_iterator pos, Args&& ... args) + iterator insert_iterator(const_iterator pos, typename iterator::difference_type cnt, Args&& ... args) { iterator result(this); JSON_ASSERT(m_value.array != nullptr); auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + const auto capacity = m_value.array->capacity(); m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); result.m_it.array_iterator = m_value.array->begin() + insert_pos; @@ -22678,6 +22706,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); // but the return value of insert is missing in GCC 4.8, so it is written this way instead. + if (capacity == m_value.array->capacity()) + { + // capacity has not changed: updating parent of inserted elements is sufficient + set_parents(result, cnt); + } + else + { + // capacity has changed: update all elements' parents + set_parents(); + } + return result; } @@ -22715,7 +22754,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return set_parents(insert_iterator(pos, val), static_cast(1)); + return insert_iterator(pos, static_cast(1), val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); @@ -22766,7 +22805,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return set_parents(insert_iterator(pos, cnt, val), static_cast(cnt)); + return insert_iterator(pos, static_cast(cnt), cnt, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); @@ -22828,7 +22867,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return set_parents(insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator), std::distance(first, last)); + return insert_iterator(pos, std::distance(first, last), first.m_it.array_iterator, last.m_it.array_iterator); } /*! @@ -22870,7 +22909,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return set_parents(insert_iterator(pos, ilist.begin(), ilist.end()), static_cast(ilist.size())); + return insert_iterator(pos, static_cast(ilist.size()), ilist.begin(), ilist.end()); } /*! diff --git a/test/src/unit-diagnostics.cpp b/test/src/unit-diagnostics.cpp index 21ced33b1..c0b5a6476 100644 --- a/test/src/unit-diagnostics.cpp +++ b/test/src/unit-diagnostics.cpp @@ -109,4 +109,61 @@ TEST_CASE("Better diagnostics") j["/foo"] = {1, 2, 3}; CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error); } + + SECTION("Regression test for https://github.com/nlohmann/json/issues/2838") + { + // void push_back(basic_json&& val) + { + json j_arr = json::array(); + j_arr.push_back(json::object()); + j_arr.push_back(json::object()); + json j_obj = json::object(); + j_obj["key"] = j_arr; + } + + // void push_back(const basic_json& val) + { + json j_arr = json::array(); + auto object = json::object(); + j_arr.push_back(object); + j_arr.push_back(object); + json j_obj = json::object(); + j_obj["key"] = j_arr; + } + + // reference emplace_back(Args&& ... args) + { + json j_arr = json::array(); + j_arr.emplace_back(json::object()); + j_arr.emplace_back(json::object()); + json j_obj = json::object(); + j_obj["key"] = j_arr; + } + + // iterator insert(const_iterator pos, const basic_json& val) + { + json j_arr = json::array(); + j_arr.insert(j_arr.begin(), json::object()); + j_arr.insert(j_arr.begin(), json::object()); + json j_obj = json::object(); + j_obj["key"] = j_arr; + } + + // iterator insert(const_iterator pos, size_type cnt, const basic_json& val) + { + json j_arr = json::array(); + j_arr.insert(j_arr.begin(), 2, json::object()); + json j_obj = json::object(); + j_obj["key"] = j_arr; + } + + // iterator insert(const_iterator pos, const_iterator first, const_iterator last) + { + json j_arr = json::array(); + json j_objects = {json::object(), json::object()}; + j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end()); + json j_obj = json::object(); + j_obj["key"] = j_arr; + } + } } From b0730f29cf2376a27591197eb793410370fdd32b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 12 Jul 2021 15:24:06 +0200 Subject: [PATCH 45/58] :bug: fix logics --- include/nlohmann/json.hpp | 23 ++++++----------------- single_include/nlohmann/json.hpp | 23 ++++++----------------- test/src/unit-diagnostics.cpp | 8 ++++++++ 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 0622d1a9c..710c5a5cf 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -5657,13 +5657,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @note: This uses std::distance to support GCC 4.8, /// see https://github.com/nlohmann/json/pull/1257 template - iterator insert_iterator(const_iterator pos, typename iterator::difference_type cnt, Args&& ... args) + iterator insert_iterator(const_iterator pos, Args&& ... args) { iterator result(this); JSON_ASSERT(m_value.array != nullptr); auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); - const auto capacity = m_value.array->capacity(); m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); result.m_it.array_iterator = m_value.array->begin() + insert_pos; @@ -5671,17 +5670,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); // but the return value of insert is missing in GCC 4.8, so it is written this way instead. - if (capacity == m_value.array->capacity()) - { - // capacity has not changed: updating parent of inserted elements is sufficient - set_parents(result, cnt); - } - else - { - // capacity has changed: update all elements' parents - set_parents(); - } - + set_parents(); return result; } @@ -5719,7 +5708,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return insert_iterator(pos, static_cast(1), val); + return insert_iterator(pos, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); @@ -5770,7 +5759,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return insert_iterator(pos, static_cast(cnt), cnt, val); + return insert_iterator(pos, cnt, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); @@ -5832,7 +5821,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return insert_iterator(pos, std::distance(first, last), first.m_it.array_iterator, last.m_it.array_iterator); + return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); } /*! @@ -5874,7 +5863,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return insert_iterator(pos, static_cast(ilist.size()), ilist.begin(), ilist.end()); + return insert_iterator(pos, ilist.begin(), ilist.end()); } /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 999d136aa..3700505c9 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -22692,13 +22692,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @note: This uses std::distance to support GCC 4.8, /// see https://github.com/nlohmann/json/pull/1257 template - iterator insert_iterator(const_iterator pos, typename iterator::difference_type cnt, Args&& ... args) + iterator insert_iterator(const_iterator pos, Args&& ... args) { iterator result(this); JSON_ASSERT(m_value.array != nullptr); auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); - const auto capacity = m_value.array->capacity(); m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); result.m_it.array_iterator = m_value.array->begin() + insert_pos; @@ -22706,17 +22705,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); // but the return value of insert is missing in GCC 4.8, so it is written this way instead. - if (capacity == m_value.array->capacity()) - { - // capacity has not changed: updating parent of inserted elements is sufficient - set_parents(result, cnt); - } - else - { - // capacity has changed: update all elements' parents - set_parents(); - } - + set_parents(); return result; } @@ -22754,7 +22743,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return insert_iterator(pos, static_cast(1), val); + return insert_iterator(pos, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); @@ -22805,7 +22794,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return insert_iterator(pos, static_cast(cnt), cnt, val); + return insert_iterator(pos, cnt, val); } JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); @@ -22867,7 +22856,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return insert_iterator(pos, std::distance(first, last), first.m_it.array_iterator, last.m_it.array_iterator); + return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); } /*! @@ -22909,7 +22898,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // insert to array and return iterator - return insert_iterator(pos, static_cast(ilist.size()), ilist.begin(), ilist.end()); + return insert_iterator(pos, ilist.begin(), ilist.end()); } /*! diff --git a/test/src/unit-diagnostics.cpp b/test/src/unit-diagnostics.cpp index c0b5a6476..ebbe64f38 100644 --- a/test/src/unit-diagnostics.cpp +++ b/test/src/unit-diagnostics.cpp @@ -117,6 +117,8 @@ TEST_CASE("Better diagnostics") json j_arr = json::array(); j_arr.push_back(json::object()); j_arr.push_back(json::object()); + j_arr.push_back(json::object()); + j_arr.push_back(json::object()); json j_obj = json::object(); j_obj["key"] = j_arr; } @@ -127,6 +129,8 @@ TEST_CASE("Better diagnostics") auto object = json::object(); j_arr.push_back(object); j_arr.push_back(object); + j_arr.push_back(object); + j_arr.push_back(object); json j_obj = json::object(); j_obj["key"] = j_arr; } @@ -136,6 +140,8 @@ TEST_CASE("Better diagnostics") json j_arr = json::array(); j_arr.emplace_back(json::object()); j_arr.emplace_back(json::object()); + j_arr.emplace_back(json::object()); + j_arr.emplace_back(json::object()); json j_obj = json::object(); j_obj["key"] = j_arr; } @@ -145,6 +151,8 @@ TEST_CASE("Better diagnostics") json j_arr = json::array(); j_arr.insert(j_arr.begin(), json::object()); j_arr.insert(j_arr.begin(), json::object()); + j_arr.insert(j_arr.begin(), json::object()); + j_arr.insert(j_arr.begin(), json::object()); json j_obj = json::object(); j_obj["key"] = j_arr; } From bc7e8faa4f1f463ef97b2c1491b1f8886bec154b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 12 Jul 2021 19:21:07 +0200 Subject: [PATCH 46/58] :fire: remove duplicated line --- include/nlohmann/json.hpp | 1 - single_include/nlohmann/json.hpp | 1 - 2 files changed, 2 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 710c5a5cf..ae77747b5 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -5429,7 +5429,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // capacity has changed: update all elements' parents set_parents(); } - set_parent(m_value.array->back()); } /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 3700505c9..2500eb9cb 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -22464,7 +22464,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // capacity has changed: update all elements' parents set_parents(); } - set_parent(m_value.array->back()); } /*! From 3bb9467073f366bfb2b46c9c6a0c1fe11219da60 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 13 Jul 2021 15:27:27 +0200 Subject: [PATCH 47/58] :recycle: move capacity check to set_parent function --- include/nlohmann/json.hpp | 53 ++++++++++++-------------------- single_include/nlohmann/json.hpp | 53 ++++++++++++-------------------- 2 files changed, 38 insertions(+), 68 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index ae77747b5..d18f082b4 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1304,9 +1304,21 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return it; } - reference set_parent(reference j) + reference set_parent(reference j, std::size_t old_capacity = -1) { #if JSON_DIAGNOSTICS + if (old_capacity != -1) + { + // see https://github.com/nlohmann/json/issues/2838 + JSON_ASSERT(type() == value_t::array); + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + return j; + } + } + j.m_parent = this; #else static_cast(j); @@ -5371,18 +5383,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array (move semantics) - const auto capacity = m_value.array->capacity(); + const auto old_capacity = m_value.array->capacity(); m_value.array->push_back(std::move(val)); - if (capacity == m_value.array->capacity()) - { - // capacity has not changed: updating parent of last element is sufficient - set_parent(m_value.array->back()); - } - else - { - // capacity has changed: update all elements' parents - set_parents(); - } + set_parent(m_value.array->back(), old_capacity); // if val is moved from, basic_json move constructor marks it null so we do not call the destructor } @@ -5417,18 +5420,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array - const auto capacity = m_value.array->capacity(); + const auto old_capacity = m_value.array->capacity(); m_value.array->push_back(val); - if (capacity == m_value.array->capacity()) - { - // capacity has not changed: updating parent of last element is sufficient - set_parent(m_value.array->back()); - } - else - { - // capacity has changed: update all elements' parents - set_parents(); - } + set_parent(m_value.array->back(), old_capacity); } /*! @@ -5582,18 +5576,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array (perfect forwarding) - const auto capacity = m_value.array->capacity(); + const auto old_capacity = m_value.array->capacity(); m_value.array->emplace_back(std::forward(args)...); - - if (capacity == m_value.array->capacity()) - { - // capacity has not changed: updating parent of last element is sufficient - return set_parent(m_value.array->back()); - } - - // capacity has changed: update all elements' parents - set_parents(); - return m_value.array->back(); + return set_parent(m_value.array->back(), old_capacity); } /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 2500eb9cb..3b5a7a75d 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -18339,9 +18339,21 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return it; } - reference set_parent(reference j) + reference set_parent(reference j, std::size_t old_capacity = -1) { #if JSON_DIAGNOSTICS + if (old_capacity != -1) + { + // see https://github.com/nlohmann/json/issues/2838 + JSON_ASSERT(type() == value_t::array); + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + return j; + } + } + j.m_parent = this; #else static_cast(j); @@ -22406,18 +22418,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array (move semantics) - const auto capacity = m_value.array->capacity(); + const auto old_capacity = m_value.array->capacity(); m_value.array->push_back(std::move(val)); - if (capacity == m_value.array->capacity()) - { - // capacity has not changed: updating parent of last element is sufficient - set_parent(m_value.array->back()); - } - else - { - // capacity has changed: update all elements' parents - set_parents(); - } + set_parent(m_value.array->back(), old_capacity); // if val is moved from, basic_json move constructor marks it null so we do not call the destructor } @@ -22452,18 +22455,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array - const auto capacity = m_value.array->capacity(); + const auto old_capacity = m_value.array->capacity(); m_value.array->push_back(val); - if (capacity == m_value.array->capacity()) - { - // capacity has not changed: updating parent of last element is sufficient - set_parent(m_value.array->back()); - } - else - { - // capacity has changed: update all elements' parents - set_parents(); - } + set_parent(m_value.array->back(), old_capacity); } /*! @@ -22617,18 +22611,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // add element to array (perfect forwarding) - const auto capacity = m_value.array->capacity(); + const auto old_capacity = m_value.array->capacity(); m_value.array->emplace_back(std::forward(args)...); - - if (capacity == m_value.array->capacity()) - { - // capacity has not changed: updating parent of last element is sufficient - return set_parent(m_value.array->back()); - } - - // capacity has changed: update all elements' parents - set_parents(); - return m_value.array->back(); + return set_parent(m_value.array->back(), old_capacity); } /*! From a711e1f5a721b12987b5748da37d3b8c2992764b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 13 Jul 2021 15:37:57 +0200 Subject: [PATCH 48/58] :rotating_light: fix warnings --- include/nlohmann/json.hpp | 5 +++-- single_include/nlohmann/json.hpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index d18f082b4..a337c1c69 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1304,10 +1304,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return it; } - reference set_parent(reference j, std::size_t old_capacity = -1) + reference set_parent(reference j, std::size_t old_capacity = std::size_t(-1)) { #if JSON_DIAGNOSTICS - if (old_capacity != -1) + if (old_capacity != std::size_t(-1)) { // see https://github.com/nlohmann/json/issues/2838 JSON_ASSERT(type() == value_t::array); @@ -1322,6 +1322,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec j.m_parent = this; #else static_cast(j); + static_cast(old_capacity); #endif return j; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 3b5a7a75d..429964dd7 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -18339,10 +18339,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return it; } - reference set_parent(reference j, std::size_t old_capacity = -1) + reference set_parent(reference j, std::size_t old_capacity = std::size_t(-1)) { #if JSON_DIAGNOSTICS - if (old_capacity != -1) + if (old_capacity != std::size_t(-1)) { // see https://github.com/nlohmann/json/issues/2838 JSON_ASSERT(type() == value_t::array); @@ -18357,6 +18357,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec j.m_parent = this; #else static_cast(j); + static_cast(old_capacity); #endif return j; } From db980739306d5dfade50a19f3a4a05702b450053 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 09:02:24 +0200 Subject: [PATCH 49/58] :white_check_mark: add regression test --- test/src/unit-regression2.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/src/unit-regression2.cpp b/test/src/unit-regression2.cpp index 4d48e4765..ef9d7ee54 100644 --- a/test/src/unit-regression2.cpp +++ b/test/src/unit-regression2.cpp @@ -594,4 +594,30 @@ TEST_CASE("regression tests 2") } } } + + SECTION("issue #2865 - ASAN detects memory leaks") + { + // the code below is expected to not leak memory + { + nlohmann::json o; + std::string s = "bar"; + + nlohmann::to_json(o["foo"], s); + + nlohmann::json p = o; + + // call to_json with a non-null JSON value + nlohmann::to_json(p["foo"], s); + } + + { + nlohmann::json o; + std::string s = "bar"; + + nlohmann::to_json(o["foo"], s); + + // call to_json with a non-null JSON value + nlohmann::to_json(o["foo"], s); + } + } } From 149ded856faaa740101bef2b5b079a6c2e134292 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 12:46:48 +0200 Subject: [PATCH 50/58] :recycle: simplify destroy() function for primitive types --- include/nlohmann/json.hpp | 74 ++++++++++++++++---------------- single_include/nlohmann/json.hpp | 74 ++++++++++++++++---------------- 2 files changed, 76 insertions(+), 72 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index a337c1c69..65d2201db 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1133,51 +1133,53 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void destroy(value_t t) noexcept { - // flatten the current json_value to a heap-allocated stack - std::vector stack; + if (t == value_t::array || t == value_t::object) + { + // flatten the current json_value to a heap-allocated stack + std::vector stack; - // move the top-level items to stack - if (t == value_t::array) - { - stack.reserve(array->size()); - std::move(array->begin(), array->end(), std::back_inserter(stack)); - } - else if (t == value_t::object) - { - stack.reserve(object->size()); - for (auto&& it : *object) + // move the top-level items to stack + if (t == value_t::array) { - stack.push_back(std::move(it.second)); + stack.reserve(array->size()); + std::move(array->begin(), array->end(), std::back_inserter(stack)); } - } - - while (!stack.empty()) - { - // move the last item to local variable to be processed - basic_json current_item(std::move(stack.back())); - stack.pop_back(); - - // if current_item is array/object, move - // its children to the stack to be processed later - if (current_item.is_array()) + else { - std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), - std::back_inserter(stack)); - - current_item.m_value.array->clear(); - } - else if (current_item.is_object()) - { - for (auto&& it : *current_item.m_value.object) + stack.reserve(object->size()); + for (auto&& it : *object) { stack.push_back(std::move(it.second)); } - - current_item.m_value.object->clear(); } - // it's now safe that current_item get destructed - // since it doesn't have any children + while (!stack.empty()) + { + // move the last item to local variable to be processed + basic_json current_item(std::move(stack.back())); + stack.pop_back(); + + // if current_item is array/object, move + // its children to the stack to be processed later + if (current_item.is_array()) + { + std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); + + current_item.m_value.array->clear(); + } + else if (current_item.is_object()) + { + for (auto&& it : *current_item.m_value.object) + { + stack.push_back(std::move(it.second)); + } + + current_item.m_value.object->clear(); + } + + // it's now safe that current_item get destructed + // since it doesn't have any children + } } switch (t) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 429964dd7..7ed12f19a 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -18168,51 +18168,53 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void destroy(value_t t) noexcept { - // flatten the current json_value to a heap-allocated stack - std::vector stack; + if (t == value_t::array || t == value_t::object) + { + // flatten the current json_value to a heap-allocated stack + std::vector stack; - // move the top-level items to stack - if (t == value_t::array) - { - stack.reserve(array->size()); - std::move(array->begin(), array->end(), std::back_inserter(stack)); - } - else if (t == value_t::object) - { - stack.reserve(object->size()); - for (auto&& it : *object) + // move the top-level items to stack + if (t == value_t::array) { - stack.push_back(std::move(it.second)); + stack.reserve(array->size()); + std::move(array->begin(), array->end(), std::back_inserter(stack)); } - } - - while (!stack.empty()) - { - // move the last item to local variable to be processed - basic_json current_item(std::move(stack.back())); - stack.pop_back(); - - // if current_item is array/object, move - // its children to the stack to be processed later - if (current_item.is_array()) + else { - std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), - std::back_inserter(stack)); - - current_item.m_value.array->clear(); - } - else if (current_item.is_object()) - { - for (auto&& it : *current_item.m_value.object) + stack.reserve(object->size()); + for (auto&& it : *object) { stack.push_back(std::move(it.second)); } - - current_item.m_value.object->clear(); } - // it's now safe that current_item get destructed - // since it doesn't have any children + while (!stack.empty()) + { + // move the last item to local variable to be processed + basic_json current_item(std::move(stack.back())); + stack.pop_back(); + + // if current_item is array/object, move + // its children to the stack to be processed later + if (current_item.is_array()) + { + std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); + + current_item.m_value.array->clear(); + } + else if (current_item.is_object()) + { + for (auto&& it : *current_item.m_value.object) + { + stack.push_back(std::move(it.second)); + } + + current_item.m_value.object->clear(); + } + + // it's now safe that current_item get destructed + // since it doesn't have any children + } } switch (t) From 6cbdc839947fd9e13e61424f6e895751d1acf7a2 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 12:47:15 +0200 Subject: [PATCH 51/58] :bug: fix leak for strings --- include/nlohmann/detail/conversions/to_json.hpp | 1 + single_include/nlohmann/json.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 9d7f55fc9..1b002ddb5 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -236,6 +236,7 @@ template::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { + j.m_value.destroy(j.m_type); external_constructor::construct(j, s); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 7ed12f19a..601b28a06 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4694,6 +4694,7 @@ template::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { + j.m_value.destroy(j.m_type); external_constructor::construct(j, s); } From c1298e69a6b308bbe3f0db41415f24c8cdbc5a73 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 12:52:17 +0200 Subject: [PATCH 52/58] :bug: fix leak for strings --- include/nlohmann/detail/conversions/to_json.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 1b002ddb5..960d92e20 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -236,7 +236,10 @@ template::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { - j.m_value.destroy(j.m_type); + if (!j.is_null()) + { + j = nullptr; + } external_constructor::construct(j, s); } From 0f8666ecdc98341c09b0a99205728e30b5bec49f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 13:03:20 +0200 Subject: [PATCH 53/58] :bug: fix leak for strings --- single_include/nlohmann/json.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 601b28a06..219a6a480 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4694,7 +4694,10 @@ template::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { - j.m_value.destroy(j.m_type); + if (!j.is_null()) + { + j = nullptr; + } external_constructor::construct(j, s); } From 0011cd1b72db57cd5691bda2d5adf410417cb099 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 13:12:21 +0200 Subject: [PATCH 54/58] :bug: fix leak for strings --- include/nlohmann/detail/conversions/to_json.hpp | 2 +- single_include/nlohmann/json.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 960d92e20..a0ca4211a 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -238,7 +238,7 @@ void to_json(BasicJsonType& j, const CompatibleString& s) { if (!j.is_null()) { - j = nullptr; + j = BasicJsonType(); } external_constructor::construct(j, s); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 219a6a480..4bdadd871 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4696,7 +4696,7 @@ void to_json(BasicJsonType& j, const CompatibleString& s) { if (!j.is_null()) { - j = nullptr; + j = BasicJsonType(); } external_constructor::construct(j, s); } From f6863e062cb4ef313e9a9d2e0dd4afa57195ff71 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 20:32:37 +0200 Subject: [PATCH 55/58] :bug: fix leak for all types --- .../nlohmann/detail/conversions/to_json.hpp | 22 +++++++++++++++---- single_include/nlohmann/json.hpp | 22 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index a0ca4211a..8d1ac30c5 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -30,6 +30,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept { + j.m_value.destroy(j.m_type); j.m_type = value_t::boolean; j.m_value = b; j.assert_invariant(); @@ -42,6 +43,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) { + j.m_value.destroy(j.m_type); j.m_type = value_t::string; j.m_value = s; j.assert_invariant(); @@ -50,6 +52,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) { + j.m_value.destroy(j.m_type); j.m_type = value_t::string; j.m_value = std::move(s); j.assert_invariant(); @@ -60,6 +63,7 @@ struct external_constructor int > = 0 > static void construct(BasicJsonType& j, const CompatibleStringType& str) { + j.m_value.destroy(j.m_type); j.m_type = value_t::string; j.m_value.string = j.template create(str); j.assert_invariant(); @@ -72,6 +76,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) { + j.m_value.destroy(j.m_type); j.m_type = value_t::binary; j.m_value = typename BasicJsonType::binary_t(b); j.assert_invariant(); @@ -80,6 +85,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) { + j.m_value.destroy(j.m_type); j.m_type = value_t::binary; j.m_value = typename BasicJsonType::binary_t(std::move(b));; j.assert_invariant(); @@ -92,6 +98,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept { + j.m_value.destroy(j.m_type); j.m_type = value_t::number_float; j.m_value = val; j.assert_invariant(); @@ -104,6 +111,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept { + j.m_value.destroy(j.m_type); j.m_type = value_t::number_unsigned; j.m_value = val; j.assert_invariant(); @@ -116,6 +124,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept { + j.m_value.destroy(j.m_type); j.m_type = value_t::number_integer; j.m_value = val; j.assert_invariant(); @@ -128,6 +137,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) { + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value = arr; j.set_parents(); @@ -137,6 +147,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value = std::move(arr); j.set_parents(); @@ -150,6 +161,8 @@ struct external_constructor { using std::begin; using std::end; + + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value.array = j.template create(begin(arr), end(arr)); j.set_parents(); @@ -159,6 +172,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const std::vector& arr) { + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value = value_t::array; j.m_value.array->reserve(arr.size()); @@ -174,6 +188,7 @@ struct external_constructor enable_if_t::value, int> = 0> static void construct(BasicJsonType& j, const std::valarray& arr) { + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value = value_t::array; j.m_value.array->resize(arr.size()); @@ -192,6 +207,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) { + j.m_value.destroy(j.m_type); j.m_type = value_t::object; j.m_value = obj; j.set_parents(); @@ -201,6 +217,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { + j.m_value.destroy(j.m_type); j.m_type = value_t::object; j.m_value = std::move(obj); j.set_parents(); @@ -214,6 +231,7 @@ struct external_constructor using std::begin; using std::end; + j.m_value.destroy(j.m_type); j.m_type = value_t::object; j.m_value.object = j.template create(begin(obj), end(obj)); j.set_parents(); @@ -236,10 +254,6 @@ template::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { - if (!j.is_null()) - { - j = BasicJsonType(); - } external_constructor::construct(j, s); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 4bdadd871..32cacdbcd 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4488,6 +4488,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept { + j.m_value.destroy(j.m_type); j.m_type = value_t::boolean; j.m_value = b; j.assert_invariant(); @@ -4500,6 +4501,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) { + j.m_value.destroy(j.m_type); j.m_type = value_t::string; j.m_value = s; j.assert_invariant(); @@ -4508,6 +4510,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) { + j.m_value.destroy(j.m_type); j.m_type = value_t::string; j.m_value = std::move(s); j.assert_invariant(); @@ -4518,6 +4521,7 @@ struct external_constructor int > = 0 > static void construct(BasicJsonType& j, const CompatibleStringType& str) { + j.m_value.destroy(j.m_type); j.m_type = value_t::string; j.m_value.string = j.template create(str); j.assert_invariant(); @@ -4530,6 +4534,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) { + j.m_value.destroy(j.m_type); j.m_type = value_t::binary; j.m_value = typename BasicJsonType::binary_t(b); j.assert_invariant(); @@ -4538,6 +4543,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) { + j.m_value.destroy(j.m_type); j.m_type = value_t::binary; j.m_value = typename BasicJsonType::binary_t(std::move(b));; j.assert_invariant(); @@ -4550,6 +4556,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept { + j.m_value.destroy(j.m_type); j.m_type = value_t::number_float; j.m_value = val; j.assert_invariant(); @@ -4562,6 +4569,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept { + j.m_value.destroy(j.m_type); j.m_type = value_t::number_unsigned; j.m_value = val; j.assert_invariant(); @@ -4574,6 +4582,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept { + j.m_value.destroy(j.m_type); j.m_type = value_t::number_integer; j.m_value = val; j.assert_invariant(); @@ -4586,6 +4595,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) { + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value = arr; j.set_parents(); @@ -4595,6 +4605,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value = std::move(arr); j.set_parents(); @@ -4608,6 +4619,8 @@ struct external_constructor { using std::begin; using std::end; + + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value.array = j.template create(begin(arr), end(arr)); j.set_parents(); @@ -4617,6 +4630,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const std::vector& arr) { + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value = value_t::array; j.m_value.array->reserve(arr.size()); @@ -4632,6 +4646,7 @@ struct external_constructor enable_if_t::value, int> = 0> static void construct(BasicJsonType& j, const std::valarray& arr) { + j.m_value.destroy(j.m_type); j.m_type = value_t::array; j.m_value = value_t::array; j.m_value.array->resize(arr.size()); @@ -4650,6 +4665,7 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) { + j.m_value.destroy(j.m_type); j.m_type = value_t::object; j.m_value = obj; j.set_parents(); @@ -4659,6 +4675,7 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { + j.m_value.destroy(j.m_type); j.m_type = value_t::object; j.m_value = std::move(obj); j.set_parents(); @@ -4672,6 +4689,7 @@ struct external_constructor using std::begin; using std::end; + j.m_value.destroy(j.m_type); j.m_type = value_t::object; j.m_value.object = j.template create(begin(obj), end(obj)); j.set_parents(); @@ -4694,10 +4712,6 @@ template::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { - if (!j.is_null()) - { - j = BasicJsonType(); - } external_constructor::construct(j, s); } From ecaac22656ee4088be4bee505862bee2799e0788 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 20:34:50 +0200 Subject: [PATCH 56/58] :bulb: add comment to describe j.m_value.destroy(j.m_type) calls --- include/nlohmann/detail/conversions/to_json.hpp | 7 +++++++ single_include/nlohmann/json.hpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 8d1ac30c5..08462a4bb 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -22,6 +22,13 @@ namespace detail // constructors // ////////////////// +/* + * Note all external_constructor<>::construct functions need to call + * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an + * allocated value (e.g., a string). See bug issue + * https://github.com/nlohmann/json/issues/2865 for more information. + */ + template struct external_constructor; template<> diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 32cacdbcd..dedd3d4a5 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4480,6 +4480,13 @@ namespace detail // constructors // ////////////////// +/* + * Note all external_constructor<>::construct functions need to call + * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an + * allocated value (e.g., a string). See bug issue + * https://github.com/nlohmann/json/issues/2865 for more information. + */ + template struct external_constructor; template<> From 3e4723a49fbfc502e4790d8a87021f57bb4cf999 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 21:49:09 +0200 Subject: [PATCH 57/58] :hammer: remove noexcept annotation --- include/nlohmann/json.hpp | 2 +- single_include/nlohmann/json.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 65d2201db..94c004227 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1131,7 +1131,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec binary = create(std::move(value)); } - void destroy(value_t t) noexcept + void destroy(value_t t) { if (t == value_t::array || t == value_t::object) { diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index dedd3d4a5..8130c6aa8 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -18191,7 +18191,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec binary = create(std::move(value)); } - void destroy(value_t t) noexcept + void destroy(value_t t) { if (t == value_t::array || t == value_t::object) { From 953dcfb61131452b36a8a59bf24102605037b0ca Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 15 Jul 2021 22:00:16 +0200 Subject: [PATCH 58/58] :rotating_light: fix warning #2572 --- single_include/nlohmann/json.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 429964dd7..c0de5acac 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -16459,7 +16459,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(3, '\0'); + std::string sn(9, '\0'); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn, BasicJsonType())); @@ -16554,7 +16554,7 @@ class serializer { case error_handler_t::strict: { - std::string sn(3, '\0'); + std::string sn(9, '\0'); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn, BasicJsonType()));