Compare commits

..

16 Commits

Author SHA1 Message Date
Niels Lohmann
7ffd3ae400 Merge branch 'develop' of https://github.com/nlohmann/json into feature/optional 2021-01-03 20:15:28 +01:00
Niels Lohmann
384442e8e5 🔥 remove useless line 2021-01-03 20:15:03 +01:00
Niels Lohmann
f1913fe7a9 ♻️ do not include experimental headers 2021-01-03 20:10:43 +01:00
Niels Lohmann
ebb63bd1fa Merge branch 'develop' of https://github.com/nlohmann/json into feature/optional
 Conflicts:
	test/src/unit-conversions.cpp
2020-12-30 18:41:51 +01:00
Niels Lohmann
5e55158d60 Merge branch 'develop' of https://github.com/nlohmann/json into feature/optional
 Conflicts:
	test/src/unit-conversions.cpp
2020-12-21 20:59:41 +01:00
Niels Lohmann
fedf82c904 Merge branch 'develop' of https://github.com/nlohmann/json into feature/optional 2020-08-07 09:37:56 +02:00
Niels Lohmann
b61d563ebe Merge branches 'develop' and 'feature/optional' of https://github.com/nlohmann/json into feature/optional 2020-05-20 19:00:49 +02:00
Niels Lohmann
f25bf312fc 🏁 include right <optional> header 2020-05-17 13:58:09 +02:00
Niels Lohmann
007c6c4bc5 update tests 2020-05-16 19:37:18 +02:00
Niels Lohmann
71c80ccfd8 Merge branches 'develop' and 'feature/optional' of https://github.com/nlohmann/json into feature/optional 2020-05-16 19:31:59 +02:00
Niels Lohmann
6b31375c7c ⚗️ set CXXFLAGS 2019-12-19 12:25:27 +01:00
Niels Lohmann
a2fea87ef6 Merge pull request #1872 from remedi/feature/optional
Use JSON_HAS_CPP_17 only after it has been defined
2019-12-18 10:59:57 +01:00
Markus Palonen
1b846c9d81 Use JSON_HAS_CPP_17 only after it has been defined 2019-12-17 16:25:35 +02:00
Niels Lohmann
713038fa27 💚 overwork tests 2019-11-23 14:40:15 +01:00
Niels Lohmann
1359c56137 🏁 fix <optional> inclusion 2019-11-23 13:29:47 +01:00
Niels Lohmann
df30a0ea07 🚧 conversions for std::optional 2019-11-23 00:21:33 +01:00
17 changed files with 304 additions and 274 deletions

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2013-2021 Niels Lohmann
Copyright (c) 2013-2020 Niels Lohmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -76,7 +76,6 @@ You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nl
- [Stefan Hagen](https://github.com/sthagen)
- [Steve Sperandeo](https://github.com/homer6)
- [Robert Jefe Lindstädt](https://github.com/eljefedelrodeodeljefe)
- [Steve Wagner](https://github.com/ciroque)
Thanks everyone!
@@ -1199,11 +1198,11 @@ auto cbor = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE
## Supported compilers
Though it's 2021 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
Though it's 2020 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
- GCC 4.8 - 11.0 (and possibly later)
- Clang 3.4 - 11.0 (and possibly later)
- Apple Clang 9.1 - 12.3 (and possibly later)
- GCC 4.8 - 10.1 (and possibly later)
- Clang 3.4 - 10.0 (and possibly later)
- Apple Clang 9.1 - 12.0 (and possibly later)
- Intel C++ Compiler 17.0.2 (and possibly later)
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
@@ -1230,37 +1229,37 @@ Please note:
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), [GitHub Actions](https://github.com/nlohmann/json/actions), and [CircleCI](https://circleci.com/gh/nlohmann/json):
| Compiler | Operating System | CI Provider |
|-------------------------------------------------------------------|--------------------|----------------|
| Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.2.1 | macOS 10.14.4 | Travis |
| Apple Clang 11.0.0 (clang-1100.0.33.12); Xcode 11.2.1 | macOS 10.14.6 | Travis |
| Apple Clang 11.0.3 (clang-1103.0.32.59); Xcode 11.4.1 | macOS 10.15.4 | GitHub Actions |
| Apple Clang 12.0.0 (clang-1200.0.22.7); Xcode 11.4.1 | macOS 10.15.5 | Travis |
| Clang 3.5.0 (3.5.0-4ubuntu2\~trusty2) | Ubuntu 14.04.5 LTS | Travis |
| Clang 3.6.2 (3.6.2-svn240577-1\~exp1) | Ubuntu 14.04.5 LTS | Travis |
| Clang 3.7.1 (3.7.1-svn253571-1\~exp1) | Ubuntu 14.04.5 LTS | Travis |
| Clang 3.8.0 (3.8.0-2ubuntu3\~trusty5) | Ubuntu 14.04.5 LTS | Travis |
| Clang 3.9.1 (3.9.1-4ubuntu3\~14.04.3) | Ubuntu 14.04.5 LTS | Travis |
| Clang 4.0.1 (4.0.1-svn305264-1\~exp1) | Ubuntu 14.04.5 LTS | Travis |
| Clang 5.0.2 (version 5.0.2-svn328729-1\~exp1\~20180509123505.100) | Ubuntu 14.04.5 LTS | Travis |
| Clang 6.0.1 (6.0.1-svn334776-1\~exp1\~20190309042707.121) | Ubuntu 14.04.5 LTS | Travis |
| Clang 7.1.0 (7.1.0-svn353565-1\~exp1\~20190419134007.64) | Ubuntu 14.04.5 LTS | Travis |
| Clang 7.5.0 (Ubuntu 7.5.0-3ubuntu1\~18.04) | Ubuntu 18.04.4 LTS | Travis |
| Clang 9.0.0 (x86_64-pc-windows-msvc) | Windows-10.0.17763 | GitHub Actions |
| Clang 10.0.0 (x86_64-pc-windows-msvc) | Windows-10.0.17763 | GitHub Actions |
| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu8\~14.04.2) | Ubuntu 14.04.5 LTS | Travis |
| GCC 4.9.4 (Ubuntu 4.9.4-2ubuntu1\~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
| GCC 5.5.0 (Ubuntu 5.5.0-12ubuntu1\~14.04) | Ubuntu 14.04.5 LTS | Travis |
| GCC 6.3.0 (Debian 6.3.0-18+deb9u1) | Debian 9 | Circle CI |
| GCC 6.5.0 (Ubuntu 6.5.0-2ubuntu1\~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
| GCC 7.3.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-6.3.9600 | AppVeyor |
| GCC 7.5.0 (Ubuntu 7.5.0-3ubuntu1\~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
| GCC 7.5.0 (Ubuntu 7.5.0-3ubuntu1\~18.04) | Ubuntu 18.04.4 LTS | GitHub Actions |
| GCC 8.4.0 (Ubuntu 8.4.0-1ubuntu1\~14.04) | Ubuntu 14.04.5 LTS | Travis |
| GCC 9.3.0 (Ubuntu 9.3.0-11ubuntu0\~14.04) | Ubuntu 14.04.5 LTS | Travis |
| GCC 10.1.0 (Arch Linux latest) | Arch Linux | Circle CI |
| MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor |
| MSVC 19.16.27035.0 (15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor |
| Compiler | Operating System | CI Provider |
|-----------------------------------------------------------------|--------------------|----------------|
| Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.2.1 | macOS 10.14.4 | Travis |
| Apple Clang 11.0.0 (clang-1100.0.33.12); Xcode 11.2.1 | macOS 10.14.6 | Travis |
| Apple Clang 11.0.3 (clang-1103.0.32.59); Xcode 11.4.1 | macOS 10.15.4 | GitHub Actions |
| Apple Clang 12.0.0 (clang-1200.0.22.7); Xcode 11.4.1 | macOS 10.15.5 | Travis |
| Clang 3.5.0 (3.5.0-4ubuntu2~trusty2) | Ubuntu 14.04.5 LTS | Travis |
| Clang 3.6.2 (3.6.2-svn240577-1~exp1) | Ubuntu 14.04.5 LTS | Travis |
| Clang 3.7.1 (3.7.1-svn253571-1~exp1) | Ubuntu 14.04.5 LTS | Travis |
| Clang 3.8.0 (3.8.0-2ubuntu3~trusty5) | Ubuntu 14.04.5 LTS | Travis |
| Clang 3.9.1 (3.9.1-4ubuntu3~14.04.3) | Ubuntu 14.04.5 LTS | Travis |
| Clang 4.0.1 (4.0.1-svn305264-1~exp1) | Ubuntu 14.04.5 LTS | Travis |
| Clang 5.0.2 (version 5.0.2-svn328729-1~exp1~20180509123505.100) | Ubuntu 14.04.5 LTS | Travis |
| Clang 6.0.1 (6.0.1-svn334776-1~exp1~20190309042707.121) | Ubuntu 14.04.5 LTS | Travis |
| Clang 7.1.0 (7.1.0-svn353565-1~exp1~20190419134007.64) | Ubuntu 14.04.5 LTS | Travis |
| Clang 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) | Ubuntu 18.04.4 LTS | Travis |
| Clang 9.0.0 (x86_64-pc-windows-msvc) | Windows-10.0.17763 | GitHub Actions |
| Clang 10.0.0 (x86_64-pc-windows-msvc) | Windows-10.0.17763 | GitHub Actions |
| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu8~14.04.2) | Ubuntu 14.04.5 LTS | Travis |
| GCC 4.9.4 (Ubuntu 4.9.4-2ubuntu1~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
| GCC 5.5.0 (Ubuntu 5.5.0-12ubuntu1~14.04) | Ubuntu 14.04.5 LTS | Travis |
| GCC 6.3.0 (Debian 6.3.0-18+deb9u1) | Debian 9 | Circle CI |
| GCC 6.5.0 (Ubuntu 6.5.0-2ubuntu1~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
| GCC 7.3.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-6.3.9600 | AppVeyor |
| GCC 7.5.0 (Ubuntu 7.5.0-3ubuntu1~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
| GCC 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) | Ubuntu 18.04.4 LTS | GitHub Actions |
| GCC 8.4.0 (Ubuntu 8.4.0-1ubuntu1~14.04) | Ubuntu 14.04.5 LTS | Travis |
| GCC 9.3.0 (Ubuntu 9.3.0-11ubuntu0~14.04) | Ubuntu 14.04.5 LTS | Travis |
| GCC 10.1.0 (Arch Linux latest) | Arch Linux | Circle CI |
| MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor |
| MSVC 19.16.27035.0 (15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor |
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) | Windows-10.0.17763 | AppVeyor |
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) | Windows-10.0.17763 | GitHub Actions |
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) with ClangCL 10.0.0 | Windows-10.0.17763 | GitHub Actions |
@@ -1271,7 +1270,7 @@ The following compilers are currently used in continuous integration at [Travis]
The class is licensed under the [MIT License](http://opensource.org/licenses/MIT):
Copyright &copy; 2013-2021 [Niels Lohmann](https://nlohmann.me)
Copyright &copy; 2013-2019 [Niels Lohmann](http://nlohmann.me)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -1528,7 +1527,6 @@ I deeply appreciate the help of the following people.
- [KonanM](https://github.com/KonanM) proposed an implementation for the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
- [Guillaume Racicot](https://github.com/gracicot) implemented `string_view` support and allowed C++20 support.
- [Alex Reinking](https://github.com/alexreinking) improved CMake support for `FetchContent`.
- [Hannes Domani](https://github.com/ssbssa) provided a GDB pretty printer.
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.

View File

@@ -2,9 +2,9 @@
"compiler": {
"c++": "201103",
"family": "clang",
"version": "12.0.0 (clang-1200.0.32.28)"
"version": "12.0.0 (clang-1200.0.22.19)"
},
"copyright": "(C) 2013-2021 Niels Lohmann",
"copyright": "(C) 2013-2020 Niels Lohmann",
"name": "JSON for Modern C++",
"platform": "apple",
"url": "https://github.com/nlohmann/json",

View File

@@ -327,7 +327,7 @@ Note that this table only lists those exceptions thrown due to the type. For ins
</tr>
</table>
@copyright Copyright &copy; 2013-2021 Niels Lohmann. The code is licensed under the [MIT License](http://opensource.org/licenses/MIT).
@copyright Copyright &copy; 2013-2020 Niels Lohmann. The code is licensed under the [MIT License](http://opensource.org/licenses/MIT).
@author [Niels Lohmann](http://nlohmann.me)
@see https://github.com/nlohmann/json to download the source code

View File

@@ -32,6 +32,21 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
n = nullptr;
}
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType, typename T>
void from_json(const BasicJsonType& j, std::optional<T>& opt)
{
if (j.is_null())
{
opt = std::nullopt;
}
else
{
opt = j.template get<T>();
}
}
#endif
// overloads for basic_json template parameters
template < typename BasicJsonType, typename ArithmeticType,
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&

View File

@@ -490,49 +490,51 @@ inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
return 10;
}
// LCOV_EXCL_STOP
if (n >= 100000000)
else if (n >= 100000000)
{
pow10 = 100000000;
return 9;
}
if (n >= 10000000)
else if (n >= 10000000)
{
pow10 = 10000000;
return 8;
}
if (n >= 1000000)
else if (n >= 1000000)
{
pow10 = 1000000;
return 7;
}
if (n >= 100000)
else if (n >= 100000)
{
pow10 = 100000;
return 6;
}
if (n >= 10000)
else if (n >= 10000)
{
pow10 = 10000;
return 5;
}
if (n >= 1000)
else if (n >= 1000)
{
pow10 = 1000;
return 4;
}
if (n >= 100)
else if (n >= 100)
{
pow10 = 100;
return 3;
}
if (n >= 10)
else if (n >= 10)
{
pow10 = 10;
return 2;
}
pow10 = 1;
return 1;
else
{
pow10 = 1;
return 1;
}
}
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,

View File

@@ -219,6 +219,22 @@ struct external_constructor<value_t::object>
// to_json //
/////////////
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType, typename T,
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
void to_json(BasicJsonType& j, const std::optional<T>& opt)
{
if (opt.has_value())
{
j = *opt;
}
else
{
j = nullptr;
}
}
#endif
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
void to_json(BasicJsonType& j, T b) noexcept

View File

@@ -135,8 +135,10 @@ class iterator_input_adapter
std::advance(current, 1);
return result;
}
return std::char_traits<char_type>::eof();
else
{
return std::char_traits<char_type>::eof();
}
}
private:

View File

@@ -393,62 +393,62 @@ class parser
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_array, "array")));
}
// states.back() is false -> object
// comma -> next value
if (get_token() == token_type::value_separator)
else // object
{
// parse key
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
// comma -> next value
if (get_token() == token_type::value_separator)
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::value_string, "object key")));
// parse key
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::value_string, "object key")));
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
{
return false;
}
// parse separator (:)
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::name_separator, "object separator")));
}
// parse values
get_token();
continue;
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
// closing }
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
{
return false;
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
{
return false;
}
// We are done with this object. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
JSON_ASSERT(!states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
// parse separator (:)
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::name_separator, "object separator")));
}
// parse values
get_token();
continue;
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_object, "object")));
}
// closing }
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
{
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
{
return false;
}
// We are done with this object. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
JSON_ASSERT(!states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_object, "object")));
}
}

