Compare commits

..
Author SHA1 Message Date
Niels Lohmann ef97a360c8 Document why the digit-count fast path is safe regardless of number_unsigned_t/number_integer_t width
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-05 21:36:16 +02:00
Niels Lohmann 7b648c7dc4 Skip integer conversion in accept()/SAX validation when the value is unused
lexer::scan_number() always converted every numeric token with
strtoull()/strtoll() before returning, even though accept() (and any
consumer using json_sax_acceptor) immediately discards the converted
value. For value_unsigned/value_integer tokens whose digit count
already guarantees the value fits into 64 bits, the conversion cannot
change the accept/reject decision (such tokens are always finite and
unconditionally accepted), so scan_number() can skip strtoull()/
strtoll() entirely in that case when the caller signals it does not
need the value. Numbers with more digits keep using the exact,
unmodified conversion path, so overflow reclassification to
value_float (and the finiteness check on it) is unaffected.

parse() and value_float handling are completely unchanged.

Fixes #5411

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-05 20:59:51 +02:00
12 changed files with 293 additions and 552 deletions
+1 -1
View File
@@ -241,7 +241,7 @@ update_hedley:
rm -f include/nlohmann/thirdparty/hedley/hedley.hpp include/nlohmann/thirdparty/hedley/hedley_undef.hpp
curl https://raw.githubusercontent.com/nemequ/hedley/master/hedley.h -o include/nlohmann/thirdparty/hedley/hedley.hpp
$(SED) -i 's/HEDLEY_/JSON_HEDLEY_/g' include/nlohmann/thirdparty/hedley/hedley.hpp
grep -oE "#[[:blank:]]*define[[:blank:]]+JSON_HEDLEY_[A-Za-z0-9_]+" include/nlohmann/thirdparty/hedley/hedley.hpp | awk '{print $$NF}' | grep -v "__" | sort -u | $(SED) 's/^/#undef /' > include/nlohmann/thirdparty/hedley/hedley_undef.hpp
grep "[[:blank:]]*#[[:blank:]]*undef" include/nlohmann/thirdparty/hedley/hedley.hpp | grep -v "__" | sort | uniq | $(SED) 's/ //g' | $(SED) 's/undef/undef /g' > include/nlohmann/thirdparty/hedley/hedley_undef.hpp
$(SED) -i '1s/^/#pragma once\n\n/' include/nlohmann/thirdparty/hedley/hedley.hpp
$(SED) -i '1s/^/#pragma once\n\n/' include/nlohmann/thirdparty/hedley/hedley_undef.hpp
$(MAKE) amalgamate
@@ -1074,9 +1074,9 @@ char* to_chars(char* first, const char* last, FloatType value)
*first++ = '-';
}
JSON_HEDLEY_DIAGNOSTIC_PUSH
#ifdef __GNUC__
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if (value == 0) // +-0
{
@@ -1086,7 +1086,9 @@ char* to_chars(char* first, const char* last, FloatType value)
*first++ = '0';
return first;
}
JSON_HEDLEY_DIAGNOSTIC_POP
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
+5 -3
View File
@@ -32,9 +32,9 @@
// functions to. As a result, we suppress this warning here to avoid client
// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
// for a discussion.
JSON_HEDLEY_DIAGNOSTIC_PUSH
#if defined(__clang__)
JSON_HEDLEY_PRAGMA(clang diagnostic ignored "-Wweak-vtables")
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
NLOHMANN_JSON_NAMESPACE_BEGIN
@@ -286,4 +286,6 @@ class other_error : public exception
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
JSON_HEDLEY_DIAGNOSTIC_POP
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
+61 -1
View File
@@ -149,10 +149,11 @@ class lexer : public lexer_base<BasicJsonType>
public:
using token_type = typename lexer_base<BasicJsonType>::token_type;
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false, bool discard_number_values_ = false) noexcept
: ia(std::move(adapter))
, ignore_comments(ignore_comments_)
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
, discard_number_values(discard_number_values_)
{}
// deleted because of pointer members
@@ -1279,6 +1280,58 @@ scan_number_done:
// we are done scanning a number)
unget();
// If the caller does not need the converted value (only whether the
// input is syntactically valid; see json_sax_acceptor/accept()), an
// unsigned/integer token can be reported without calling
// strtoull()/strtoll() at all, *provided* we can already tell from
// the digit count alone that the conversion cannot overflow 64 bits.
// Such tokens are always finite and are accepted unconditionally by
// the parser regardless of their actual value (parser::sax_parse_internal()
// never checks finiteness for value_unsigned/value_integer), so the
// classification below is all that is needed.
//
// A decimal number with up to 18 digits is always representable in
// both std::uint64_t and std::int64_t (18 nines is ~1e18, well below
// both UINT64_MAX ~1.8e19 and INT64_MAX ~9.2e18), so strtoull()/strtoll()
// could not have set errno to ERANGE for it. Numbers with more digits
// (rare in practice) fall through to the exact code below, unchanged,
// so their handling -- including reclassification to value_float when
// the value overflows 64 bits, and rejection when it is not even
// finite as a double -- is bit-for-bit identical to before this
// optimization.
//
// Note this reasons about std::uint64_t/std::int64_t, not about
// number_unsigned_t/number_integer_t (BasicJsonType's own, possibly
// narrower, template parameters -- e.g. std::uint32_t). That is fine
// *only* because discard_number_values is exclusively set by
// accept() (see json.hpp), and accept() always parses through the
// library's own json_sax_acceptor -- never a user-supplied SAX
// consumer -- whose number_unsigned()/number_integer()/number_float()
// callbacks unconditionally discard their argument and return true.
// So for every caller that can reach this branch, neither the token
// classification below nor the eventual (possibly narrowed, and on
// this fast path left stale/unset) value_unsigned/value_integer is
// ever consulted -- an unsigned/integer token is accepted outright,
// and even a >18-digit token that this fast path deliberately falls
// through for is, once reclassified to value_float, still finite
// (and thus accepted) for any digit count that fits in number_unsigned_t
// or number_integer_t regardless of that type's width. If this
// function is ever taught to run with discard_number_values true for
// a caller that *does* read the converted value, this reasoning (and
// the fast path below) would need to be revisited.
if (discard_number_values)
{
constexpr std::size_t safe_digit_count = 18;
if (number_type == token_type::value_unsigned && token_buffer.size() <= safe_digit_count)
{
return token_type::value_unsigned;
}
if (number_type == token_type::value_integer && token_buffer.size() - 1 <= safe_digit_count)
{
return token_type::value_integer;
}
}
char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
errno = 0;
@@ -1754,6 +1807,13 @@ scan_number_done:
const char_int_type decimal_point_char = '.';
/// the position of the decimal point in the input
std::size_t decimal_point_position = std::string::npos;
/// whether the caller (e.g. accept()/json_sax_acceptor) only needs the
/// token classification and never looks at the converted numeric value;
/// when set, scan_number() may skip strtoull()/strtoll() for
/// value_unsigned/value_integer tokens whose digit count guarantees they
/// fit into 64 bits (see scan_number())
const bool discard_number_values = false;
};
} // namespace detail
+3 -2
View File
@@ -72,9 +72,10 @@ class parser
parser_callback_t<BasicJsonType> cb = nullptr,
const bool allow_exceptions_ = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas_ = false)
const bool ignore_trailing_commas_ = false,
const bool discard_number_values_ = false)
: callback(std::move(cb))
, m_lexer(std::move(adapter), ignore_comments)
, m_lexer(std::move(adapter), ignore_comments, discard_number_values_)
, allow_exceptions(allow_exceptions_)
, ignore_trailing_commas(ignore_trailing_commas_)
{
@@ -18,7 +18,6 @@
#endif
#include <nlohmann/detail/abi_macros.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/string_utils.hpp>
#include <nlohmann/detail/value_t.hpp>
@@ -207,10 +206,10 @@ NLOHMANN_JSON_NAMESPACE_END
namespace std
{
// Fix: https://github.com/nlohmann/json/issues/1401
JSON_HEDLEY_DIAGNOSTIC_PUSH
#if defined(__clang__)
JSON_HEDLEY_PRAGMA(clang diagnostic ignored "-Wmismatched-tags")
// Fix: https://github.com/nlohmann/json/issues/1401
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-tags"
#endif
template<typename IteratorType>
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
@@ -224,7 +223,9 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
get<N>(std::declval <
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
};
JSON_HEDLEY_DIAGNOSTIC_POP
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} // namespace std
@@ -1849,9 +1849,9 @@ class binary_writer
void write_compact_float(const number_float_t n, detail::input_format_t format)
{
JSON_HEDLEY_DIAGNOSTIC_PUSH
#ifdef __GNUC__
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if (!std::isfinite(n) || ((static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
@@ -1869,7 +1869,9 @@ class binary_writer
: get_msgpack_float_prefix(n));
write_number(n);
}
JSON_HEDLEY_DIAGNOSTIC_POP
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
public:
+16 -11
View File
@@ -164,11 +164,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::parser_callback_t<basic_json>cb = nullptr,
const bool allow_exceptions = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false
const bool ignore_trailing_commas = false,
const bool discard_number_values = false
)
{
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas, discard_number_values);
}
private:
@@ -3769,13 +3770,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
bool operator==(const_reference rhs) const noexcept
{
JSON_HEDLEY_DIAGNOSTIC_PUSH
#ifdef __GNUC__
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
const_reference lhs = *this;
JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
JSON_HEDLEY_DIAGNOSTIC_POP
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
/// @brief comparison: equal
@@ -3860,12 +3863,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
{
JSON_HEDLEY_DIAGNOSTIC_PUSH
#ifdef __GNUC__
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
JSON_HEDLEY_DIAGNOSTIC_POP
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
/// @brief comparison: equal
@@ -4129,7 +4134,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true);
}
/// @brief check if the input is valid JSON (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -4140,7 +4145,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true);
}
JSON_HEDLEY_WARN_UNUSED_RESULT
@@ -4149,7 +4154,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true);
}
/// @brief generate SAX events
+1 -4
View File
@@ -17,7 +17,7 @@
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
#undef JSON_HEDLEY_CLANG_HAS_WARNING
@@ -108,10 +108,7 @@
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
#undef JSON_HEDLEY_PGI_VERSION
#undef JSON_HEDLEY_PGI_VERSION_CHECK
#undef JSON_HEDLEY_PRAGMA
#undef JSON_HEDLEY_PREDICT
#undef JSON_HEDLEY_PREDICT_FALSE
#undef JSON_HEDLEY_PREDICT_TRUE
#undef JSON_HEDLEY_PRINTF_FORMAT
#undef JSON_HEDLEY_PRIVATE
#undef JSON_HEDLEY_PUBLIC
+102 -33
View File
@@ -4944,9 +4944,9 @@ NLOHMANN_JSON_NAMESPACE_END
// functions to. As a result, we suppress this warning here to avoid client
// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
// for a discussion.
JSON_HEDLEY_DIAGNOSTIC_PUSH
#if defined(__clang__)
JSON_HEDLEY_PRAGMA(clang diagnostic ignored "-Wweak-vtables")
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
NLOHMANN_JSON_NAMESPACE_BEGIN
@@ -5198,7 +5198,9 @@ class other_error : public exception
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
JSON_HEDLEY_DIAGNOSTIC_POP
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
// #include <nlohmann/detail/macro_scope.hpp>
@@ -5973,8 +5975,6 @@ NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/abi_macros.hpp>
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/string_utils.hpp>
@@ -6204,10 +6204,10 @@ NLOHMANN_JSON_NAMESPACE_END
namespace std
{
// Fix: https://github.com/nlohmann/json/issues/1401
JSON_HEDLEY_DIAGNOSTIC_PUSH
#if defined(__clang__)
JSON_HEDLEY_PRAGMA(clang diagnostic ignored "-Wmismatched-tags")
// Fix: https://github.com/nlohmann/json/issues/1401
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-tags"
#endif
template<typename IteratorType>
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
@@ -6221,7 +6221,9 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
get<N>(std::declval <
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
};
JSON_HEDLEY_DIAGNOSTIC_POP
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} // namespace std
@@ -7930,10 +7932,11 @@ class lexer : public lexer_base<BasicJsonType>
public:
using token_type = typename lexer_base<BasicJsonType>::token_type;
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false, bool discard_number_values_ = false) noexcept
: ia(std::move(adapter))
, ignore_comments(ignore_comments_)
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
, discard_number_values(discard_number_values_)
{}
// deleted because of pointer members
@@ -9060,6 +9063,58 @@ scan_number_done:
// we are done scanning a number)
unget();
// If the caller does not need the converted value (only whether the
// input is syntactically valid; see json_sax_acceptor/accept()), an
// unsigned/integer token can be reported without calling
// strtoull()/strtoll() at all, *provided* we can already tell from
// the digit count alone that the conversion cannot overflow 64 bits.
// Such tokens are always finite and are accepted unconditionally by
// the parser regardless of their actual value (parser::sax_parse_internal()
// never checks finiteness for value_unsigned/value_integer), so the
// classification below is all that is needed.
//
// A decimal number with up to 18 digits is always representable in
// both std::uint64_t and std::int64_t (18 nines is ~1e18, well below
// both UINT64_MAX ~1.8e19 and INT64_MAX ~9.2e18), so strtoull()/strtoll()
// could not have set errno to ERANGE for it. Numbers with more digits
// (rare in practice) fall through to the exact code below, unchanged,
// so their handling -- including reclassification to value_float when
// the value overflows 64 bits, and rejection when it is not even
// finite as a double -- is bit-for-bit identical to before this
// optimization.
//
// Note this reasons about std::uint64_t/std::int64_t, not about
// number_unsigned_t/number_integer_t (BasicJsonType's own, possibly
// narrower, template parameters -- e.g. std::uint32_t). That is fine
// *only* because discard_number_values is exclusively set by
// accept() (see json.hpp), and accept() always parses through the
// library's own json_sax_acceptor -- never a user-supplied SAX
// consumer -- whose number_unsigned()/number_integer()/number_float()
// callbacks unconditionally discard their argument and return true.
// So for every caller that can reach this branch, neither the token
// classification below nor the eventual (possibly narrowed, and on
// this fast path left stale/unset) value_unsigned/value_integer is
// ever consulted -- an unsigned/integer token is accepted outright,
// and even a >18-digit token that this fast path deliberately falls
// through for is, once reclassified to value_float, still finite
// (and thus accepted) for any digit count that fits in number_unsigned_t
// or number_integer_t regardless of that type's width. If this
// function is ever taught to run with discard_number_values true for
// a caller that *does* read the converted value, this reasoning (and
// the fast path below) would need to be revisited.
if (discard_number_values)
{
constexpr std::size_t safe_digit_count = 18;
if (number_type == token_type::value_unsigned && token_buffer.size() <= safe_digit_count)
{
return token_type::value_unsigned;
}
if (number_type == token_type::value_integer && token_buffer.size() - 1 <= safe_digit_count)
{
return token_type::value_integer;
}
}
char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
errno = 0;
@@ -9535,6 +9590,13 @@ scan_number_done:
const char_int_type decimal_point_char = '.';
/// the position of the decimal point in the input
std::size_t decimal_point_position = std::string::npos;
/// whether the caller (e.g. accept()/json_sax_acceptor) only needs the
/// token classification and never looks at the converted numeric value;
/// when set, scan_number() may skip strtoull()/strtoll() for
/// value_unsigned/value_integer tokens whose digit count guarantees they
/// fit into 64 bits (see scan_number())
const bool discard_number_values = false;
};
} // namespace detail
@@ -14041,9 +14103,10 @@ class parser
parser_callback_t<BasicJsonType> cb = nullptr,
const bool allow_exceptions_ = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas_ = false)
const bool ignore_trailing_commas_ = false,
const bool discard_number_values_ = false)
: callback(std::move(cb))
, m_lexer(std::move(adapter), ignore_comments)
, m_lexer(std::move(adapter), ignore_comments, discard_number_values_)
, allow_exceptions(allow_exceptions_)
, ignore_trailing_commas(ignore_trailing_commas_)
{
@@ -18855,9 +18918,9 @@ class binary_writer
void write_compact_float(const number_float_t n, detail::input_format_t format)
{
JSON_HEDLEY_DIAGNOSTIC_PUSH
#ifdef __GNUC__
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if (!std::isfinite(n) || ((static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
@@ -18875,7 +18938,9 @@ class binary_writer
: get_msgpack_float_prefix(n));
write_number(n);
}
JSON_HEDLEY_DIAGNOSTIC_POP
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
public:
@@ -20048,9 +20113,9 @@ char* to_chars(char* first, const char* last, FloatType value)
*first++ = '-';
}
JSON_HEDLEY_DIAGNOSTIC_PUSH
#ifdef __GNUC__
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if (value == 0) // +-0
{
@@ -20060,7 +20125,9 @@ char* to_chars(char* first, const char* last, FloatType value)
*first++ = '0';
return first;
}
JSON_HEDLEY_DIAGNOSTIC_POP
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
@@ -21586,11 +21653,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::parser_callback_t<basic_json>cb = nullptr,
const bool allow_exceptions = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false
const bool ignore_trailing_commas = false,
const bool discard_number_values = false
)
{
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas, discard_number_values);
}
private:
@@ -25191,13 +25259,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
bool operator==(const_reference rhs) const noexcept
{
JSON_HEDLEY_DIAGNOSTIC_PUSH
#ifdef __GNUC__
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
const_reference lhs = *this;
JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
JSON_HEDLEY_DIAGNOSTIC_POP
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
/// @brief comparison: equal
@@ -25282,12 +25352,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
{
JSON_HEDLEY_DIAGNOSTIC_PUSH
#ifdef __GNUC__
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
JSON_HEDLEY_DIAGNOSTIC_POP
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
/// @brief comparison: equal
@@ -25551,7 +25623,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true);
}
/// @brief check if the input is valid JSON (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -25562,7 +25634,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true);
}
JSON_HEDLEY_WARN_UNUSED_RESULT
@@ -25571,7 +25643,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true);
}
/// @brief generate SAX events
@@ -26955,7 +27027,7 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
#undef JSON_HEDLEY_CLANG_HAS_WARNING
@@ -27046,10 +27118,7 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
#undef JSON_HEDLEY_PGI_VERSION
#undef JSON_HEDLEY_PGI_VERSION_CHECK
#undef JSON_HEDLEY_PRAGMA
#undef JSON_HEDLEY_PREDICT
#undef JSON_HEDLEY_PREDICT_FALSE
#undef JSON_HEDLEY_PREDICT_TRUE
#undef JSON_HEDLEY_PRINTF_FORMAT
#undef JSON_HEDLEY_PRIVATE
#undef JSON_HEDLEY_PUBLIC
+88
View File
@@ -930,6 +930,94 @@ TEST_CASE("parser class")
CHECK(accept_helper("+1") == false);
CHECK(accept_helper("+0") == false);
}
SECTION("issue #5411 - skip conversion when accept() does not need the numeric value")
{
// lexer::scan_number() may skip strtoull()/strtoll() for
// value_unsigned/value_integer tokens when the caller (e.g.
// json::accept()) does not need the converted value, as long
// as the digit count alone guarantees no 64-bit overflow (see
// the "safe_digit_count" fast path in scan_number()). This
// differential test checks that json::accept() (which enables
// the fast path) and json::parse() (which never does) always
// agree, over a corpus that exercises both the fast path
// (<=18 digits) and the untouched, exact fallback path (>=19
// digits) -- including reclassification of huge digit-only
// integers to a (possibly non-finite) floating-point value.
const std::vector<std::pair<std::string, bool>> cases =
{
// normal small/large integers, both signs
{"0", true}, {"1", true}, {"-1", true}, {"42", true}, {"-42", true},
{"123456789", true}, {"-123456789", true},
// digit-count boundary around the 18-digit safe cutoff (both signs)
{std::string(17, '9'), true},
{std::string(18, '9'), true},
{std::string(19, '9'), true},
{std::string(20, '9'), true},
{"-" + std::string(17, '9'), true},
{"-" + std::string(18, '9'), true},
{"-" + std::string(19, '9'), true},
{"-" + std::string(20, '9'), true},
// 64-bit boundaries
{"9223372036854775807", true}, // INT64_MAX
{"-9223372036854775808", true}, // INT64_MIN
{"18446744073709551615", true}, // UINT64_MAX
{"18446744073709551616", true}, // UINT64_MAX + 1 (overflows uint64_t, finite double)
// the 28-digit example from the issue: overflows uint64_t
// but is finite as a double, so the scanner reclassifies
// it to value_float and it is accepted
{"9999999999999999999999999999", true},
// huge digit-only integers that overflow even a double -> rejected
{std::string(309, '9'), false},
{std::string(400, '9'), false},
{"1" + std::string(400, '0'), false},
// 1e999 / 1e400 style overflow -> rejected
{"1e999", false},
{"1e400", false},
{"-1e999", false},
{"1E999", false},
// values straddling DBL_MAX
{"1.7976931348623157e308", true}, // <= DBL_MAX, finite
{"1.7976931348623159e308", false}, // > DBL_MAX, overflows to inf
// a mix of other valid/invalid numeric syntax
{"3.14159", true},
{"-0.0", true},
{"1.0e10", true},
{"01", false},
{"-", false},
{"1.", false},
{"1e", false},
{"+1", false},
};
for (const auto& c : cases)
{
const std::string& number = c.first;
const bool expected = c.second;
CAPTURE(number)
CAPTURE(expected)
// accept() takes the fast path (skips conversion when possible)
CHECK(json::accept(number) == expected);
// parse() always performs the full conversion; it must agree
json j;
CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(number), nullptr, false).parse(true, j));
CHECK(!j.is_discarded() == expected);
// wrap in an array so get_token() is exercised beyond the
// very first (constructor-time) scan as well
const std::string wrapped = "[" + number + "," + number + "]";
CHECK(json::accept(wrapped) == expected);
}
}
}
}
-486
View File
@@ -1,486 +0,0 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// This file makes sure that none of the internal JSON_HEDLEY_* macros (vendored
// from https://nemequ.github.io/hedley/, see
// include/nlohmann/thirdparty/hedley/hedley.hpp) leak into the including
// translation unit. include/nlohmann/detail/macro_unscope.hpp is supposed to
// #undef every JSON_HEDLEY_* macro (via hedley_undef.hpp) once json.hpp has
// been fully processed. See https://github.com/nlohmann/json/issues/5408,
// where JSON_HEDLEY_PRAGMA, JSON_HEDLEY_PREDICT_TRUE, JSON_HEDLEY_PREDICT_FALSE,
// and JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE escaped this cleanup because
// hedley_undef.hpp had no matching #undef for them.
//
// The #ifdef/#error checks below are mechanically derived from the full list
// of macro names in hedley_undef.hpp, so every JSON_HEDLEY_* macro is covered
// -- not just the four that leaked historically.
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
#ifdef JSON_HEDLEY_ALWAYS_INLINE
#error "JSON_HEDLEY_ALWAYS_INLINE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_ARM_VERSION
#error "JSON_HEDLEY_ARM_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_ARM_VERSION_CHECK
#error "JSON_HEDLEY_ARM_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_ARRAY_PARAM
#error "JSON_HEDLEY_ARRAY_PARAM must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_ASSUME
#error "JSON_HEDLEY_ASSUME must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_BEGIN_C_DECLS
#error "JSON_HEDLEY_BEGIN_C_DECLS must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
#error "JSON_HEDLEY_CLANG_HAS_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CLANG_HAS_BUILTIN
#error "JSON_HEDLEY_CLANG_HAS_BUILTIN must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
#error "JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE
#error "JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CLANG_HAS_EXTENSION
#error "JSON_HEDLEY_CLANG_HAS_EXTENSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CLANG_HAS_FEATURE
#error "JSON_HEDLEY_CLANG_HAS_FEATURE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CLANG_HAS_WARNING
#error "JSON_HEDLEY_CLANG_HAS_WARNING must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_COMPCERT_VERSION
#error "JSON_HEDLEY_COMPCERT_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_COMPCERT_VERSION_CHECK
#error "JSON_HEDLEY_COMPCERT_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CONCAT
#error "JSON_HEDLEY_CONCAT must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CONCAT3
#error "JSON_HEDLEY_CONCAT3 must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CONCAT3_EX
#error "JSON_HEDLEY_CONCAT3_EX must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CONCAT_EX
#error "JSON_HEDLEY_CONCAT_EX must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CONST
#error "JSON_HEDLEY_CONST must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CONSTEXPR
#error "JSON_HEDLEY_CONSTEXPR must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CONST_CAST
#error "JSON_HEDLEY_CONST_CAST must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CPP_CAST
#error "JSON_HEDLEY_CPP_CAST must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CRAY_VERSION
#error "JSON_HEDLEY_CRAY_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_CRAY_VERSION_CHECK
#error "JSON_HEDLEY_CRAY_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_C_DECL
#error "JSON_HEDLEY_C_DECL must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DEPRECATED
#error "JSON_HEDLEY_DEPRECATED must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DEPRECATED_FOR
#error "JSON_HEDLEY_DEPRECATED_FOR must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
#error "JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
#error "JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
#error "JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
#error "JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
#error "JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
#error "JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DIAGNOSTIC_POP
#error "JSON_HEDLEY_DIAGNOSTIC_POP must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DIAGNOSTIC_PUSH
#error "JSON_HEDLEY_DIAGNOSTIC_PUSH must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DMC_VERSION
#error "JSON_HEDLEY_DMC_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_DMC_VERSION_CHECK
#error "JSON_HEDLEY_DMC_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_EMPTY_BASES
#error "JSON_HEDLEY_EMPTY_BASES must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_EMSCRIPTEN_VERSION
#error "JSON_HEDLEY_EMSCRIPTEN_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
#error "JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_END_C_DECLS
#error "JSON_HEDLEY_END_C_DECLS must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_FALL_THROUGH
#error "JSON_HEDLEY_FALL_THROUGH must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_FLAGS
#error "JSON_HEDLEY_FLAGS must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_FLAGS_CAST
#error "JSON_HEDLEY_FLAGS_CAST must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
#error "JSON_HEDLEY_GCC_HAS_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_HAS_BUILTIN
#error "JSON_HEDLEY_GCC_HAS_BUILTIN must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
#error "JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
#error "JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_HAS_EXTENSION
#error "JSON_HEDLEY_GCC_HAS_EXTENSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_HAS_FEATURE
#error "JSON_HEDLEY_GCC_HAS_FEATURE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_HAS_WARNING
#error "JSON_HEDLEY_GCC_HAS_WARNING must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
#error "JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_VERSION
#error "JSON_HEDLEY_GCC_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GCC_VERSION_CHECK
#error "JSON_HEDLEY_GCC_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
#error "JSON_HEDLEY_GNUC_HAS_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_HAS_BUILTIN
#error "JSON_HEDLEY_GNUC_HAS_BUILTIN must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
#error "JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
#error "JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_HAS_EXTENSION
#error "JSON_HEDLEY_GNUC_HAS_EXTENSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_HAS_FEATURE
#error "JSON_HEDLEY_GNUC_HAS_FEATURE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_HAS_WARNING
#error "JSON_HEDLEY_GNUC_HAS_WARNING must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_VERSION
#error "JSON_HEDLEY_GNUC_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_GNUC_VERSION_CHECK
#error "JSON_HEDLEY_GNUC_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_HAS_ATTRIBUTE
#error "JSON_HEDLEY_HAS_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_HAS_BUILTIN
#error "JSON_HEDLEY_HAS_BUILTIN must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
#error "JSON_HEDLEY_HAS_CPP_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
#error "JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
#error "JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_HAS_EXTENSION
#error "JSON_HEDLEY_HAS_EXTENSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_HAS_FEATURE
#error "JSON_HEDLEY_HAS_FEATURE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_HAS_WARNING
#error "JSON_HEDLEY_HAS_WARNING must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_IAR_VERSION
#error "JSON_HEDLEY_IAR_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_IAR_VERSION_CHECK
#error "JSON_HEDLEY_IAR_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_IBM_VERSION
#error "JSON_HEDLEY_IBM_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_IBM_VERSION_CHECK
#error "JSON_HEDLEY_IBM_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_IMPORT
#error "JSON_HEDLEY_IMPORT must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_INLINE
#error "JSON_HEDLEY_INLINE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_INTEL_CL_VERSION
#error "JSON_HEDLEY_INTEL_CL_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
#error "JSON_HEDLEY_INTEL_CL_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_INTEL_VERSION
#error "JSON_HEDLEY_INTEL_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_INTEL_VERSION_CHECK
#error "JSON_HEDLEY_INTEL_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_IS_CONSTANT
#error "JSON_HEDLEY_IS_CONSTANT must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_IS_CONSTEXPR_
#error "JSON_HEDLEY_IS_CONSTEXPR_ must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_LIKELY
#error "JSON_HEDLEY_LIKELY must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_MALLOC
#error "JSON_HEDLEY_MALLOC must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_MCST_LCC_VERSION
#error "JSON_HEDLEY_MCST_LCC_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
#error "JSON_HEDLEY_MCST_LCC_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_MESSAGE
#error "JSON_HEDLEY_MESSAGE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_MSVC_VERSION
#error "JSON_HEDLEY_MSVC_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_MSVC_VERSION_CHECK
#error "JSON_HEDLEY_MSVC_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_NEVER_INLINE
#error "JSON_HEDLEY_NEVER_INLINE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_NON_NULL
#error "JSON_HEDLEY_NON_NULL must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_NO_ESCAPE
#error "JSON_HEDLEY_NO_ESCAPE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_NO_RETURN
#error "JSON_HEDLEY_NO_RETURN must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_NO_THROW
#error "JSON_HEDLEY_NO_THROW must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_NULL
#error "JSON_HEDLEY_NULL must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PELLES_VERSION
#error "JSON_HEDLEY_PELLES_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PELLES_VERSION_CHECK
#error "JSON_HEDLEY_PELLES_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PGI_VERSION
#error "JSON_HEDLEY_PGI_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PGI_VERSION_CHECK
#error "JSON_HEDLEY_PGI_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PRAGMA
#error "JSON_HEDLEY_PRAGMA must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PREDICT
#error "JSON_HEDLEY_PREDICT must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PREDICT_FALSE
#error "JSON_HEDLEY_PREDICT_FALSE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PREDICT_TRUE
#error "JSON_HEDLEY_PREDICT_TRUE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PRINTF_FORMAT
#error "JSON_HEDLEY_PRINTF_FORMAT must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PRIVATE
#error "JSON_HEDLEY_PRIVATE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PUBLIC
#error "JSON_HEDLEY_PUBLIC must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_PURE
#error "JSON_HEDLEY_PURE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_REINTERPRET_CAST
#error "JSON_HEDLEY_REINTERPRET_CAST must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_REQUIRE
#error "JSON_HEDLEY_REQUIRE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_REQUIRE_CONSTEXPR
#error "JSON_HEDLEY_REQUIRE_CONSTEXPR must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_REQUIRE_MSG
#error "JSON_HEDLEY_REQUIRE_MSG must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_RESTRICT
#error "JSON_HEDLEY_RESTRICT must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_RETURNS_NON_NULL
#error "JSON_HEDLEY_RETURNS_NON_NULL must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_SENTINEL
#error "JSON_HEDLEY_SENTINEL must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_STATIC_ASSERT
#error "JSON_HEDLEY_STATIC_ASSERT must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_STATIC_CAST
#error "JSON_HEDLEY_STATIC_CAST must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_STRINGIFY
#error "JSON_HEDLEY_STRINGIFY must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_STRINGIFY_EX
#error "JSON_HEDLEY_STRINGIFY_EX must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_SUNPRO_VERSION
#error "JSON_HEDLEY_SUNPRO_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_SUNPRO_VERSION_CHECK
#error "JSON_HEDLEY_SUNPRO_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TINYC_VERSION
#error "JSON_HEDLEY_TINYC_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TINYC_VERSION_CHECK
#error "JSON_HEDLEY_TINYC_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_ARMCL_VERSION
#error "JSON_HEDLEY_TI_ARMCL_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
#error "JSON_HEDLEY_TI_ARMCL_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CL2000_VERSION
#error "JSON_HEDLEY_TI_CL2000_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
#error "JSON_HEDLEY_TI_CL2000_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CL430_VERSION
#error "JSON_HEDLEY_TI_CL430_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CL430_VERSION_CHECK
#error "JSON_HEDLEY_TI_CL430_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CL6X_VERSION
#error "JSON_HEDLEY_TI_CL6X_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
#error "JSON_HEDLEY_TI_CL6X_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CL7X_VERSION
#error "JSON_HEDLEY_TI_CL7X_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
#error "JSON_HEDLEY_TI_CL7X_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CLPRU_VERSION
#error "JSON_HEDLEY_TI_CLPRU_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
#error "JSON_HEDLEY_TI_CLPRU_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_VERSION
#error "JSON_HEDLEY_TI_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_TI_VERSION_CHECK
#error "JSON_HEDLEY_TI_VERSION_CHECK must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_UNAVAILABLE
#error "JSON_HEDLEY_UNAVAILABLE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_UNLIKELY
#error "JSON_HEDLEY_UNLIKELY must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_UNPREDICTABLE
#error "JSON_HEDLEY_UNPREDICTABLE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_UNREACHABLE
#error "JSON_HEDLEY_UNREACHABLE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_UNREACHABLE_RETURN
#error "JSON_HEDLEY_UNREACHABLE_RETURN must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_VERSION
#error "JSON_HEDLEY_VERSION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_VERSION_DECODE_MAJOR
#error "JSON_HEDLEY_VERSION_DECODE_MAJOR must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_VERSION_DECODE_MINOR
#error "JSON_HEDLEY_VERSION_DECODE_MINOR must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_VERSION_DECODE_REVISION
#error "JSON_HEDLEY_VERSION_DECODE_REVISION must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_VERSION_ENCODE
#error "JSON_HEDLEY_VERSION_ENCODE must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_WARNING
#error "JSON_HEDLEY_WARNING must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_WARN_UNUSED_RESULT
#error "JSON_HEDLEY_WARN_UNUSED_RESULT must not remain defined after including json.hpp"
#endif
#ifdef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
#error "JSON_HEDLEY_WARN_UNUSED_RESULT_MSG must not remain defined after including json.hpp"
#endif
TEST_CASE("no JSON_HEDLEY_* macro leaks after including json.hpp")
{
// if this test compiles at all, none of the JSON_HEDLEY_* macros checked
// above remained defined after including <nlohmann/json.hpp>
CHECK(true);
}