Loading README.md +1 −1 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ include(FetchContent) FetchContent_Declare(json GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohman_json GIT_TAG v2.0.7) GIT_TAG v2.0.8) FetchContent_GetProperties(json) if(NOT json_POPULATED) Loading include/nlohmann/json.hpp +177 −76 Original line number Diff line number Diff line /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ | | |__ | | | | | | version 2.0.7 | | |__ | | | | | | version 2.0.8 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. Loading Loading @@ -29,32 +29,32 @@ SOFTWARE. #ifndef NLOHMANN_JSON_HPP #define NLOHMANN_JSON_HPP #include <algorithm> #include <array> #include <cassert> #include <cctype> #include <ciso646> #include <cmath> #include <cstddef> #include <cstdint> #include <cstdlib> #include <cstring> #include <functional> #include <initializer_list> #include <iomanip> #include <iostream> #include <iterator> #include <limits> #include <locale> #include <map> #include <memory> #include <numeric> #include <sstream> #include <stdexcept> #include <string> #include <type_traits> #include <utility> #include <vector> #include <algorithm> // all_of, for_each, transform #include <array> // array #include <cassert> // assert #include <cctype> // isdigit #include <ciso646> // and, not, or #include <cmath> // isfinite, signbit #include <cstddef> // nullptr_t, ptrdiff_t, size_t #include <cstdint> // int64_t, uint64_t #include <cstdlib> // strtod, strtof, strtold, strtoul #include <cstring> // strlen #include <functional> // function, hash, less #include <initializer_list> // initializer_list #include <iomanip> // setw #include <iostream> // istream, ostream #include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator #include <limits> // numeric_limits #include <locale> // locale #include <map> // map #include <memory> // addressof, allocator, allocator_traits, unique_ptr #include <numeric> // accumulate #include <sstream> // stringstream #include <stdexcept> // domain_error, invalid_argument, out_of_range #include <string> // getline, stoi, string, to_string #include <type_traits> // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference #include <utility> // declval, forward, make_pair, move, pair, swap #include <vector> // vector // exclude unsupported compilers #if defined(__clang__) Loading Loading @@ -122,26 +122,6 @@ struct has_mapped_type std::is_integral<decltype(detect(std::declval<T>()))>::value; }; /*! @brief helper class to create locales with decimal point This struct is used a default locale during the JSON serialization. JSON requires the decimal point to be `.`, so this function overloads the `do_decimal_point()` function to return `.`. This function is called by float-to-string conversions to retrieve the decimal separator between integer and fractional parts. @sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315 @since version 2.0.0 */ struct DecimalSeparator : std::numpunct<char> { char do_decimal_point() const { return '.'; } }; } /*! Loading Loading @@ -2201,8 +2181,7 @@ class basic_json { std::stringstream ss; // fix locale problems const static std::locale loc(std::locale(), new DecimalSeparator); ss.imbue(loc); ss.imbue(std::locale::classic()); // 6, 15 or 16 digits of precision allows round-trip IEEE 754 // string->float->string, string->double->string or string->long Loading Loading @@ -5053,6 +5032,102 @@ class basic_json return *this; } /*! @brief add an object to an array Creates a JSON value from the passed parameters @a args to the end of the JSON value. If the function is called on a JSON null value, an empty array is created before appending the value created from @a args. @param[in] args arguments to forward to a constructor of @ref basic_json @tparam Args compatible types to create a @ref basic_json object @throw std::domain_error when called on a type other than JSON array or null; example: `"cannot use emplace_back() with number"` @complexity Amortized constant. @liveexample{The example shows how `push_back()` can be used to add elements to a JSON array. Note how the `null` value was silently converted to a JSON array.,emplace_back} @since version 2.0.8 */ template<class... Args> void emplace_back(Args&& ... args) { // emplace_back only works for null objects or arrays if (not(is_null() or is_array())) { throw std::domain_error("cannot use emplace_back() with " + type_name()); } // transform null object into an array if (is_null()) { m_type = value_t::array; m_value = value_t::array; assert_invariant(); } // add element to array (perfect forwarding) m_value.array->emplace_back(std::forward<Args>(args)...); } /*! @brief add an object to an object if key does not exist Inserts a new element into a JSON object constructed in-place with the given @a args if there is no element with the key in the container. If the function is called on a JSON null value, an empty object is created before appending the value created from @a args. @param[in] args arguments to forward to a constructor of @ref basic_json @tparam Args compatible types to create a @ref basic_json object @return a pair consisting of an iterator to the inserted element, or the already-existing element if no insertion happened, and a bool denoting whether the insertion took place. @throw std::domain_error when called on a type other than JSON object or null; example: `"cannot use emplace() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @liveexample{The example shows how `emplace()` can be used to add elements to a JSON object. Note how the `null` value was silently converted to a JSON object. Further note how no value is added if there was already one value stored with the same key.,emplace} @since version 2.0.8 */ template<class... Args> std::pair<iterator, bool> emplace(Args&& ... args) { // emplace only works for null objects or arrays if (not(is_null() or is_object())) { throw std::domain_error("cannot use emplace() with " + type_name()); } // transform null object into an object if (is_null()) { m_type = value_t::object; m_value = value_t::object; assert_invariant(); } // add element to array (perfect forwarding) auto res = m_value.object->emplace(std::forward<Args>(args)...); // create result iterator and set iterator to the result of emplace auto it = begin(); it.m_it.object_iterator = res.first; // return pair of iterator and boolean return {it, res.second}; } /*! @brief inserts element Loading Loading @@ -5829,7 +5904,7 @@ class basic_json o.width(0); // fix locale problems const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator)); const auto old_locale = o.imbue(std::locale::classic()); // set precision // 6, 15 or 16 digits of precision allows round-trip IEEE 754 Loading Loading @@ -7618,6 +7693,12 @@ class basic_json explicit lexer(std::istream& s) : m_stream(&s), m_line_buffer() { // immediately abort if stream is erroneous if (s.fail()) { throw std::invalid_argument("stream error: " + std::string(strerror(errno))); } // fill buffer fill_line_buffer(); Loading Loading @@ -8740,8 +8821,22 @@ basic_json_parser_66: */ void fill_line_buffer(size_t n = 0) { // if line buffer is used, m_content points to its data assert(m_line_buffer.empty() or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data())); // if line buffer is used, m_limit is set past the end of its data assert(m_line_buffer.empty() or m_limit == m_content + m_line_buffer.size()); // pointer relationships assert(m_content <= m_start); assert(m_start <= m_cursor); assert(m_cursor <= m_limit); assert(m_marker == nullptr or m_marker <= m_limit); // number of processed characters (p) const auto offset_start = m_start - m_content; const size_t num_processed_chars = static_cast<size_t>(m_start - m_content); // offset for m_marker wrt. to m_start const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; // number of unprocessed characters (u) Loading @@ -8750,35 +8845,34 @@ basic_json_parser_66: // no stream is used or end of file is reached if (m_stream == nullptr or m_stream->eof()) { // skip this part if we are already using the line buffer if (m_start != reinterpret_cast<const lexer_char_t*>(m_line_buffer.data())) { // copy unprocessed characters to line buffer m_line_buffer.clear(); for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor) { m_line_buffer.append(1, static_cast<const char>(*m_cursor)); } } // m_start may or may not be pointing into m_line_buffer at // this point. We trust the standand library to do the right // thing. See http://stackoverflow.com/q/28142011/266378 m_line_buffer.assign(m_start, m_limit); // append n characters to make sure that there is sufficient // space between m_cursor and m_limit m_line_buffer.append(1, '\x00'); if (n > 0) { m_line_buffer.append(n - 1, '\x01'); } } else { // delete processed characters from line buffer m_line_buffer.erase(0, static_cast<size_t>(offset_start)); m_line_buffer.erase(0, num_processed_chars); // read next line from input stream std::string line; std::getline(*m_stream, line, '\n'); m_line_buffer_tmp.clear(); std::getline(*m_stream, m_line_buffer_tmp, '\n'); // add line with newline symbol to the line buffer m_line_buffer += line + "\n"; m_line_buffer += m_line_buffer_tmp; m_line_buffer.push_back('\n'); } // set pointers m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.c_str()); m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()); assert(m_content != nullptr); m_start = m_content; m_marker = m_start + offset_marker; Loading Loading @@ -8861,9 +8955,20 @@ basic_json_parser_66: // iterate the result between the quotes for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i) { // process escaped characters if (*i == '\\') // find next escape character auto e = std::find(i, m_cursor - 1, '\\'); if (e != i) { // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705 for (auto k = i; k < e; k++) { result.push_back(static_cast<typename string_t::value_type>(*k)); } i = e - 1; // -1 because of ++i } else { // processing escaped character // read next character ++i; Loading Loading @@ -8950,12 +9055,6 @@ basic_json_parser_66: } } } else { // all other characters are just copied to the end of the // string result.append(1, static_cast<typename string_t::value_type>(*i)); } } return result; Loading Loading @@ -9139,6 +9238,8 @@ basic_json_parser_66: std::istream* m_stream = nullptr; /// line buffer buffer for m_stream string_t m_line_buffer {}; /// used for filling m_line_buffer string_t m_line_buffer_tmp {}; /// the buffer pointer const lexer_char_t* m_content = nullptr; /// pointer to the beginning of the current symbol Loading @@ -9164,7 +9265,7 @@ basic_json_parser_66: /// a parser reading from a string literal parser(const char* buff, const parser_callback_t cb = nullptr) : callback(cb), m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff)) m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff)) {} /// a parser reading from an input stream Loading Loading
README.md +1 −1 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ include(FetchContent) FetchContent_Declare(json GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohman_json GIT_TAG v2.0.7) GIT_TAG v2.0.8) FetchContent_GetProperties(json) if(NOT json_POPULATED) Loading
include/nlohmann/json.hpp +177 −76 Original line number Diff line number Diff line /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ | | |__ | | | | | | version 2.0.7 | | |__ | | | | | | version 2.0.8 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. Loading Loading @@ -29,32 +29,32 @@ SOFTWARE. #ifndef NLOHMANN_JSON_HPP #define NLOHMANN_JSON_HPP #include <algorithm> #include <array> #include <cassert> #include <cctype> #include <ciso646> #include <cmath> #include <cstddef> #include <cstdint> #include <cstdlib> #include <cstring> #include <functional> #include <initializer_list> #include <iomanip> #include <iostream> #include <iterator> #include <limits> #include <locale> #include <map> #include <memory> #include <numeric> #include <sstream> #include <stdexcept> #include <string> #include <type_traits> #include <utility> #include <vector> #include <algorithm> // all_of, for_each, transform #include <array> // array #include <cassert> // assert #include <cctype> // isdigit #include <ciso646> // and, not, or #include <cmath> // isfinite, signbit #include <cstddef> // nullptr_t, ptrdiff_t, size_t #include <cstdint> // int64_t, uint64_t #include <cstdlib> // strtod, strtof, strtold, strtoul #include <cstring> // strlen #include <functional> // function, hash, less #include <initializer_list> // initializer_list #include <iomanip> // setw #include <iostream> // istream, ostream #include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator #include <limits> // numeric_limits #include <locale> // locale #include <map> // map #include <memory> // addressof, allocator, allocator_traits, unique_ptr #include <numeric> // accumulate #include <sstream> // stringstream #include <stdexcept> // domain_error, invalid_argument, out_of_range #include <string> // getline, stoi, string, to_string #include <type_traits> // add_pointer, enable_if, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_floating_point, is_integral, is_nothrow_move_assignable, std::is_nothrow_move_constructible, std::is_pointer, std::is_reference, std::is_same, remove_const, remove_pointer, remove_reference #include <utility> // declval, forward, make_pair, move, pair, swap #include <vector> // vector // exclude unsupported compilers #if defined(__clang__) Loading Loading @@ -122,26 +122,6 @@ struct has_mapped_type std::is_integral<decltype(detect(std::declval<T>()))>::value; }; /*! @brief helper class to create locales with decimal point This struct is used a default locale during the JSON serialization. JSON requires the decimal point to be `.`, so this function overloads the `do_decimal_point()` function to return `.`. This function is called by float-to-string conversions to retrieve the decimal separator between integer and fractional parts. @sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315 @since version 2.0.0 */ struct DecimalSeparator : std::numpunct<char> { char do_decimal_point() const { return '.'; } }; } /*! Loading Loading @@ -2201,8 +2181,7 @@ class basic_json { std::stringstream ss; // fix locale problems const static std::locale loc(std::locale(), new DecimalSeparator); ss.imbue(loc); ss.imbue(std::locale::classic()); // 6, 15 or 16 digits of precision allows round-trip IEEE 754 // string->float->string, string->double->string or string->long Loading Loading @@ -5053,6 +5032,102 @@ class basic_json return *this; } /*! @brief add an object to an array Creates a JSON value from the passed parameters @a args to the end of the JSON value. If the function is called on a JSON null value, an empty array is created before appending the value created from @a args. @param[in] args arguments to forward to a constructor of @ref basic_json @tparam Args compatible types to create a @ref basic_json object @throw std::domain_error when called on a type other than JSON array or null; example: `"cannot use emplace_back() with number"` @complexity Amortized constant. @liveexample{The example shows how `push_back()` can be used to add elements to a JSON array. Note how the `null` value was silently converted to a JSON array.,emplace_back} @since version 2.0.8 */ template<class... Args> void emplace_back(Args&& ... args) { // emplace_back only works for null objects or arrays if (not(is_null() or is_array())) { throw std::domain_error("cannot use emplace_back() with " + type_name()); } // transform null object into an array if (is_null()) { m_type = value_t::array; m_value = value_t::array; assert_invariant(); } // add element to array (perfect forwarding) m_value.array->emplace_back(std::forward<Args>(args)...); } /*! @brief add an object to an object if key does not exist Inserts a new element into a JSON object constructed in-place with the given @a args if there is no element with the key in the container. If the function is called on a JSON null value, an empty object is created before appending the value created from @a args. @param[in] args arguments to forward to a constructor of @ref basic_json @tparam Args compatible types to create a @ref basic_json object @return a pair consisting of an iterator to the inserted element, or the already-existing element if no insertion happened, and a bool denoting whether the insertion took place. @throw std::domain_error when called on a type other than JSON object or null; example: `"cannot use emplace() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @liveexample{The example shows how `emplace()` can be used to add elements to a JSON object. Note how the `null` value was silently converted to a JSON object. Further note how no value is added if there was already one value stored with the same key.,emplace} @since version 2.0.8 */ template<class... Args> std::pair<iterator, bool> emplace(Args&& ... args) { // emplace only works for null objects or arrays if (not(is_null() or is_object())) { throw std::domain_error("cannot use emplace() with " + type_name()); } // transform null object into an object if (is_null()) { m_type = value_t::object; m_value = value_t::object; assert_invariant(); } // add element to array (perfect forwarding) auto res = m_value.object->emplace(std::forward<Args>(args)...); // create result iterator and set iterator to the result of emplace auto it = begin(); it.m_it.object_iterator = res.first; // return pair of iterator and boolean return {it, res.second}; } /*! @brief inserts element Loading Loading @@ -5829,7 +5904,7 @@ class basic_json o.width(0); // fix locale problems const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator)); const auto old_locale = o.imbue(std::locale::classic()); // set precision // 6, 15 or 16 digits of precision allows round-trip IEEE 754 Loading Loading @@ -7618,6 +7693,12 @@ class basic_json explicit lexer(std::istream& s) : m_stream(&s), m_line_buffer() { // immediately abort if stream is erroneous if (s.fail()) { throw std::invalid_argument("stream error: " + std::string(strerror(errno))); } // fill buffer fill_line_buffer(); Loading Loading @@ -8740,8 +8821,22 @@ basic_json_parser_66: */ void fill_line_buffer(size_t n = 0) { // if line buffer is used, m_content points to its data assert(m_line_buffer.empty() or m_content == reinterpret_cast<const lexer_char_t*>(m_line_buffer.data())); // if line buffer is used, m_limit is set past the end of its data assert(m_line_buffer.empty() or m_limit == m_content + m_line_buffer.size()); // pointer relationships assert(m_content <= m_start); assert(m_start <= m_cursor); assert(m_cursor <= m_limit); assert(m_marker == nullptr or m_marker <= m_limit); // number of processed characters (p) const auto offset_start = m_start - m_content; const size_t num_processed_chars = static_cast<size_t>(m_start - m_content); // offset for m_marker wrt. to m_start const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; // number of unprocessed characters (u) Loading @@ -8750,35 +8845,34 @@ basic_json_parser_66: // no stream is used or end of file is reached if (m_stream == nullptr or m_stream->eof()) { // skip this part if we are already using the line buffer if (m_start != reinterpret_cast<const lexer_char_t*>(m_line_buffer.data())) { // copy unprocessed characters to line buffer m_line_buffer.clear(); for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor) { m_line_buffer.append(1, static_cast<const char>(*m_cursor)); } } // m_start may or may not be pointing into m_line_buffer at // this point. We trust the standand library to do the right // thing. See http://stackoverflow.com/q/28142011/266378 m_line_buffer.assign(m_start, m_limit); // append n characters to make sure that there is sufficient // space between m_cursor and m_limit m_line_buffer.append(1, '\x00'); if (n > 0) { m_line_buffer.append(n - 1, '\x01'); } } else { // delete processed characters from line buffer m_line_buffer.erase(0, static_cast<size_t>(offset_start)); m_line_buffer.erase(0, num_processed_chars); // read next line from input stream std::string line; std::getline(*m_stream, line, '\n'); m_line_buffer_tmp.clear(); std::getline(*m_stream, m_line_buffer_tmp, '\n'); // add line with newline symbol to the line buffer m_line_buffer += line + "\n"; m_line_buffer += m_line_buffer_tmp; m_line_buffer.push_back('\n'); } // set pointers m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.c_str()); m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.data()); assert(m_content != nullptr); m_start = m_content; m_marker = m_start + offset_marker; Loading Loading @@ -8861,9 +8955,20 @@ basic_json_parser_66: // iterate the result between the quotes for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i) { // process escaped characters if (*i == '\\') // find next escape character auto e = std::find(i, m_cursor - 1, '\\'); if (e != i) { // see https://github.com/nlohmann/json/issues/365#issuecomment-262874705 for (auto k = i; k < e; k++) { result.push_back(static_cast<typename string_t::value_type>(*k)); } i = e - 1; // -1 because of ++i } else { // processing escaped character // read next character ++i; Loading Loading @@ -8950,12 +9055,6 @@ basic_json_parser_66: } } } else { // all other characters are just copied to the end of the // string result.append(1, static_cast<typename string_t::value_type>(*i)); } } return result; Loading Loading @@ -9139,6 +9238,8 @@ basic_json_parser_66: std::istream* m_stream = nullptr; /// line buffer buffer for m_stream string_t m_line_buffer {}; /// used for filling m_line_buffer string_t m_line_buffer_tmp {}; /// the buffer pointer const lexer_char_t* m_content = nullptr; /// pointer to the beginning of the current symbol Loading @@ -9164,7 +9265,7 @@ basic_json_parser_66: /// a parser reading from a string literal parser(const char* buff, const parser_callback_t cb = nullptr) : callback(cb), m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff)) m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff)) {} /// a parser reading from an input stream Loading