View File

@@ -39,7 +39,7 @@ template<typename IteratorType> class iteration_proxy_value
/// a string representation of the array index
mutable string_type array_index_str = "0";
/// an empty string (to return a reference for primitive values)
const string_type empty_str;
const string_type empty_str = "";
public:
explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}

View File

@@ -31,6 +31,10 @@
#define JSON_HAS_CPP_14
#endif
#ifdef JSON_HAS_CPP_17
#include <optional>
#endif
// disable float-equal warnings on GCC/clang
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#pragma GCC diagnostic push

View File

@@ -351,7 +351,7 @@ class basic_json
{
basic_json result;
result["copyright"] = "(C) 2013-2021 Niels Lohmann";
result["copyright"] = "(C) 2013-2020 Niels Lohmann";
result["name"] = "JSON for Modern C++";
result["url"] = "https://github.com/nlohmann/json";
result["version"]["string"] =

View File

@@ -2108,6 +2108,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP
#define JSON_HAS_CPP_14
#endif
#ifdef JSON_HAS_CPP_17
#include <optional>
#endif
// disable float-equal warnings on GCC/clang
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#pragma GCC diagnostic push
@@ -3518,6 +3522,21 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
n = nullptr;
}
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType, typename T>
void from_json(const BasicJsonType& j, std::optional<T>& opt)
{
if (j.is_null())
{
opt = std::nullopt;
}
else
{
opt = j.template get<T>();
}
}
#endif
// overloads for basic_json template parameters
template < typename BasicJsonType, typename ArithmeticType,
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
@@ -3944,7 +3963,7 @@ template<typename IteratorType> class iteration_proxy_value
/// a string representation of the array index
mutable string_type array_index_str = "0";
/// an empty string (to return a reference for primitive values)
const string_type empty_str;
const string_type empty_str = "";
public:
explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
@@ -4294,6 +4313,22 @@ struct external_constructor<value_t::object>
// to_json //
/////////////
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType, typename T,
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
void to_json(BasicJsonType& j, const std::optional<T>& opt)
{
if (opt.has_value())
{
j = *opt;
}
else
{
j = nullptr;
}
}
#endif
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
void to_json(BasicJsonType& j, T b) noexcept
@@ -4947,8 +4982,10 @@ class iterator_input_adapter
std::advance(current, 1);
return result;
}
return std::char_traits<char_type>::eof();
else
{
return std::char_traits<char_type>::eof();
}
}
private:
@@ -10616,62 +10653,62 @@ class parser
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_array, "array")));
}
// states.back() is false -> object
// comma -> next value
if (get_token() == token_type::value_separator)
else // object
{
// parse key
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
// comma -> next value
if (get_token() == token_type::value_separator)
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::value_string, "object key")));
// parse key
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::value_string, "object key")));
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
{
return false;
}
// parse separator (:)
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::name_separator, "object separator")));
}
// parse values
get_token();
continue;
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
// closing }
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
{
return false;
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
{
return false;
}
// We are done with this object. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
JSON_ASSERT(!states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
// parse separator (:)
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::name_separator, "object separator")));
}
// parse values
get_token();
continue;
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_object, "object")));
}
// closing }
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
{
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
{
return false;
}
// We are done with this object. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
JSON_ASSERT(!states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_object, "object")));
}
}
@@ -14946,49 +14983,51 @@ inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
return 10;
}
// LCOV_EXCL_STOP
if (n >= 100000000)
else if (n >= 100000000)
{
pow10 = 100000000;
return 9;
}
if (n >= 10000000)
else if (n >= 10000000)
{
pow10 = 10000000;
return 8;
}
if (n >= 1000000)
else if (n >= 1000000)
{
pow10 = 1000000;
return 7;
}
if (n >= 100000)
else if (n >= 100000)
{
pow10 = 100000;
return 6;
}
if (n >= 10000)
else if (n >= 10000)
{
pow10 = 10000;
return 5;
}
if (n >= 1000)
else if (n >= 1000)
{
pow10 = 1000;
return 4;
}
if (n >= 100)
else if (n >= 100)
{
pow10 = 100;
return 3;
}
if (n >= 10)
else if (n >= 10)
{
pow10 = 10;
return 2;
}
pow10 = 1;
return 1;
else
{
pow10 = 1;
return 1;
}
}
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
@@ -16971,7 +17010,7 @@ class basic_json
{
basic_json result;
result["copyright"] = "(C) 2013-2021 Niels Lohmann";
result["copyright"] = "(C) 2013-2020 Niels Lohmann";
result["name"] = "JSON for Modern C++";
result["url"] = "https://github.com/nlohmann/json";
result["version"]["string"] =

View File

@@ -1703,6 +1703,65 @@ TEST_CASE("JSON to enum mapping")
}
}
#ifdef JSON_HAS_CPP_17
TEST_CASE("std::optional")
{
SECTION("null")
{
json j_null;
std::optional<std::string> opt_null;
CHECK(json(opt_null) == j_null);
CHECK(std::optional<std::string>(j_null) == std::nullopt);
}
SECTION("string")
{
json j_string = "string";
std::optional<std::string> opt_string = "string";
CHECK(json(opt_string) == j_string);
CHECK(std::optional<std::string>(j_string) == opt_string);
}
SECTION("bool")
{
json j_bool = true;
std::optional<bool> opt_bool = true;
CHECK(json(opt_bool) == j_bool);
CHECK(std::optional<bool>(j_bool) == opt_bool);
}
SECTION("number")
{
json j_number = 1;
std::optional<int> opt_int = 1;
CHECK(json(opt_int) == j_number);
CHECK(std::optional<int>(j_number) == opt_int);
}
SECTION("array")
{
json j_array = {1, 2, nullptr};
std::vector<std::optional<int>> opt_array = {{1, 2, std::nullopt}};
CHECK(json(opt_array) == j_array);
CHECK(std::vector<std::optional<int>>(j_array) == opt_array);
}
SECTION("object")
{
json j_object = {{"one", 1}, {"two", 2}, {"zero", nullptr}};
std::map<std::string, std::optional<int>> opt_object {{"one", 1}, {"two", 2}, {"zero", std::nullopt}};
CHECK(json(opt_object) == j_object);
CHECK(std::map<std::string, std::optional<int>>(j_object) == opt_object);
}
}
#endif
#ifdef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_17
#endif

View File

@@ -39,7 +39,7 @@ TEST_CASE("version information")
json j = json::meta();
CHECK(j["name"] == "JSON for Modern C++");
CHECK(j["copyright"] == "(C) 2013-2021 Niels Lohmann");
CHECK(j["copyright"] == "(C) 2013-2020 Niels Lohmann");
CHECK(j["url"] == "https://github.com/nlohmann/json");
CHECK(j["version"] == json(
{

View File

@@ -1,77 +0,0 @@
# GDB Pretty Printer
File [nlohmann-json.py](nlohmann-json.py) contains a pretty printer for GDB for JSON values of this library. It was originally published as [Gist](https://gist.github.com/ssbssa/60da5339c6e6036b2afce17de06050ea#file-nlohmann-json-py) by [Hannes Domani](https://github.com/ssbssa).
## How to use
- Add line
```
source /path/to/nlohmann-json.py
```
to `~/.gdbinit`. Note you must replace `/path/to` with whatever path you stored file `nlohmann-json.py`.
- In GDB, debug as usual. When you want to pretty-print a JSON value `var`, type
```
p -pretty on -array on -- var
```
The result should look like
```
$1 = std::map with 5 elements = {
["Baptiste"] = std::map with 1 element = {
["first"] = "second"
},
["Emmanuel"] = std::vector of length 3, capacity 3 = {
3,
"25",
0.5
},
["Jean"] = 0.7,
["Zorg"] = std::map with 8 elements = {
["array"] = std::vector of length 3, capacity 3 = {
1,
0,
2
},
["awesome_str"] = "bleh",
["bool"] = true,
["flex"] = 0.2,
["float"] = 5.22,
["int"] = 5,
["nested"] = std::map with 1 element = {
["bar"] = "barz"
},
["trap "] = "you fell"
},
["empty"] = nlohmann::detail::value_t::null
}
```
Tested with GDB 9.2. See [#1952](https://github.com/nlohmann/json/issues/1952) for more information. Please post questions there.
## Copyright
MIT License
Copyright (C) 2020 [Hannes Domani](https://github.com/ssbssa)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,28 +0,0 @@
import gdb
import re
class JsonValuePrinter:
"Print a json-value"
def __init__(self, val):
self.val = val
def to_string(self):
if self.val.type.strip_typedefs().code == gdb.TYPE_CODE_FLT:
return ("%.6f" % float(self.val)).rstrip("0")
return self.val
def json_lookup_function(val):
if re.search("^nlohmann::basic_json<.*>$", val.type.strip_typedefs().name):
t = str(val['m_type'])
if t.startswith("nlohmann::detail::value_t::"):
try:
union_val = val['m_value'][t[27:]]
if union_val.type.code == gdb.TYPE_CODE_PTR:
return gdb.default_visualizer(union_val.dereference())
else:
return JsonValuePrinter(union_val)
except:
return JsonValuePrinter(val['m_type'])
gdb.pretty_printers.append(json_lookup_function)